diff --git a/docs/docs/04-standard-library/std/node.md b/docs/docs/04-standard-library/std/node.md index 86b8067d357..1b4021f6df3 100644 --- a/docs/docs/04-standard-library/std/node.md +++ b/docs/docs/04-standard-library/std/node.md @@ -640,6 +640,7 @@ prepended to the unique identifier. | node | constructs.Node | The tree node. | | entrypointDir | str | The directory of the entrypoint of the current program. | | isTestEnvironment | bool | `true` if this is a testing environment. | +| parameters | ParameterRegistrar | The application's parameter registrar. | | workdir | str | The `.wing` directory into which you can emit artifacts during preflight. | --- @@ -680,6 +681,18 @@ isTestEnvironment: bool; --- +##### `parameters`Required + +```wing +parameters: ParameterRegistrar; +``` + +- *Type:* ParameterRegistrar + +The application's parameter registrar. + +--- + ##### `workdir`Required ```wing diff --git a/examples/tests/invalid/parameters.test.w b/examples/tests/invalid/parameters.test.w new file mode 100644 index 00000000000..71b00933910 --- /dev/null +++ b/examples/tests/invalid/parameters.test.w @@ -0,0 +1,12 @@ +let app = nodeof(this).app; + +struct MyParams { + foo: str; +} + +app.parameters.addSchema(MyParams.schema()); + +// Error: Parameter validation errors: +// - must have required property 'foo' + +// (hint: make sure to use --values to provide the required parameters file) diff --git a/examples/tests/invalid/struct_from_parameter.test.w b/examples/tests/invalid/struct_from_parameter.test.w new file mode 100644 index 00000000000..908b478fcf4 --- /dev/null +++ b/examples/tests/invalid/struct_from_parameter.test.w @@ -0,0 +1,18 @@ +struct MyParams { + foo: str; + bar: bool; + baz: num; +} + + +let app = nodeof(this).app; + +// Never added the schema to the parameters, so +// technically we never enforced the parameters must have been +// provided + +MyParams.fromJson(app.parameters.read()); +//Error: unable to parse MyParams: +// - instance requires property "bar" +// - instance requires property "baz" +// - instance requires property "foo" \ No newline at end of file diff --git a/examples/tests/valid/parameters/nested/parameters.test.w b/examples/tests/valid/parameters/nested/parameters.test.w new file mode 100644 index 00000000000..618b89979fc --- /dev/null +++ b/examples/tests/valid/parameters/nested/parameters.test.w @@ -0,0 +1,21 @@ +struct Person { + name: str; + age: num; +} + +struct House { + address: str; + residents: Array; +} + +struct MyParams { + houses: Array; +} + +let app = nodeof(this).app; + +let myParams = MyParams.fromJson(app.parameters.read(schema: MyParams.schema())); + +assert(myParams.houses.length == 2); +assert(myParams.houses.at(0).address == "123 Main St"); +assert(myParams.houses.at(0).residents.length == 2); \ No newline at end of file diff --git a/examples/tests/valid/parameters/nested/wing.toml b/examples/tests/valid/parameters/nested/wing.toml new file mode 100644 index 00000000000..155886a5249 --- /dev/null +++ b/examples/tests/valid/parameters/nested/wing.toml @@ -0,0 +1,13 @@ +[[houses]] +address = "123 Main St" +residents = [ + {name = "John Doe", age = 30}, + {name = "Jane Doe", age = 24} +] + +[[houses]] +address = "456 Elm St" +residents = [ + {name = "Tom Smith", age = 45}, + {name = "Sue Smith", age = 40} +] \ No newline at end of file diff --git a/examples/tests/valid/parameters/simple/parameters.test.w b/examples/tests/valid/parameters/simple/parameters.test.w new file mode 100644 index 00000000000..740e1b2ecea --- /dev/null +++ b/examples/tests/valid/parameters/simple/parameters.test.w @@ -0,0 +1,18 @@ +let app = nodeof(this).app; + +struct MyParams { + foo: str?; + meaningOfLife: num; +} + +let myParams = MyParams.fromJson(app.parameters.read(schema: MyParams.schema())); + +if let foo = myParams.foo { + assert(false); // shouldnt happen +} else { + assert(true); +} + +let meaningOfLife = myParams.meaningOfLife; + +assert(meaningOfLife == 42); \ No newline at end of file diff --git a/examples/tests/valid/parameters/simple/wing.toml b/examples/tests/valid/parameters/simple/wing.toml new file mode 100644 index 00000000000..54e0f73088f --- /dev/null +++ b/examples/tests/valid/parameters/simple/wing.toml @@ -0,0 +1 @@ +meaningOfLife = 42 \ No newline at end of file diff --git a/examples/tests/valid/struct_from_json.test.w b/examples/tests/valid/struct_from_json.test.w index cd878088614..0bc62575891 100644 --- a/examples/tests/valid/struct_from_json.test.w +++ b/examples/tests/valid/struct_from_json.test.w @@ -282,7 +282,7 @@ assert(myStruct.m2.val == "10"); let schema = MyStruct.schema(); schema.validate(jMyStruct); // Should not throw exception -let expectedSchema = {"id":"/MyStruct","type":"object","properties":{"m1":{"type":"object","properties":{"val":{"type":"number"}},"required":["val"]},"m2":{"type":"object","properties":{"val":{"type":"string"}},"required":["val"]}},"required":["m1","m2"]}; +let expectedSchema = {"$id":"/MyStruct","type":"object","properties":{"m1":{"type":"object","properties":{"val":{"type":"number"}},"required":["val"]},"m2":{"type":"object","properties":{"val":{"type":"string"}},"required":["val"]}},"required":["m1","m2"]}; assert(schema.asStr() == Json.stringify(expectedSchema)); diff --git a/libs/wingc/src/json_schema_generator.rs b/libs/wingc/src/json_schema_generator.rs index e585879cdbe..ac4560cf7b9 100644 --- a/libs/wingc/src/json_schema_generator.rs +++ b/libs/wingc/src/json_schema_generator.rs @@ -88,7 +88,7 @@ impl JsonSchemaGenerator { let mut code = CodeMaker::default(); code.open("{"); - code.line(format!("id: \"/{}\",", struct_.name)); + code.line(format!("$id: \"/{}\",", struct_.name)); code.line("type: \"object\",".to_string()); code.open("properties: {"); diff --git a/libs/wingsdk/src/core/app.ts b/libs/wingsdk/src/core/app.ts index 38c5e7ff3af..ec9a6f14eca 100644 --- a/libs/wingsdk/src/core/app.ts +++ b/libs/wingsdk/src/core/app.ts @@ -155,7 +155,7 @@ export abstract class App extends Construct implements IApp { * Parameter registrar of composed platforms * @internal */ - protected _platformParameters?: ParameterRegistrar; + protected _parameters?: ParameterRegistrar; constructor(scope: Construct, id: string, props: AppProps) { super(scope, id); @@ -187,14 +187,11 @@ export abstract class App extends Construct implements IApp { * The parameter registrar for the app, can be used to find and register * parameter values that were provided to the wing application. */ - public get platformParameters() { - if (!this._platformParameters) { - this._platformParameters = new ParameterRegistrar( - this, - "ParameterRegistrar" - ); + public get parameters() { + if (!this._parameters) { + this._parameters = new ParameterRegistrar(this, "ParameterRegistrar"); } - return this._platformParameters!; + return this._parameters!; } /** diff --git a/libs/wingsdk/src/platform/parameter-registrar.ts b/libs/wingsdk/src/platform/parameter-registrar.ts index fb979a77574..967687f061f 100644 --- a/libs/wingsdk/src/platform/parameter-registrar.ts +++ b/libs/wingsdk/src/platform/parameter-registrar.ts @@ -1,7 +1,19 @@ import Ajv from "ajv"; import { Construct } from "constructs"; -import { loadPlatformSpecificValues } from "./util"; -import { Node } from "../std"; +import { + loadPlatformSpecificValues, + extractFieldsFromSchema, + filterParametersBySchema, +} from "./util"; +import { Json, Node } from "../std"; + +/** + * Options for reading parameters + */ +export interface ReadParameterOptions { + /** Schema to limit the read to */ + readonly schema?: any; +} /** * Parameter Registrar @@ -29,7 +41,7 @@ export class ParameterRegistrar extends Construct { * @param path the path of the parameter * @returns the value of the parameter */ - public getParameterValue(path: string): any { + public value(path: string): any { if (this.parameterValueByPath[path] === undefined) { // attempt to read the value from the raw parameters, then cache it this.parameterValueByPath[path] = resolveValueFromPath( @@ -41,13 +53,36 @@ export class ParameterRegistrar extends Construct { return this.parameterValueByPath[path]; } + /** + * Read parameters + * + * @param options options for reading parameters + * @returns the schema as a string + */ + public read(options?: ReadParameterOptions): Json { + if (options?.schema) { + this.addSchema(options.schema); + const fields = extractFieldsFromSchema( + options.schema._rawSchema // If a JsonSchema object is passed in, extract raw schema from it + ? options.schema._rawSchema + : options.schema + ); + return filterParametersBySchema(fields, this._rawParameters); + } + return this._rawParameters as Json; + } + /** * Add parameter schema to registrar * * @param schema schema to add to the registrar */ - public addParameterSchema(schema: any) { - this.parameterSchemas.push(schema); + public addSchema(schema: any) { + // If a JsonSchema object is passed in, extract the raw schema from it + const schemaToAdd = schema._rawSchema ? schema._rawSchema : schema; + if (!this.parameterSchemas.includes(schemaToAdd)) { + this.parameterSchemas.push(schemaToAdd); + } } /** @@ -58,14 +93,8 @@ export class ParameterRegistrar extends Construct { * @param path the path to nest the schema under * @param recursiveRequire whether or not to require all the nested properties */ - public addParameterSchemaAtPath( - schema: any, - path: string, - recursiveRequire = false - ) { - this.addParameterSchema( - this._nestSchemaUnderPath(schema, path, recursiveRequire) - ); + public addSchemaAtPath(schema: any, path: string, recursiveRequire = false) { + this.addSchema(this._nestSchemaUnderPath(schema, path, recursiveRequire)); } /** diff --git a/libs/wingsdk/src/platform/platform-manager.ts b/libs/wingsdk/src/platform/platform-manager.ts index 321385ed188..53d5bc3ba88 100644 --- a/libs/wingsdk/src/platform/platform-manager.ts +++ b/libs/wingsdk/src/platform/platform-manager.ts @@ -148,10 +148,10 @@ export class PlatformManager { newInstanceOverrides, }) as App; - let registrar = app.platformParameters; + let registrar = app.parameters; parameterSchemas.forEach((schema) => { - registrar.addParameterSchema(schema); + registrar.addSchema(schema); }); return app; diff --git a/libs/wingsdk/src/platform/util.ts b/libs/wingsdk/src/platform/util.ts index 7b92a6c5c66..a76c969f2f7 100644 --- a/libs/wingsdk/src/platform/util.ts +++ b/libs/wingsdk/src/platform/util.ts @@ -42,6 +42,39 @@ export function parseValuesObjectFromString(values: string) { return result; } +/** + * Extracts all fields from a JSON schema. + * + * @param schema the schema to extract fields from + * @returns a set of all fields in the schema + */ +export function extractFieldsFromSchema(schema: any): Set { + const fields = new Set(); + + if (schema.properties) { + for (const key of Object.keys(schema.properties)) { + fields.add(key); + } + } + + return fields; +} + +export function filterParametersBySchema( + fields: Set, + parameters: any +): any { + const filtered: any = {}; + + for (const field of fields) { + if (parameters.hasOwnProperty(field)) { + filtered[field] = parameters[field]; + } + } + + return filtered; +} + /** * Loads platform-specific values that were passed in via CLI arguments and * from a values file. CLI arguments take precedence over values file. diff --git a/libs/wingsdk/src/shared-aws/domain.ts b/libs/wingsdk/src/shared-aws/domain.ts index 432e04859fd..8b06e99092f 100644 --- a/libs/wingsdk/src/shared-aws/domain.ts +++ b/libs/wingsdk/src/shared-aws/domain.ts @@ -17,7 +17,7 @@ export class Domain extends cloud.Domain { constructor(scope: Construct, id: string, props: cloud.DomainProps) { super(scope, id, props); - const parameters = App.of(scope).platformParameters; + const parameters = App.of(scope).parameters; // Domain requires parameters from the user, so we need to add the parameter schemas to the registrar let schema = { @@ -44,17 +44,13 @@ export class Domain extends cloud.Domain { }, }; - parameters.addParameterSchemaAtPath(schema, this.node.path, true); + parameters.addSchemaAtPath(schema, this.node.path, true); - const iamCertificate = parameters.getParameterValue( - `${this.node.path}/iamCertificate` - ); - const acmCertificateArn = parameters.getParameterValue( + const iamCertificate = parameters.value(`${this.node.path}/iamCertificate`); + const acmCertificateArn = parameters.value( `${this.node.path}/acmCertificateArn` ); - const hostedZoneId = parameters.getParameterValue( - `${this.node.path}/hostedZoneId` - ); + const hostedZoneId = parameters.value(`${this.node.path}/hostedZoneId`); this._iamCertificate = iamCertificate; this._hostedZoneId = hostedZoneId; diff --git a/libs/wingsdk/src/std/bool.ts b/libs/wingsdk/src/std/bool.ts index d5af712c398..74b9468c872 100644 --- a/libs/wingsdk/src/std/bool.ts +++ b/libs/wingsdk/src/std/bool.ts @@ -15,7 +15,7 @@ export class Boolean { */ public static fromJson(json: Json, options?: JsonValidationOptions): boolean { const schema = JsonSchema._createJsonSchema({ - id: "bool", + $id: "bool", type: "boolean", } as any); schema.validate(json, options); diff --git a/libs/wingsdk/src/std/json_schema.ts b/libs/wingsdk/src/std/json_schema.ts index cbcbd4b4db5..27c32678957 100644 --- a/libs/wingsdk/src/std/json_schema.ts +++ b/libs/wingsdk/src/std/json_schema.ts @@ -1,6 +1,10 @@ import { Validator } from "jsonschema"; import { Json, JsonValidationOptions } from "./json"; import { InflightClient } from "../core"; +import { + extractFieldsFromSchema, + filterParametersBySchema, +} from "../platform/util"; /** * Struct Schema @@ -25,11 +29,12 @@ export class JsonSchema { return new JsonSchema(schema); } - private jsonSchema: any; + /** @internal */ + public _rawSchema: any; private validator: Validator; constructor(schema: Json) { - this.jsonSchema = schema; + this._rawSchema = schema; this.validator = new Validator(); } @@ -44,10 +49,10 @@ export class JsonSchema { return; // skip validation } - const result = this.validator.validate(obj, this.jsonSchema); + const result = this.validator.validate(obj, this._rawSchema); if (result.errors.length > 0) { throw new Error( - `unable to parse ${this.jsonSchema.id.replace( + `unable to parse ${this._rawSchema.$id.replace( "/", "" )}:\n- ${result.errors.join("\n- ")}` @@ -61,13 +66,16 @@ export class JsonSchema { * @returns the schema as a string */ public asStr(): String { - return JSON.stringify(this.jsonSchema); + return JSON.stringify(this._rawSchema); } /** @internal */ public _fromJson(obj: Json, validateOptions?: JsonValidationOptions) { this.validate(obj, validateOptions); - return obj; + const fields = extractFieldsFromSchema(this._rawSchema); + // Filter rawParameters based on the schema + const filteredParameters = filterParametersBySchema(fields, obj); + return filteredParameters; } /** @internal */ @@ -90,6 +98,6 @@ export class JsonSchema { /** @internal */ public _toInflightType() { - return JsonSchema._toInflightType(this.jsonSchema); + return JsonSchema._toInflightType(this._rawSchema); } } diff --git a/libs/wingsdk/src/std/node.ts b/libs/wingsdk/src/std/node.ts index f3154e2a27f..02498e8833a 100644 --- a/libs/wingsdk/src/std/node.ts +++ b/libs/wingsdk/src/std/node.ts @@ -7,6 +7,7 @@ import { IValidation, } from "constructs"; import { Connections } from "../core/connections"; +import { ParameterRegistrar } from "../platform"; const NODE_SYMBOL = Symbol.for("@winglang/sdk.std.Node"); export const APP_SYMBOL = Symbol.for("@winglang/sdk.std.Node/app"); @@ -452,6 +453,11 @@ export interface IApp extends IConstruct { */ readonly entrypointDir: string; + /** + * The application's parameter registrar + */ + readonly parameters: ParameterRegistrar; + /** * Generate a unique ID for the given scope and prefix. The newly generated ID is * guaranteed to be unique within the given scope. diff --git a/libs/wingsdk/src/std/number.ts b/libs/wingsdk/src/std/number.ts index dd02ebc6bfc..f30a0b235f3 100644 --- a/libs/wingsdk/src/std/number.ts +++ b/libs/wingsdk/src/std/number.ts @@ -15,7 +15,7 @@ export class Number { */ public static fromJson(json: Json, options?: JsonValidationOptions): number { const schema = JsonSchema._createJsonSchema({ - id: "num", + $id: "num", type: "number", } as any); schema.validate(json, options); diff --git a/libs/wingsdk/src/std/string.ts b/libs/wingsdk/src/std/string.ts index f0d77b13ee4..82cff5cfe1e 100644 --- a/libs/wingsdk/src/std/string.ts +++ b/libs/wingsdk/src/std/string.ts @@ -26,7 +26,7 @@ export class String { */ public static fromJson(json: Json, options?: JsonValidationOptions): string { const schema = JsonSchema._createJsonSchema({ - id: "string", + $id: "string", type: "string", } as any); schema.validate(json, options); diff --git a/libs/wingsdk/src/target-tf-aws/api.ts b/libs/wingsdk/src/target-tf-aws/api.ts index 7877c6590cc..daa80e0534d 100644 --- a/libs/wingsdk/src/target-tf-aws/api.ts +++ b/libs/wingsdk/src/target-tf-aws/api.ts @@ -333,9 +333,7 @@ class WingRestApi extends Construct { this.accountId = app.accountId; // Check for PRIVATE API Gateway configuration - let privateApiGateway = app.platformParameters.getParameterValue( - "tf-aws/vpc_api_gateway" - ); + let privateApiGateway = app.parameters.value("tf-aws/vpc_api_gateway"); if (privateApiGateway === true) { this.privateVpc = true; const vpcResources = this._initVpcResources(app); diff --git a/libs/wingsdk/src/target-tf-aws/app.ts b/libs/wingsdk/src/target-tf-aws/app.ts index c45890d55f8..95af8724ca7 100644 --- a/libs/wingsdk/src/target-tf-aws/app.ts +++ b/libs/wingsdk/src/target-tf-aws/app.ts @@ -170,20 +170,17 @@ export class App extends CdktfApp { return this._vpc; } - return this.platformParameters.getParameterValue(`${this._target}/vpc`) === - "existing" + return this.parameters.value(`${this._target}/vpc`) === "existing" ? this.importExistingVpc() : this.createDefaultVpc(); } private importExistingVpc(): DataAwsVpc { - const vpcId = this.platformParameters.getParameterValue( - `${this._target}/vpc_id` - ); - const privateSubnetIds = this.platformParameters.getParameterValue( + const vpcId = this.parameters.value(`${this._target}/vpc_id`); + const privateSubnetIds = this.parameters.value( `${this._target}/private_subnet_ids` ); - const publicSubnetIds = this.platformParameters.getParameterValue( + const publicSubnetIds = this.parameters.value( `${this._target}/public_subnet_ids` ); diff --git a/libs/wingsdk/src/target-tf-aws/function.ts b/libs/wingsdk/src/target-tf-aws/function.ts index fa2c17be175..6cfb6088d87 100644 --- a/libs/wingsdk/src/target-tf-aws/function.ts +++ b/libs/wingsdk/src/target-tf-aws/function.ts @@ -236,9 +236,7 @@ export class Function extends cloud.Function implements IAwsFunction { architectures: ["arm64"], }); - if ( - app.platformParameters.getParameterValue("tf-aws/vpc_lambda") === true - ) { + if (app.parameters.value("tf-aws/vpc_lambda") === true) { const sg = new SecurityGroup(this, `${id}SecurityGroup`, { vpcId: app.vpc.id, egress: [ diff --git a/libs/wingsdk/test/target-tf-aws/api.test.ts b/libs/wingsdk/test/target-tf-aws/api.test.ts index 9bff61f1d24..d83966d4bbf 100644 --- a/libs/wingsdk/test/target-tf-aws/api.test.ts +++ b/libs/wingsdk/test/target-tf-aws/api.test.ts @@ -36,7 +36,7 @@ test("api with GET route at root", () => { test("api will be private when vpc_api_gateway is true", () => { // GIVEN const app = new tfaws.App({ outdir: mkdtemp(), entrypointDir: __dirname }); - const parameters = app.platformParameters; + const parameters = app.parameters; parameters._rawParameters["tf-aws"] = { vpc: "new", vpc_api_gateway: true, diff --git a/libs/wingsdk/test/target-tf-aws/function.test.ts b/libs/wingsdk/test/target-tf-aws/function.test.ts index ce7c99a4401..21158b84ad8 100644 --- a/libs/wingsdk/test/target-tf-aws/function.test.ts +++ b/libs/wingsdk/test/target-tf-aws/function.test.ts @@ -45,7 +45,7 @@ test("basic function", () => { test("function will be behind a vpc when vpc_lambda is set to true", () => { // GIVEN const app = new tfaws.App({ outdir: mkdtemp(), entrypointDir: __dirname }); - const parameters = app.platformParameters; + const parameters = app.parameters; parameters._rawParameters["tf-aws"] = { vpc: "new", vpc_lambda: true, diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index da92ba95642..e894fd962d1 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -3061,6 +3061,19 @@ Duration " exports[`panic.test.w 2`] = `"Panicked, backtrace not captured: Unsupported"`; +exports[`parameters.test.w 1`] = ` +"Error: Parameter validation errors: +- must have required property 'foo' + +(hint: make sure to use --values to provide the required parameters file) + + + +Tests 1 failed (1) +Test Files 1 failed (1) +Duration " +`; + exports[`phase_mismatch.test.w 1`] = ` "error: Expected type to be \\"inflight (num): num\\", but got \\"preflight (n: num): num\\" instead --> ../../../examples/tests/invalid/phase_mismatch.test.w:2:10 @@ -3750,6 +3763,25 @@ error: Expected between 2 and 3 positional arguments or named arguments for the +Tests 1 failed (1) +Test Files 1 failed (1) +Duration " +`; + +exports[`struct_from_parameter.test.w 1`] = ` +"Error: unable to parse MyParams: +- instance requires property \\"bar\\" +- instance requires property \\"baz\\" +- instance requires property \\"foo\\" + --> ../../../examples/tests/invalid/struct_from_parameter.test.w:14:1 + | // technically we never enforced the parameters must have been + | // provided + | +14 | MyParams.fromJson(app.parameters.read()); + | ^ +at /struct_from_parameter.test.w:14:1 + + Tests 1 failed (1) Test Files 1 failed (1) Duration " diff --git a/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/nested_params/parameters.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/nested_params/parameters.test.w_compile_tf-aws.md new file mode 100644 index 00000000000..b39b3583e47 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/nested_params/parameters.test.w_compile_tf-aws.md @@ -0,0 +1,48 @@ +# [parameters.test.w](../../../../../../../examples/tests/valid/apps_with_params/nested_params/parameters.test.w) | compile | tf-aws + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.20.3" + }, + "outputs": {} + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +"use strict"; +const $stdlib = require('@winglang/sdk'); +const $platforms = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLATFORMS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const $helpers = $stdlib.helpers; +class $Root extends $stdlib.std.Resource { + constructor($scope, $id) { + super($scope, $id); + const MyParams = $stdlib.std.Struct._createJsonSchema({$id:"/MyParams",type:"object",properties:{houses:{type:"array",items:{type:"object",properties:{address:{type:"string"},residents:{type:"array",items:{type:"object",properties:{age:{type:"number"},name:{type:"string"},},required:["age","name",]}},},required:["address","residents",]}},},required:["houses",]}); + const app = $helpers.nodeof(this).app; + (app.parameters.addSchema(MyParams)); + const myParams = MyParams._fromJson((app.parameters.json())); + $helpers.assert($helpers.eq(myParams.houses.length, 2), "myParams.houses.length == 2"); + $helpers.assert($helpers.eq(((arr, index) => { if (index < 0 || index >= arr.length) throw new Error("Index out of bounds"); return arr[index]; })(myParams.houses, 0).address, "123 Main St"), "myParams.houses.at(0).address == \"123 Main St\""); + $helpers.assert($helpers.eq(((arr, index) => { if (index < 0 || index >= arr.length) throw new Error("Index out of bounds"); return arr[index]; })(myParams.houses, 0).residents.length, 2), "myParams.houses.at(0).residents.length == 2"); + } +} +const $PlatformManager = new $stdlib.platform.PlatformManager({platformPaths: $platforms}); +const $APP = $PlatformManager.createApp({ outdir: $outdir, name: "parameters.test", rootConstruct: $Root, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }); +$APP.synth(); +//# sourceMappingURL=preflight.js.map +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/nested_params/parameters.test.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/nested_params/parameters.test.w_test_sim.md new file mode 100644 index 00000000000..9af2392c17f --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/nested_params/parameters.test.w_test_sim.md @@ -0,0 +1,12 @@ +# [parameters.test.w](../../../../../../../examples/tests/valid/apps_with_params/nested_params/parameters.test.w) | test | sim + +## stdout.log +```log +pass ─ parameters.test.wsim (no tests) + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/simple_test/parameters.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/simple_test/parameters.test.w_compile_tf-aws.md new file mode 100644 index 00000000000..618e28b7345 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/simple_test/parameters.test.w_compile_tf-aws.md @@ -0,0 +1,57 @@ +# [parameters.test.w](../../../../../../../examples/tests/valid/apps_with_params/simple_test/parameters.test.w) | compile | tf-aws + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.20.3" + }, + "outputs": {} + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +"use strict"; +const $stdlib = require('@winglang/sdk'); +const $platforms = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLATFORMS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const $helpers = $stdlib.helpers; +class $Root extends $stdlib.std.Resource { + constructor($scope, $id) { + super($scope, $id); + const MyParams = $stdlib.std.Struct._createJsonSchema({$id:"/MyParams",type:"object",properties:{foo:{type:"string"},meaningOfLife:{type:"number"},},required:["meaningOfLife",]}); + const app = $helpers.nodeof(this).app; + (app.parameters.addSchema(MyParams)); + const myParams = MyParams._fromJson((app.parameters.json())); + { + const $if_let_value = myParams.foo; + if ($if_let_value != undefined) { + const foo = $if_let_value; + $helpers.assert(false, "false"); + } + else { + $helpers.assert(true, "true"); + } + } + const meaningOfLife = myParams.meaningOfLife; + $helpers.assert($helpers.eq(meaningOfLife, 42), "meaningOfLife == 42"); + } +} +const $PlatformManager = new $stdlib.platform.PlatformManager({platformPaths: $platforms}); +const $APP = $PlatformManager.createApp({ outdir: $outdir, name: "parameters.test", rootConstruct: $Root, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }); +$APP.synth(); +//# sourceMappingURL=preflight.js.map +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/simple_test/parameters.test.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/simple_test/parameters.test.w_test_sim.md new file mode 100644 index 00000000000..8d5a0d65458 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/apps_with_params/simple_test/parameters.test.w_test_sim.md @@ -0,0 +1,12 @@ +# [parameters.test.w](../../../../../../../examples/tests/valid/apps_with_params/simple_test/parameters.test.w) | test | sim + +## stdout.log +```log +pass ─ parameters.test.wsim (no tests) + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/optionals.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/optionals.test.w_compile_tf-aws.md index 2a75aef7ff9..e8c58f3d390 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/optionals.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/optionals.test.w_compile_tf-aws.md @@ -127,7 +127,7 @@ const cloud = $stdlib.cloud; class $Root extends $stdlib.std.Resource { constructor($scope, $id) { super($scope, $id); - const Person = $stdlib.std.Struct._createJsonSchema({id:"/Person",type:"object",properties:{age:{type:"number"},name:{type:"string"},},required:["age","name",]}); + const Person = $stdlib.std.Struct._createJsonSchema({$id:"/Person",type:"object",properties:{age:{type:"number"},name:{type:"string"},},required:["age","name",]}); class Super extends $stdlib.std.Resource { constructor($scope, $id, ) { super($scope, $id); diff --git a/tools/hangar/__snapshots__/test_corpus/valid/parameters.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/parameters.test.w_compile_tf-aws.md new file mode 100644 index 00000000000..ad0d76a840d --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/parameters.test.w_compile_tf-aws.md @@ -0,0 +1,56 @@ +# [parameters.test.w](../../../../../examples/tests/valid/parameters.test.w) | compile | tf-aws + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.20.3" + }, + "outputs": {} + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +"use strict"; +const $stdlib = require('@winglang/sdk'); +const $platforms = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLATFORMS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const $helpers = $stdlib.helpers; +class $Root extends $stdlib.std.Resource { + constructor($scope, $id) { + super($scope, $id); + const MyParams = $stdlib.std.Struct._createJsonSchema({$id:"/MyParams",type:"object",properties:{foo:{type:"string"},},required:[]}); + const app = $helpers.nodeof(this).app; + const registrar = app.parameters; + (registrar.addSchema(MyParams)); + const foo = (registrar.getValue("foo")); + { + const $if_let_value = foo; + if ($if_let_value != undefined) { + const foo = $if_let_value; + $helpers.assert(false, "false"); + } + else { + $helpers.assert(true, "true"); + } + } + } +} +const $PlatformManager = new $stdlib.platform.PlatformManager({platformPaths: $platforms}); +const $APP = $PlatformManager.createApp({ outdir: $outdir, name: "parameters.test", rootConstruct: $Root, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }); +$APP.synth(); +//# sourceMappingURL=preflight.js.map +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/parameters.test.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/valid/parameters.test.w_test_sim.md new file mode 100644 index 00000000000..bfdf85bcb57 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/parameters.test.w_test_sim.md @@ -0,0 +1,12 @@ +# [parameters.test.w](../../../../../examples/tests/valid/parameters.test.w) | test | sim + +## stdout.log +```log +pass ─ parameters.test.wsim (no tests) + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/parameters/nested/parameters.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/parameters/nested/parameters.test.w_compile_tf-aws.md new file mode 100644 index 00000000000..14640a022b0 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/parameters/nested/parameters.test.w_compile_tf-aws.md @@ -0,0 +1,47 @@ +# [parameters.test.w](../../../../../../../examples/tests/valid/parameters/nested/parameters.test.w) | compile | tf-aws + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.20.3" + }, + "outputs": {} + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +"use strict"; +const $stdlib = require('@winglang/sdk'); +const $platforms = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLATFORMS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const $helpers = $stdlib.helpers; +class $Root extends $stdlib.std.Resource { + constructor($scope, $id) { + super($scope, $id); + const MyParams = $stdlib.std.Struct._createJsonSchema({$id:"/MyParams",type:"object",properties:{houses:{type:"array",items:{type:"object",properties:{address:{type:"string"},residents:{type:"array",items:{type:"object",properties:{age:{type:"number"},name:{type:"string"},},required:["age","name",]}},},required:["address","residents",]}},},required:["houses",]}); + const app = $helpers.nodeof(this).app; + const myParams = MyParams._fromJson((app.parameters.read({ schema: MyParams }))); + $helpers.assert($helpers.eq(myParams.houses.length, 2), "myParams.houses.length == 2"); + $helpers.assert($helpers.eq(((arr, index) => { if (index < 0 || index >= arr.length) throw new Error("Index out of bounds"); return arr[index]; })(myParams.houses, 0).address, "123 Main St"), "myParams.houses.at(0).address == \"123 Main St\""); + $helpers.assert($helpers.eq(((arr, index) => { if (index < 0 || index >= arr.length) throw new Error("Index out of bounds"); return arr[index]; })(myParams.houses, 0).residents.length, 2), "myParams.houses.at(0).residents.length == 2"); + } +} +const $PlatformManager = new $stdlib.platform.PlatformManager({platformPaths: $platforms}); +const $APP = $PlatformManager.createApp({ outdir: $outdir, name: "parameters.test", rootConstruct: $Root, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }); +$APP.synth(); +//# sourceMappingURL=preflight.js.map +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/parameters/nested/parameters.test.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/valid/parameters/nested/parameters.test.w_test_sim.md new file mode 100644 index 00000000000..39af5eaaa1f --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/parameters/nested/parameters.test.w_test_sim.md @@ -0,0 +1,12 @@ +# [parameters.test.w](../../../../../../../examples/tests/valid/parameters/nested/parameters.test.w) | test | sim + +## stdout.log +```log +pass ─ parameters.test.wsim (no tests) + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/parameters/simple/parameters.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/parameters/simple/parameters.test.w_compile_tf-aws.md new file mode 100644 index 00000000000..6ed099b6449 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/parameters/simple/parameters.test.w_compile_tf-aws.md @@ -0,0 +1,56 @@ +# [parameters.test.w](../../../../../../../examples/tests/valid/parameters/simple/parameters.test.w) | compile | tf-aws + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.20.3" + }, + "outputs": {} + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +"use strict"; +const $stdlib = require('@winglang/sdk'); +const $platforms = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLATFORMS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const $helpers = $stdlib.helpers; +class $Root extends $stdlib.std.Resource { + constructor($scope, $id) { + super($scope, $id); + const MyParams = $stdlib.std.Struct._createJsonSchema({$id:"/MyParams",type:"object",properties:{foo:{type:"string"},meaningOfLife:{type:"number"},},required:["meaningOfLife",]}); + const app = $helpers.nodeof(this).app; + const myParams = MyParams._fromJson((app.parameters.read({ schema: MyParams }))); + { + const $if_let_value = myParams.foo; + if ($if_let_value != undefined) { + const foo = $if_let_value; + $helpers.assert(false, "false"); + } + else { + $helpers.assert(true, "true"); + } + } + const meaningOfLife = myParams.meaningOfLife; + $helpers.assert($helpers.eq(meaningOfLife, 42), "meaningOfLife == 42"); + } +} +const $PlatformManager = new $stdlib.platform.PlatformManager({platformPaths: $platforms}); +const $APP = $PlatformManager.createApp({ outdir: $outdir, name: "parameters.test", rootConstruct: $Root, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }); +$APP.synth(); +//# sourceMappingURL=preflight.js.map +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/parameters/simple/parameters.test.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/valid/parameters/simple/parameters.test.w_test_sim.md new file mode 100644 index 00000000000..c758692e008 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/parameters/simple/parameters.test.w_test_sim.md @@ -0,0 +1,12 @@ +# [parameters.test.w](../../../../../../../examples/tests/valid/parameters/simple/parameters.test.w) | test | sim + +## stdout.log +```log +pass ─ parameters.test.wsim (no tests) + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/struct_from_json.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/struct_from_json.test.w_compile_tf-aws.md index 26f928a21ed..52865eb4974 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/struct_from_json.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/struct_from_json.test.w_compile_tf-aws.md @@ -182,14 +182,14 @@ const otherExternalStructs = require("./preflight.structs2-2.js"); class $Root extends $stdlib.std.Resource { constructor($scope, $id) { super($scope, $id); - const Bar = $stdlib.std.Struct._createJsonSchema({id:"/Bar",type:"object",properties:{b:{type:"number"},f:{type:"string"},},required:["b","f",]}); - const Foo = $stdlib.std.Struct._createJsonSchema({id:"/Foo",type:"object",properties:{f:{type:"string"},},required:["f",]}); - const Foosible = $stdlib.std.Struct._createJsonSchema({id:"/Foosible",type:"object",properties:{f:{type:"string"},},required:[]}); - const MyStruct = $stdlib.std.Struct._createJsonSchema({id:"/MyStruct",type:"object",properties:{m1:{type:"object",properties:{val:{type:"number"},},required:["val",]},m2:{type:"object",properties:{val:{type:"string"},},required:["val",]},},required:["m1","m2",]}); - const SomeStruct = $stdlib.std.Struct._createJsonSchema({id:"/SomeStruct",type:"object",properties:{foo:{type:"string"},},required:["foo",]}); - const Student = $stdlib.std.Struct._createJsonSchema({id:"/Student",type:"object",properties:{additionalData:{type:"object"},advisor:{type:"object",properties:{dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},employeeID:{type:"string"},firstName:{type:"string"},lastName:{type:"string"},},required:["dob","employeeID","firstName","lastName",]},coursesTaken:{type:"array",items:{type:"object",properties:{course:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]},dateTaken:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},grade:{type:"string"},},required:["course","dateTaken","grade",]}},dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},enrolled:{type:"boolean"},enrolledCourses:{type:"array",uniqueItems:true,items:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]}},firstName:{type:"string"},lastName:{type:"string"},schoolId:{type:"string"},},required:["dob","enrolled","firstName","lastName","schoolId",]}); - const cloud_BucketProps = $stdlib.std.Struct._createJsonSchema({id:"/BucketProps",type:"object",properties:{public:{type:"boolean"},},required:[]}); - const externalStructs_MyOtherStruct = $stdlib.std.Struct._createJsonSchema({id:"/MyOtherStruct",type:"object",properties:{data:{type:"object",properties:{val:{type:"number"},},required:["val",]},},required:["data",]}); + const Bar = $stdlib.std.Struct._createJsonSchema({$id:"/Bar",type:"object",properties:{b:{type:"number"},f:{type:"string"},},required:["b","f",]}); + const Foo = $stdlib.std.Struct._createJsonSchema({$id:"/Foo",type:"object",properties:{f:{type:"string"},},required:["f",]}); + const Foosible = $stdlib.std.Struct._createJsonSchema({$id:"/Foosible",type:"object",properties:{f:{type:"string"},},required:[]}); + const MyStruct = $stdlib.std.Struct._createJsonSchema({$id:"/MyStruct",type:"object",properties:{m1:{type:"object",properties:{val:{type:"number"},},required:["val",]},m2:{type:"object",properties:{val:{type:"string"},},required:["val",]},},required:["m1","m2",]}); + const SomeStruct = $stdlib.std.Struct._createJsonSchema({$id:"/SomeStruct",type:"object",properties:{foo:{type:"string"},},required:["foo",]}); + const Student = $stdlib.std.Struct._createJsonSchema({$id:"/Student",type:"object",properties:{additionalData:{type:"object"},advisor:{type:"object",properties:{dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},employeeID:{type:"string"},firstName:{type:"string"},lastName:{type:"string"},},required:["dob","employeeID","firstName","lastName",]},coursesTaken:{type:"array",items:{type:"object",properties:{course:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]},dateTaken:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},grade:{type:"string"},},required:["course","dateTaken","grade",]}},dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},enrolled:{type:"boolean"},enrolledCourses:{type:"array",uniqueItems:true,items:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]}},firstName:{type:"string"},lastName:{type:"string"},schoolId:{type:"string"},},required:["dob","enrolled","firstName","lastName","schoolId",]}); + const cloud_BucketProps = $stdlib.std.Struct._createJsonSchema({$id:"/BucketProps",type:"object",properties:{public:{type:"boolean"},},required:[]}); + const externalStructs_MyOtherStruct = $stdlib.std.Struct._createJsonSchema({$id:"/MyOtherStruct",type:"object",properties:{data:{type:"object",properties:{val:{type:"number"},},required:["val",]},},required:["data",]}); class $Closure1 extends $stdlib.std.AutoIdResource { _id = $stdlib.core.closureId(); constructor($scope, $id, ) { @@ -488,7 +488,7 @@ class $Root extends $stdlib.std.Resource { $helpers.assert($helpers.eq(myStruct.m2.val, "10"), "myStruct.m2.val == \"10\""); const schema = MyStruct; (schema.validate(jMyStruct)); - const expectedSchema = ({"id": "/MyStruct", "type": "object", "properties": ({"m1": ({"type": "object", "properties": ({"val": ({"type": "number"})}), "required": ["val"]}), "m2": ({"type": "object", "properties": ({"val": ({"type": "string"})}), "required": ["val"]})}), "required": ["m1", "m2"]}); + const expectedSchema = ({"$id": "/MyStruct", "type": "object", "properties": ({"m1": ({"type": "object", "properties": ({"val": ({"type": "number"})}), "required": ["val"]}), "m2": ({"type": "object", "properties": ({"val": ({"type": "string"})}), "required": ["val"]})}), "required": ["m1", "m2"]}); $helpers.assert($helpers.eq((schema.asStr()), ((json, opts) => { return JSON.stringify(json, null, opts?.indent) })(expectedSchema)), "schema.asStr() == Json.stringify(expectedSchema)"); this.node.root.new("@winglang/sdk.std.Test", std.Test, this, "test:inflight schema usage", new $Closure4(this, "$Closure4")); (std.String.fromJson(10, { unsafe: true })); @@ -511,14 +511,14 @@ $APP.synth(); const $stdlib = require('@winglang/sdk'); const std = $stdlib.std; const $helpers = $stdlib.helpers; -const Bar = $stdlib.std.Struct._createJsonSchema({id:"/Bar",type:"object",properties:{b:{type:"number"},f:{type:"string"},},required:["b","f",]}); -const Foo = $stdlib.std.Struct._createJsonSchema({id:"/Foo",type:"object",properties:{f:{type:"string"},},required:["f",]}); -const Foosible = $stdlib.std.Struct._createJsonSchema({id:"/Foosible",type:"object",properties:{f:{type:"string"},},required:[]}); -const MyStruct = $stdlib.std.Struct._createJsonSchema({id:"/MyStruct",type:"object",properties:{m1:{type:"object",properties:{val:{type:"number"},},required:["val",]},m2:{type:"object",properties:{val:{type:"string"},},required:["val",]},},required:["m1","m2",]}); -const SomeStruct = $stdlib.std.Struct._createJsonSchema({id:"/SomeStruct",type:"object",properties:{foo:{type:"string"},},required:["foo",]}); -const Student = $stdlib.std.Struct._createJsonSchema({id:"/Student",type:"object",properties:{additionalData:{type:"object"},advisor:{type:"object",properties:{dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},employeeID:{type:"string"},firstName:{type:"string"},lastName:{type:"string"},},required:["dob","employeeID","firstName","lastName",]},coursesTaken:{type:"array",items:{type:"object",properties:{course:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]},dateTaken:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},grade:{type:"string"},},required:["course","dateTaken","grade",]}},dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},enrolled:{type:"boolean"},enrolledCourses:{type:"array",uniqueItems:true,items:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]}},firstName:{type:"string"},lastName:{type:"string"},schoolId:{type:"string"},},required:["dob","enrolled","firstName","lastName","schoolId",]}); -const cloud_BucketProps = $stdlib.std.Struct._createJsonSchema({id:"/BucketProps",type:"object",properties:{public:{type:"boolean"},},required:[]}); -const externalStructs_MyOtherStruct = $stdlib.std.Struct._createJsonSchema({id:"/MyOtherStruct",type:"object",properties:{data:{type:"object",properties:{val:{type:"number"},},required:["val",]},},required:["data",]}); +const Bar = $stdlib.std.Struct._createJsonSchema({$id:"/Bar",type:"object",properties:{b:{type:"number"},f:{type:"string"},},required:["b","f",]}); +const Foo = $stdlib.std.Struct._createJsonSchema({$id:"/Foo",type:"object",properties:{f:{type:"string"},},required:["f",]}); +const Foosible = $stdlib.std.Struct._createJsonSchema({$id:"/Foosible",type:"object",properties:{f:{type:"string"},},required:[]}); +const MyStruct = $stdlib.std.Struct._createJsonSchema({$id:"/MyStruct",type:"object",properties:{m1:{type:"object",properties:{val:{type:"number"},},required:["val",]},m2:{type:"object",properties:{val:{type:"string"},},required:["val",]},},required:["m1","m2",]}); +const SomeStruct = $stdlib.std.Struct._createJsonSchema({$id:"/SomeStruct",type:"object",properties:{foo:{type:"string"},},required:["foo",]}); +const Student = $stdlib.std.Struct._createJsonSchema({$id:"/Student",type:"object",properties:{additionalData:{type:"object"},advisor:{type:"object",properties:{dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},employeeID:{type:"string"},firstName:{type:"string"},lastName:{type:"string"},},required:["dob","employeeID","firstName","lastName",]},coursesTaken:{type:"array",items:{type:"object",properties:{course:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]},dateTaken:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},grade:{type:"string"},},required:["course","dateTaken","grade",]}},dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},enrolled:{type:"boolean"},enrolledCourses:{type:"array",uniqueItems:true,items:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]}},firstName:{type:"string"},lastName:{type:"string"},schoolId:{type:"string"},},required:["dob","enrolled","firstName","lastName","schoolId",]}); +const cloud_BucketProps = $stdlib.std.Struct._createJsonSchema({$id:"/BucketProps",type:"object",properties:{public:{type:"boolean"},},required:[]}); +const externalStructs_MyOtherStruct = $stdlib.std.Struct._createJsonSchema({$id:"/MyOtherStruct",type:"object",properties:{data:{type:"object",properties:{val:{type:"number"},},required:["val",]},},required:["data",]}); module.exports = { }; //# sourceMappingURL=preflight.structs-1.js.map ``` @@ -529,14 +529,14 @@ module.exports = { }; const $stdlib = require('@winglang/sdk'); const std = $stdlib.std; const $helpers = $stdlib.helpers; -const Bar = $stdlib.std.Struct._createJsonSchema({id:"/Bar",type:"object",properties:{b:{type:"number"},f:{type:"string"},},required:["b","f",]}); -const Foo = $stdlib.std.Struct._createJsonSchema({id:"/Foo",type:"object",properties:{f:{type:"string"},},required:["f",]}); -const Foosible = $stdlib.std.Struct._createJsonSchema({id:"/Foosible",type:"object",properties:{f:{type:"string"},},required:[]}); -const MyStruct = $stdlib.std.Struct._createJsonSchema({id:"/MyStruct",type:"object",properties:{m1:{type:"object",properties:{val:{type:"number"},},required:["val",]},m2:{type:"object",properties:{val:{type:"string"},},required:["val",]},},required:["m1","m2",]}); -const SomeStruct = $stdlib.std.Struct._createJsonSchema({id:"/SomeStruct",type:"object",properties:{foo:{type:"string"},},required:["foo",]}); -const Student = $stdlib.std.Struct._createJsonSchema({id:"/Student",type:"object",properties:{additionalData:{type:"object"},advisor:{type:"object",properties:{dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},employeeID:{type:"string"},firstName:{type:"string"},lastName:{type:"string"},},required:["dob","employeeID","firstName","lastName",]},coursesTaken:{type:"array",items:{type:"object",properties:{course:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]},dateTaken:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},grade:{type:"string"},},required:["course","dateTaken","grade",]}},dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},enrolled:{type:"boolean"},enrolledCourses:{type:"array",uniqueItems:true,items:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]}},firstName:{type:"string"},lastName:{type:"string"},schoolId:{type:"string"},},required:["dob","enrolled","firstName","lastName","schoolId",]}); -const cloud_BucketProps = $stdlib.std.Struct._createJsonSchema({id:"/BucketProps",type:"object",properties:{public:{type:"boolean"},},required:[]}); -const externalStructs_MyOtherStruct = $stdlib.std.Struct._createJsonSchema({id:"/MyOtherStruct",type:"object",properties:{data:{type:"object",properties:{val:{type:"number"},},required:["val",]},},required:["data",]}); +const Bar = $stdlib.std.Struct._createJsonSchema({$id:"/Bar",type:"object",properties:{b:{type:"number"},f:{type:"string"},},required:["b","f",]}); +const Foo = $stdlib.std.Struct._createJsonSchema({$id:"/Foo",type:"object",properties:{f:{type:"string"},},required:["f",]}); +const Foosible = $stdlib.std.Struct._createJsonSchema({$id:"/Foosible",type:"object",properties:{f:{type:"string"},},required:[]}); +const MyStruct = $stdlib.std.Struct._createJsonSchema({$id:"/MyStruct",type:"object",properties:{m1:{type:"object",properties:{val:{type:"number"},},required:["val",]},m2:{type:"object",properties:{val:{type:"string"},},required:["val",]},},required:["m1","m2",]}); +const SomeStruct = $stdlib.std.Struct._createJsonSchema({$id:"/SomeStruct",type:"object",properties:{foo:{type:"string"},},required:["foo",]}); +const Student = $stdlib.std.Struct._createJsonSchema({$id:"/Student",type:"object",properties:{additionalData:{type:"object"},advisor:{type:"object",properties:{dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},employeeID:{type:"string"},firstName:{type:"string"},lastName:{type:"string"},},required:["dob","employeeID","firstName","lastName",]},coursesTaken:{type:"array",items:{type:"object",properties:{course:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]},dateTaken:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},grade:{type:"string"},},required:["course","dateTaken","grade",]}},dob:{type:"object",properties:{day:{type:"number"},month:{type:"number"},year:{type:"number"},},required:["day","month","year",]},enrolled:{type:"boolean"},enrolledCourses:{type:"array",uniqueItems:true,items:{type:"object",properties:{credits:{type:"number"},name:{type:"string"},},required:["credits","name",]}},firstName:{type:"string"},lastName:{type:"string"},schoolId:{type:"string"},},required:["dob","enrolled","firstName","lastName","schoolId",]}); +const cloud_BucketProps = $stdlib.std.Struct._createJsonSchema({$id:"/BucketProps",type:"object",properties:{public:{type:"boolean"},},required:[]}); +const externalStructs_MyOtherStruct = $stdlib.std.Struct._createJsonSchema({$id:"/MyOtherStruct",type:"object",properties:{data:{type:"object",properties:{val:{type:"number"},},required:["val",]},},required:["data",]}); class UsesStructInImportedFile extends $stdlib.std.Resource { constructor($scope, $id, ) { super($scope, $id); diff --git a/tools/hangar/__snapshots__/test_corpus/valid/wing_parameters/parameters.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/wing_parameters/parameters.test.w_compile_tf-aws.md new file mode 100644 index 00000000000..bd6254aff1f --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/wing_parameters/parameters.test.w_compile_tf-aws.md @@ -0,0 +1,56 @@ +# [parameters.test.w](../../../../../../examples/tests/valid/wing_parameters/parameters.test.w) | compile | tf-aws + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.20.3" + }, + "outputs": {} + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +"use strict"; +const $stdlib = require('@winglang/sdk'); +const $platforms = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLATFORMS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const $helpers = $stdlib.helpers; +class $Root extends $stdlib.std.Resource { + constructor($scope, $id) { + super($scope, $id); + const MyParams = $stdlib.std.Struct._createJsonSchema({$id:"/MyParams",type:"object",properties:{bar:{type:"string"},foo:{type:"string"},},required:["bar",]}); + const app = $helpers.nodeof(this).app; + const registrar = app.parameters; + (registrar.addSchema(MyParams)); + const foo = (registrar.getValue("foo")); + { + const $if_let_value = foo; + if ($if_let_value != undefined) { + const foo = $if_let_value; + $helpers.assert(false, "false"); + } + else { + $helpers.assert(true, "true"); + } + } + } +} +const $PlatformManager = new $stdlib.platform.PlatformManager({platformPaths: $platforms}); +const $APP = $PlatformManager.createApp({ outdir: $outdir, name: "parameters.test", rootConstruct: $Root, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }); +$APP.synth(); +//# sourceMappingURL=preflight.js.map +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/valid/wing_parameters/parameters.test.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/valid/wing_parameters/parameters.test.w_test_sim.md new file mode 100644 index 00000000000..38a805d41f3 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/valid/wing_parameters/parameters.test.w_test_sim.md @@ -0,0 +1,12 @@ +# [parameters.test.w](../../../../../../examples/tests/valid/wing_parameters/parameters.test.w) | test | sim + +## stdout.log +```log +pass ─ parameters.test.wsim (no tests) + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/src/generate_tests.ts b/tools/hangar/src/generate_tests.ts index c863edac72f..a38c5b4223c 100644 --- a/tools/hangar/src/generate_tests.ts +++ b/tools/hangar/src/generate_tests.ts @@ -1,5 +1,5 @@ import { mkdirSync, readdirSync, rmSync, writeFileSync } from "fs"; -import { sdkTestsDir, validTestDir } from "./paths"; +import { appWithParamsDir, sdkTestsDir, validTestDir } from "./paths"; import { join, extname } from "path"; import { parseMetaCommentFromPath } from "./meta_comment"; @@ -96,6 +96,12 @@ generateTests({ isRecursive: false, includeJavaScriptInSnapshots: true, }); +generateTests({ + sourceDir: appWithParamsDir, + destination: generatedTestDir, + isRecursive: true, + includeJavaScriptInSnapshots: true, +}); generateTests({ sourceDir: sdkTestsDir, destination: generatedSDKTestDir, diff --git a/tools/hangar/src/paths.ts b/tools/hangar/src/paths.ts index b5a2051f878..5b8f5db8491 100644 --- a/tools/hangar/src/paths.ts +++ b/tools/hangar/src/paths.ts @@ -5,6 +5,7 @@ export const repoRoot = path.resolve(__dirname, "../../.."); export const examplesDir = path.join(repoRoot, "examples"); export const testDir = path.join(examplesDir, "tests"); export const validTestDir = path.join(testDir, "valid"); +export const appWithParamsDir = path.join(validTestDir, "parameters"); export const sdkTestsDir = path.join(testDir, "sdk_tests"); export const compatibilityTestsDir = path.join(testDir, "sdk_tests/counter"); export const platformsDir = path.join(validTestDir, "platforms");