diff --git a/changelog/pending/20221209--sdk-nodejs--add-output-jsonstringify-using-json-stringify.yaml b/changelog/pending/20221209--sdk-nodejs--add-output-jsonstringify-using-json-stringify.yaml new file mode 100644 index 000000000000..f7feb962f356 --- /dev/null +++ b/changelog/pending/20221209--sdk-nodejs--add-output-jsonstringify-using-json-stringify.yaml @@ -0,0 +1,4 @@ +changes: +- type: feat + scope: sdk/nodejs + description: Add output jsonStringify using JSON.stringify. diff --git a/sdk/nodejs/output.ts b/sdk/nodejs/output.ts index c73540fb5162..622beac80d44 100644 --- a/sdk/nodejs/output.ts +++ b/sdk/nodejs/output.ts @@ -1013,3 +1013,12 @@ export function interpolate(literals: TemplateStringsArray, ...placeholders: Inp return result; }); } + +/** + * [jsonStringify] Uses JSON.stringify to serialize the given Input value into a JSON string. + */ +export function jsonStringify(obj: Input, replacer?: (this: any, key: string, value: any) => any | (number | string)[], space?: string | number): Output { + return output(obj).apply(o => { + return JSON.stringify(o, replacer, space); + }); +} diff --git a/sdk/nodejs/tests/output.spec.ts b/sdk/nodejs/tests/output.spec.ts index d957c17e7f64..a4f32f35e3f1 100644 --- a/sdk/nodejs/tests/output.spec.ts +++ b/sdk/nodejs/tests/output.spec.ts @@ -15,7 +15,7 @@ /* eslint-disable */ import * as assert from "assert"; -import { Output, all, concat, interpolate, output, unknown, secret, unsecret, isSecret } from "../output"; +import { Output, all, concat, interpolate, output, unknown, secret, unsecret, isSecret, jsonStringify } from "../output"; import { Resource } from "../resource"; import * as runtime from "../runtime"; @@ -138,8 +138,7 @@ describe("output", () => { describe("apply", () => { function createOutput(val: T, isKnown: boolean, isSecret: boolean = false): Output { - return new Output(new Set(), Promise.resolve(val), Promise.resolve(isKnown), Promise.resolve(isSecret), - Promise.resolve(new Set())); + return new Output(new Set(), Promise.resolve(val), Promise.resolve(isKnown), Promise.resolve(isSecret), Promise.resolve(new Set())); } it("can run on known value during preview", async () => { @@ -859,6 +858,72 @@ describe("output", () => { }); }); + describe("jsonStringify", () => { + it ("basic", async () => { + const x = output([0, 1]) + const result = jsonStringify(x) + assert.strictEqual(await result.promise(), "[0,1]"); + assert.strictEqual(await result.isKnown, true); + assert.strictEqual(await result.isSecret, false); + }); + + it ("nested", async () => { + const x = output([output(0), output(1)]) + const result = jsonStringify(x) + assert.strictEqual(await result.promise(), "[0,1]"); + assert.strictEqual(await result.isKnown, true); + assert.strictEqual(await result.isSecret, false); + }); + + it ("nested unknowns", async () => { + const x = output([ + new Output(new Set(), Promise.resolve(undefined), Promise.resolve(false), Promise.resolve(false), Promise.resolve(new Set())), + output(1)]) + const result = jsonStringify(x) + assert.strictEqual(await result.isKnown, false); + assert.strictEqual(await result.isSecret, false); + }); + + it ("nested secret", async () => { + const x = output([ + new Output(new Set(), Promise.resolve(0), Promise.resolve(true), Promise.resolve(true), Promise.resolve(new Set())), + output(1)]) + const result = jsonStringify(x) + assert.strictEqual(await result.promise(), "[0,1]"); + assert.strictEqual(await result.isKnown, true); + assert.strictEqual(await result.isSecret, true); + }); + + it ("with options", async () => { + const x = output([0, 1]) + const result = jsonStringify(x, undefined, " ") + assert.strictEqual(await result.promise(), "[\n 0,\n 1\n]"); + assert.strictEqual(await result.isKnown, true); + assert.strictEqual(await result.isSecret, false); + }); + + it ("nested dependencies", async () => { + // Output's don't actually _look_ at the resources, they just need to keep a collection of them + const mockResource : Resource = {} as any + const mockResources : Resource[] = [mockResource] + + const x = output([ + new Output(new Set(mockResources), Promise.resolve(0), Promise.resolve(true), Promise.resolve(true), Promise.resolve(new Set())), + output(1)]) + const result = jsonStringify(x) + assert.strictEqual(await result.promise(), "[0,1]"); + assert.strictEqual(await result.isKnown, true); + assert.strictEqual(await result.isSecret, true); + if (result.allResources === undefined) { + assert.fail("Output.allResources was undefined") + } + const allResources = await result.allResources(); + // We should have just the one mockResource in this set + assert.strictEqual(allResources.size, 1) + assert.ok(allResources.has(mockResource)) + }); + }); + describe("secret operations", () => { it("ensure secret", async () => { const sec = secret("foo");