From b0f5d5fa4a99bfd72028895e7c41cf0b3de4d6c1 Mon Sep 17 00:00:00 2001 From: Shoujian Zheng Date: Thu, 5 Oct 2023 22:55:43 +0800 Subject: [PATCH] feat(sdk): add fs module --- examples/tests/sdk_tests/fs/basic.main.w | 30 ++ examples/tests/sdk_tests/fs/directory.main.w | 45 +++ examples/tests/sdk_tests/fs/json.main.w | 46 +++ examples/tests/sdk_tests/fs/path.main.w | 36 +++ examples/tests/sdk_tests/fs/temp_dir.main.w | 15 + examples/tests/sdk_tests/fs/yaml.main.w | 31 ++ libs/wingc/src/lib.rs | 4 +- libs/wingsdk/.projen/deps.json | 10 + libs/wingsdk/.projen/tasks.json | 2 +- libs/wingsdk/.projenrc.ts | 3 + libs/wingsdk/package.json | 3 + libs/wingsdk/src/fs/fs.ts | 292 ++++++++++++++++++ libs/wingsdk/src/fs/index.ts | 1 + libs/wingsdk/src/index.ts | 1 + libs/wingsdk/test/fs/fs.test.ts | 86 ++++++ pnpm-lock.yaml | 16 +- .../fs/basic.main.w_compile_tf-aws.md | 124 ++++++++ .../sdk_tests/fs/basic.main.w_test_sim.md | 12 + .../fs/directory.main.w_compile_tf-aws.md | 142 +++++++++ .../sdk_tests/fs/directory.main.w_test_sim.md | 12 + .../fs/json.main.w_compile_tf-aws.md | 141 +++++++++ .../sdk_tests/fs/json.main.w_test_sim.md | 12 + .../fs/path.main.w_compile_tf-aws.md | 128 ++++++++ .../sdk_tests/fs/path.main.w_test_sim.md | 12 + .../fs/temp_dir.main.w_compile_tf-aws.md | 105 +++++++ .../sdk_tests/fs/temp_dir.main.w_test_sim.md | 12 + .../fs/yaml.main.w_compile_tf-aws.md | 125 ++++++++ .../sdk_tests/fs/yaml.main.w_test_sim.md | 12 + 28 files changed, 1453 insertions(+), 5 deletions(-) create mode 100644 examples/tests/sdk_tests/fs/basic.main.w create mode 100644 examples/tests/sdk_tests/fs/directory.main.w create mode 100644 examples/tests/sdk_tests/fs/json.main.w create mode 100644 examples/tests/sdk_tests/fs/path.main.w create mode 100644 examples/tests/sdk_tests/fs/temp_dir.main.w create mode 100644 examples/tests/sdk_tests/fs/yaml.main.w create mode 100644 libs/wingsdk/src/fs/fs.ts create mode 100644 libs/wingsdk/src/fs/index.ts create mode 100644 libs/wingsdk/test/fs/fs.test.ts create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/basic.main.w_compile_tf-aws.md create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/basic.main.w_test_sim.md create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/directory.main.w_compile_tf-aws.md create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/directory.main.w_test_sim.md create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/json.main.w_compile_tf-aws.md create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/json.main.w_test_sim.md create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/path.main.w_compile_tf-aws.md create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/path.main.w_test_sim.md create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/temp_dir.main.w_compile_tf-aws.md create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/temp_dir.main.w_test_sim.md create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/yaml.main.w_compile_tf-aws.md create mode 100644 tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/yaml.main.w_test_sim.md diff --git a/examples/tests/sdk_tests/fs/basic.main.w b/examples/tests/sdk_tests/fs/basic.main.w new file mode 100644 index 00000000000..34e5a23ce55 --- /dev/null +++ b/examples/tests/sdk_tests/fs/basic.main.w @@ -0,0 +1,30 @@ +bring fs; + +let filename = "hello.txt"; +let data = "Hello, Wing!"; + +fs.writeFile(filename, data); +assert(fs.exists(filename) == true); + +let content = fs.readFile(filename); +assert(content == data); + +fs.remove(filename); +assert(fs.exists(filename) == false); + +let nilContent = fs.tryReadFile(filename); +assert(nilContent == nil); + +test "inflight file basic operations" { + fs.writeFile(filename, data); + assert(fs.exists(filename) == true); + + let content = fs.readFile(filename); + assert(content == data); + + fs.remove(filename); + assert(fs.exists(filename) == false); + + let nilContent = fs.tryReadFile(filename); + assert(nilContent == nil); +} \ No newline at end of file diff --git a/examples/tests/sdk_tests/fs/directory.main.w b/examples/tests/sdk_tests/fs/directory.main.w new file mode 100644 index 00000000000..e8aacf38b35 --- /dev/null +++ b/examples/tests/sdk_tests/fs/directory.main.w @@ -0,0 +1,45 @@ +bring fs; +bring regex; + +let dirname = "wingdir"; +let filename = "temp.txt"; + +fs.mkdir(dirname); +assert(fs.exists(dirname) == true); + +try { + fs.mkdir(dirname); +} catch e { + assert(regex.match("^EEXIST: file already exists", e) == true); +} + +fs.writeFile(fs.join(dirname, filename), ""); +let files = fs.readdir(dirname); +assert(files.length == 1); + +fs.remove(dirname, { recursive: true }); +assert(fs.exists(dirname) == false); + +let nilFiles = fs.tryReaddir(dirname); +assert(nilFiles == nil); + +test "inflight create normal directory" { + fs.mkdir(dirname); + assert(fs.exists(dirname) == true); + + try { + fs.mkdir(dirname); + } catch e { + assert(regex.match("^EEXIST: file already exists", e) == true); + } + + fs.writeFile(fs.join(dirname, filename), ""); + let files = fs.readdir(dirname); + assert(files.length == 1); + + fs.remove(dirname, { recursive: true }); + assert(fs.exists(dirname) == false); + + let nilFiles = fs.tryReaddir(dirname); + assert(nilFiles == nil); +} \ No newline at end of file diff --git a/examples/tests/sdk_tests/fs/json.main.w b/examples/tests/sdk_tests/fs/json.main.w new file mode 100644 index 00000000000..371496886b1 --- /dev/null +++ b/examples/tests/sdk_tests/fs/json.main.w @@ -0,0 +1,46 @@ +bring fs; +bring regex; + +let filename = "test-json.json"; +let data = Json { + "foo": "bar", + "arr": [1, 2, 3, "test", { "foo": "bar" }] +}; + +try { + fs.writeFile(filename, "invalid content"); + fs.readJson(filename); +} catch e { + assert(regex.match("^Unexpected token", e) == true); +} + +fs.writeJson(filename, data); +assert(fs.exists(filename) == true); + +let obj = fs.readJson(filename); +assert(Json.stringify(obj) == Json.stringify(data)); + +fs.remove(filename); +assert(fs.exists(filename) == false); + +assert(fs.tryReadJson(filename) == nil); + +test "inflight json operations" { + try { + fs.writeFile(filename, "invalid content"); + fs.readJson(filename); + } catch e { + assert(regex.match("^Unexpected token", e) == true); + } + + fs.writeJson(filename, data); + assert(fs.exists(filename) == true); + + let obj = fs.readJson(filename); + assert(Json.stringify(obj) == Json.stringify(data)); + + fs.remove(filename); + assert(fs.exists(filename) == false); + + assert(fs.tryReadJson(filename) == nil); +} \ No newline at end of file diff --git a/examples/tests/sdk_tests/fs/path.main.w b/examples/tests/sdk_tests/fs/path.main.w new file mode 100644 index 00000000000..0bb5ecfd47c --- /dev/null +++ b/examples/tests/sdk_tests/fs/path.main.w @@ -0,0 +1,36 @@ +bring fs; + +let from = "/a/b/c/d"; +let to = "/a/b/e/f"; + +let var result = fs.join(from, to); +assert(result == "/a/b/c/d/a/b/e/f"); + +result = fs.relative(from ,to); +assert(result == "../../e/f"); + +result = fs.dirname(from); +assert(result == "/a/b/c"); + +result = fs.basename(from); +assert(result == "d"); + +result = fs.resolve(from, to); +assert(result == "/a/b/e/f"); + +test "inflight path conversion" { + let var result = fs.join(from, to); + assert(result == "/a/b/c/d/a/b/e/f"); + + result = fs.relative(from ,to); + assert(result == "../../e/f"); + + result = fs.dirname(from); + assert(result == "/a/b/c"); + + result = fs.basename(from); + assert(result == "d"); + + result = fs.resolve(from, to); + assert(result == "/a/b/e/f"); +} \ No newline at end of file diff --git a/examples/tests/sdk_tests/fs/temp_dir.main.w b/examples/tests/sdk_tests/fs/temp_dir.main.w new file mode 100644 index 00000000000..b63af29c8e1 --- /dev/null +++ b/examples/tests/sdk_tests/fs/temp_dir.main.w @@ -0,0 +1,15 @@ +bring fs; + +let tmpdir = fs.mkdtemp(); +assert(fs.exists(tmpdir) == true); + +fs.remove(tmpdir, { recursive: true }); +assert(fs.exists(tmpdir) == false); + +test "inflight create temporary directory" { + let tmpdir = fs.mkdtemp(); + assert(fs.exists(tmpdir) == true); + + fs.remove(tmpdir, { recursive: true }); + assert(fs.exists(tmpdir) == false); +} \ No newline at end of file diff --git a/examples/tests/sdk_tests/fs/yaml.main.w b/examples/tests/sdk_tests/fs/yaml.main.w new file mode 100644 index 00000000000..27e891e0112 --- /dev/null +++ b/examples/tests/sdk_tests/fs/yaml.main.w @@ -0,0 +1,31 @@ +bring fs; + +let filename = "test-yaml.yaml"; +let data = Json { + "foo": "bar", + "arr": [1, 2, 3, "test", { "foo": "bar" }] +}; + +fs.writeYaml(filename, data, data); +assert(fs.exists(filename) == true); + +let objs = fs.readYaml(filename); +assert(objs.length == 2); +assert(Json.stringify(objs.at(0)) == Json.stringify(data)); +assert(Json.stringify(objs.at(1)) == Json.stringify(data)); + +fs.remove(filename); +assert(fs.exists(filename) == false); + +test "inflight yaml operations" { + fs.writeYaml(filename, data, data); + assert(fs.exists(filename) == true); + + let objs = fs.readYaml(filename); + assert(objs.length == 2); + assert(Json.stringify(objs.at(0)) == Json.stringify(data)); + assert(Json.stringify(objs.at(1)) == Json.stringify(data)); + + fs.remove(filename); + assert(fs.exists(filename) == false); +} \ No newline at end of file diff --git a/libs/wingc/src/lib.rs b/libs/wingc/src/lib.rs index bb2a8fe2057..24cd414e1e2 100644 --- a/libs/wingc/src/lib.rs +++ b/libs/wingc/src/lib.rs @@ -77,10 +77,11 @@ const WINGSDK_MATH_MODULE: &'static str = "math"; const WINGSDK_AWS_MODULE: &'static str = "aws"; const WINGSDK_EX_MODULE: &'static str = "ex"; const WINGSDK_REGEX_MODULE: &'static str = "regex"; +const WINGSDK_FS_MODULE: &'static str = "fs"; pub const UTIL_CLASS_NAME: &'static str = "Util"; -const WINGSDK_BRINGABLE_MODULES: [&'static str; 7] = [ +const WINGSDK_BRINGABLE_MODULES: [&'static str; 8] = [ WINGSDK_CLOUD_MODULE, WINGSDK_UTIL_MODULE, WINGSDK_HTTP_MODULE, @@ -88,6 +89,7 @@ const WINGSDK_BRINGABLE_MODULES: [&'static str; 7] = [ WINGSDK_AWS_MODULE, WINGSDK_EX_MODULE, WINGSDK_REGEX_MODULE, + WINGSDK_FS_MODULE, ]; const WINGSDK_DURATION: &'static str = "std.Duration"; diff --git a/libs/wingsdk/.projen/deps.json b/libs/wingsdk/.projen/deps.json index 668f39c0664..6f6ba2136b2 100644 --- a/libs/wingsdk/.projen/deps.json +++ b/libs/wingsdk/.projen/deps.json @@ -17,6 +17,11 @@ "name": "@types/fs-extra", "type": "build" }, + { + "name": "@types/js-yaml", + "version": "^4.0.6", + "type": "build" + }, { "name": "@types/mime-types", "type": "build" @@ -278,6 +283,11 @@ "name": "ioredis", "type": "bundled" }, + { + "name": "js-yaml", + "version": "^4.1.0", + "type": "bundled" + }, { "name": "jsonschema", "type": "bundled" diff --git a/libs/wingsdk/.projen/tasks.json b/libs/wingsdk/.projen/tasks.json index 2d44d3269ec..5523d868d0b 100644 --- a/libs/wingsdk/.projen/tasks.json +++ b/libs/wingsdk/.projen/tasks.json @@ -474,7 +474,7 @@ "exec": "pnpm i --no-frozen-lockfile" }, { - "exec": "pnpm update @cdktf/provider-aws @types/aws-lambda @types/express @types/fs-extra @types/mime-types @types/node @types/uuid @typescript-eslint/eslint-plugin @typescript-eslint/parser @vitest/coverage-v8 @winglang/jsii-docgen aws-sdk-client-mock aws-sdk-client-mock-jest bump-pack cdktf-cli constructs eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint-plugin-sort-exports eslint fs-extra jsii-diff jsii-pacmak jsii-rosetta jsii nanoid npm-check-updates prettier projen standard-version ts-node typescript vitest wing-api-checker @aws-sdk/client-cloudwatch-logs @aws-sdk/client-dynamodb @aws-sdk/client-elasticache @aws-sdk/client-lambda @aws-sdk/client-s3 @aws-sdk/client-secrets-manager @aws-sdk/client-sns @aws-sdk/client-sqs @aws-sdk/is-array-buffer @aws-sdk/s3-request-presigner @aws-sdk/types @aws-sdk/util-buffer-from @aws-sdk/util-dynamodb @aws-sdk/util-stream-node @aws-sdk/util-utf8-node @azure/core-paging @azure/identity @azure/storage-blob @types/aws-lambda aws-cdk-lib cdktf cron-parser esbuild-wasm express ioredis jsonschema mime-types nanoid safe-stable-stringify uuid constructs constructs" + "exec": "pnpm update @cdktf/provider-aws @types/aws-lambda @types/express @types/fs-extra @types/js-yaml @types/mime-types @types/node @types/uuid @typescript-eslint/eslint-plugin @typescript-eslint/parser @vitest/coverage-v8 @winglang/jsii-docgen aws-sdk-client-mock aws-sdk-client-mock-jest bump-pack cdktf-cli constructs eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint-plugin-sort-exports eslint fs-extra jsii-diff jsii-pacmak jsii-rosetta jsii nanoid npm-check-updates prettier projen standard-version ts-node typescript vitest wing-api-checker @aws-sdk/client-cloudwatch-logs @aws-sdk/client-dynamodb @aws-sdk/client-elasticache @aws-sdk/client-lambda @aws-sdk/client-s3 @aws-sdk/client-secrets-manager @aws-sdk/client-sns @aws-sdk/client-sqs @aws-sdk/is-array-buffer @aws-sdk/s3-request-presigner @aws-sdk/types @aws-sdk/util-buffer-from @aws-sdk/util-dynamodb @aws-sdk/util-stream-node @aws-sdk/util-utf8-node @azure/core-paging @azure/identity @azure/storage-blob @types/aws-lambda aws-cdk-lib cdktf cron-parser esbuild-wasm express ioredis js-yaml jsonschema mime-types nanoid safe-stable-stringify uuid constructs constructs" }, { "exec": "pnpm exec projen" diff --git a/libs/wingsdk/.projenrc.ts b/libs/wingsdk/.projenrc.ts index 421eeb2e3d8..090f70c9623 100644 --- a/libs/wingsdk/.projenrc.ts +++ b/libs/wingsdk/.projenrc.ts @@ -84,6 +84,8 @@ const project = new cdk.JsiiProject({ // shared client dependencies "ioredis", "jsonschema", + // fs module dependency + "js-yaml@^4.1.0", ], devDeps: [ `@cdktf/provider-aws@^15.0.0`, // only for testing Wing plugins @@ -101,6 +103,7 @@ const project = new cdk.JsiiProject({ "vitest", "@types/uuid", "@vitest/coverage-v8", + "@types/js-yaml@^4.0.6", "nanoid", // for ESM import test in target-sim/function.test.ts ...JSII_DEPS, ], diff --git a/libs/wingsdk/package.json b/libs/wingsdk/package.json index 1fa4480365c..973288a975d 100644 --- a/libs/wingsdk/package.json +++ b/libs/wingsdk/package.json @@ -41,6 +41,7 @@ "@types/aws-lambda": "^8.10.109", "@types/express": "^4.17.17", "@types/fs-extra": "^11.0.1", + "@types/js-yaml": "^4.0.6", "@types/mime-types": "^2.1.1", "@types/node": "^18", "@types/uuid": "^9.0.3", @@ -105,6 +106,7 @@ "esbuild-wasm": "^0.18.20", "express": "^4.18.2", "ioredis": "^5.3.2", + "js-yaml": "^4.1.0", "jsonschema": "^1.4.1", "mime-types": "^2.1.35", "nanoid": "^3.3.6", @@ -137,6 +139,7 @@ "esbuild-wasm", "express", "ioredis", + "js-yaml", "jsonschema", "mime-types", "nanoid", diff --git a/libs/wingsdk/src/fs/fs.ts b/libs/wingsdk/src/fs/fs.ts new file mode 100644 index 00000000000..dee7fc5905a --- /dev/null +++ b/libs/wingsdk/src/fs/fs.ts @@ -0,0 +1,292 @@ +import * as fs from "fs"; +import * as os from "os"; +import * as path from "path"; +import * as yaml from "js-yaml"; +import { InflightClient } from "../core"; +import { Json } from "../std"; + +/** + * Convert the path to Windows format if running on Windows. + * @param p The path to convert. + * @returns The Normalized path + */ +function localePath(p: string): string { + if (process.platform !== "win32") { + return p; + } + return p.split(path.posix.sep).join(path.win32.sep); +} + +/** + * Convert the path to POSIX format. + * @param p The path to convert. + * @returns The Normalized path. + */ +function posixPath(p: string): string { + return p.split(path.sep).join(path.posix.sep); +} + +/** + * Custom settings for reading file + */ +export interface ReadFileOptions { + /** + * The character encoding utilized for file reading. + * @default "utf-8" + */ + readonly encoding?: BufferEncoding; + /** + * The `flag` can be set to specify the attributes. + * @default 'r'. + */ + readonly flag?: string; +} + +/** + * Custom settings for creating directory + */ +export interface MkdirOptions { + /** + * Indicates whether parent folders should be created. + * If a folder was created, the path to the first created folder will be returned. + * @default false + */ + readonly recursive?: boolean; + /** + * A file mode. The string will be parsed as an octal integer. + * @default "0o777" + */ + readonly mode?: string; +} + +/** + * Custom settings for removing files and directories + */ +export interface RemoveOptions { + /** + * When `true`, exceptions will be ignored if `path` does not exist. + * @default false + */ + readonly force?: boolean; + /** + * If `true`, perform a recursive directory removal. In + * recursive mode, operations are retried on failure. + * @default false + */ + readonly recursive?: boolean; +} + +/** + * The fs class is used for interacting with the file system. + * All file paths must be POSIX file paths (/ instead of \), + * and will be normalized to the target platform if running on Windows. + */ +export class Util { + /** + * Join all arguments together and normalize the resulting path. + * @param paths The array of path need to join. + * @returns The resulting path after joining all the paths. + */ + public static join(...paths: string[]): string { + return path.join(...paths); + } + /** + * Retrieve the name of the directory from a given file path. + * @param p The path to evaluate. + * @returns The directory name of the path. + */ + public static dirname(p: string): string { + return path.dirname(p); + } + /** + * Retrieve the final segment of a given file path. + * @param p The path to evaluate. + * @returns The last portion of a path. + */ + public static basename(p: string): string { + return path.basename(p); + } + /** + * Solve the relative path from {from} to {to} based on the current working directory. + * At times we have two absolute paths, and we need to derive the relative path from one to the other. + * @returns The relative path from {from} to {to}. + */ + public static relative(from: string, to: string): string { + return path.relative(from, to); + } + /** + * The right-most parameter is considered {to}. Other parameters are considered an array of {from}. + * + * Starting from leftmost {from} parameter, resolves {to} to an absolute path. + * + * If {to} isn't already absolute, {from} arguments are prepended in right to left order, + * until an absolute path is found. If after using all {from} paths still no absolute path is found, + * the current working directory is used as well. The resulting path is normalized, + * and trailing slashes are removed unless the path gets resolved to the root directory. + * + * @param paths A sequence of paths or path segments. + * @returns The resulting path after performing the resolve operation. + */ + public static resolve(...paths: string[]): string { + return path.resolve(...paths); + } + /** + * Check if the path exists. + * @param p The path to evaluate. + * @returns `true` if the path exists, `false` otherwise. + */ + public static exists(p: string): boolean { + const normPath = localePath(p); + return fs.existsSync(normPath); + } + /** + * Read the contents of the directory. + * @param dirpath The path to evaluate. + * @returns The contents of the directory. + */ + public static readdir(dirpath: string): Array { + const normPath = localePath(dirpath); + return fs.readdirSync(normPath); + } + /** + * If the path exists, read the contents of the directory; otherwise, return `undefined`. + * @param dirpath The path to evaluate. + * @returns The contents of the directory if the path exists, `undefined` otherwise. + */ + public static tryReaddir(dirpath: string): Array | undefined { + if (!Util.exists(dirpath)) { + return undefined; + } + return Util.readdir(dirpath); + } + /** + * Create a directory. + * @param dirpath The path to the directory you want to create. + */ + public static mkdir(dirpath: string, opts?: MkdirOptions): void { + const normPath = localePath(dirpath); + fs.mkdirSync(normPath, opts); + } + /** + * Create a temporary directory. + * Generates six random characters to be appended behind a required prefix to create a unique temporary directory. + * @param prefix The prefix for the directory to be created, default `wingtemp`. + * @returns The created directory path. + */ + public static mkdtemp(prefix?: string): string { + if (prefix == undefined) { + prefix = "wingtemp"; + } + const dirpath = fs.mkdtempSync(path.join(os.tmpdir(), prefix)); + return posixPath(dirpath); + } + /** + * Read the entire contents of a file. + * @param filepath The path of the file to be read. + * @param options The `encoding` can be set to specify the character encoding. And the `flag` can be set to specify the attributes. + * If a flag is not provided, it defaults to `'r'`. + * @returns The contents of the `filepath`. + */ + public static readFile(filepath: string, options?: ReadFileOptions): string { + const normPath = localePath(filepath); + const buf = fs.readFileSync(normPath, options); + return buf.toString(); + } + /** + * Read the entire contents if the file exists, `undefined` otherwise. + * @param filepath The path of the file to be read. + * @param options The `encoding` can be set to specify the character encoding, or the `flag` can be set to specify the attributes. + * @returns The contents of the `filepath`, `undefined` otherwise. + */ + public static tryReadFile( + filepath: string, + options?: ReadFileOptions + ): string | undefined { + if (!Util.exists(filepath)) { + return; + } + return Util.readFile(filepath, options); + } + /** + * Read the content of the file and convert it to JSON + * @param filepath The file path of the JSON file. + * @returns The JSON object contained in the file. + */ + public static readJson(filepath: string): Json { + const text = Util.readFile(filepath); + return JSON.parse(text) as Json; + } + /** + * Get the content of the file and convert it to JSON if the path exists, `undefined` otherwise. + * @param filepath The file path of the JSON file. + * @returns The JSON object contained in the file, `undefined` otherwise. + */ + public static tryReadJson(filepath: string): Json | undefined { + if (!Util.exists(filepath)) { + return undefined; + } + return Util.readJson(filepath); + } + /** + * Convert all YAML objects from a single file into JSON objects. + * @param filepath The file path of the YAML file. + * @returns The JSON objects converted from YAML objects in the file. + */ + public static readYaml(filepath: string): Json[] { + const text = Util.readFile(filepath); + const yamlObjs = yaml.loadAll(text); + return yamlObjs.map((o: any) => JSON.parse(JSON.stringify(o)) as Json); + } + /** + * Convert all YAML objects from a single file into JSON objects if the path exists, `undefined` otherwise. + * @param filepath The file path of the YAML file. + * @returns The JSON objects converted from YAML objects in the file, `undefined` otherwise. + */ + public static tryReadYaml(filepath: string): Json[] | undefined { + if (!Util.exists(filepath)) { + return undefined; + } + return Util.readYaml(filepath); + } + /** + * Writes data to a file, replacing the file if it already exists. + * @param filepath The file path that needs to be written. + * @param data The data to write. + */ + public static writeFile(filepath: string, data: string): void { + const normPath = localePath(filepath); + fs.writeFileSync(normPath, data); + } + /** + * Writes JSON to a file, replacing the file if it already exists. + * @param filepath The file path that needs to be written. + * @param obj The JSON object to be dumped. + */ + public static writeJson(filepath: string, obj: Json): void { + const text = JSON.stringify(obj, null, 2); + fs.writeFileSync(filepath, text); + } + /** + * Writes multiple YAML objects to a file, replacing the file if it already exists. + * @param filepath The file path that needs to be written. + * @param objs The YANL objects to be dumped. + */ + public static writeYaml(filepath: string, ...objs: Json[]): void { + const contents = objs.map((o) => yaml.dump(o, { noRefs: true })); + fs.writeFileSync(filepath, contents.join("---\n")); + } + /** + * Remove files and directories (modeled on the standard POSIX `rm`utility). Returns `undefined`. + * @param p The path to the file or directory you want to remove. + */ + public static remove(p: string, opts?: RemoveOptions): void { + const normPath = localePath(p); + fs.rmSync(normPath, opts); + } + /** + * @internal + */ + public static _toInflightType(): string { + return InflightClient.forType(__filename, this.name); + } +} diff --git a/libs/wingsdk/src/fs/index.ts b/libs/wingsdk/src/fs/index.ts new file mode 100644 index 00000000000..ff41260878f --- /dev/null +++ b/libs/wingsdk/src/fs/index.ts @@ -0,0 +1 @@ +export * from "./fs"; diff --git a/libs/wingsdk/src/index.ts b/libs/wingsdk/src/index.ts index a87907c2bf5..27b0c7aaf93 100644 --- a/libs/wingsdk/src/index.ts +++ b/libs/wingsdk/src/index.ts @@ -2,6 +2,7 @@ export * as cloud from "./cloud"; export * as core from "./core"; export * as ex from "./ex"; +export * as fs from "./fs"; export * as http from "./http"; export * as math from "./math"; export * as regex from "./regex"; diff --git a/libs/wingsdk/test/fs/fs.test.ts b/libs/wingsdk/test/fs/fs.test.ts new file mode 100644 index 00000000000..9ea5c1c8064 --- /dev/null +++ b/libs/wingsdk/test/fs/fs.test.ts @@ -0,0 +1,86 @@ +import { test, expect } from "vitest"; +import { Util as fs } from "../../src/fs/fs"; +import { Json } from "../../src/std"; + +const data = `{ + "foo": "bar", + "arr": [ + 1, + 2, + 3, + "test", + { + "foo": "bar" + } + ] +}`; +const jsonObj = JSON.parse(data) as Json; + +function randomStr(): string { + return (Math.random() + 1).toString(36).substring(7); +} + +test("write, read and remove file", async () => { + const filename = `testfile-${randomStr()}.txt`; + fs.writeFile(filename, data); + + const exist1 = fs.exists(filename); + expect(exist1).toEqual(true); + + const text = fs.readFile(filename); + expect(text).toEqual(text); + + fs.remove(filename); + const exist2 = fs.exists(filename); + expect(exist2).toEqual(false); +}); + +test("make directory recursively", async () => { + const baseDir = `testdir-${randomStr()}`; + const dirpath = `${baseDir}/test`; + fs.mkdir(dirpath, { recursive: true }); + + const dirContent = fs.readdir(dirpath); + expect(dirContent.length).toEqual(0); + + fs.remove(baseDir, { force: true, recursive: true }); + const exist = fs.exists(dirpath); + expect(exist).toEqual(false); +}); + +test("make temp directory", async () => { + const prefix = `prefix-${randomStr()}`; + const dirpath = fs.mkdtemp(prefix); + expect(dirpath.split("/").pop()).match(new RegExp(`${prefix}`)); + + let exist = fs.exists(dirpath); + expect(exist).toEqual(true); + + fs.remove(dirpath, { recursive: true }); + exist = fs.exists(dirpath); + expect(exist).toEqual(false); +}); + +test("write and read json", async () => { + const filename = `testfile-${randomStr()}.json`; + fs.writeJson(filename, jsonObj); + + const obj = fs.readJson(filename); + expect(obj).toEqual(jsonObj); + + fs.remove(filename); + const exist = fs.exists(filename); + expect(exist).toEqual(false); +}); + +test("write and read yaml", async () => { + const filename = `testfile-${randomStr()}.yaml`; + fs.writeYaml(filename, jsonObj, jsonObj); + + const objs = fs.readYaml(filename); + expect(objs).toEqual([jsonObj, jsonObj]); + + fs.remove(filename); + const exist = fs.exists(filename); + expect(exist).toEqual(false); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4201fe258b6..5056380403d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1197,6 +1197,9 @@ importers: ioredis: specifier: ^5.3.2 version: 5.3.2 + js-yaml: + specifier: ^4.1.0 + version: 4.1.0 jsonschema: specifier: ^1.4.1 version: 1.4.1 @@ -1222,6 +1225,9 @@ importers: '@types/fs-extra': specifier: ^11.0.1 version: 11.0.1 + '@types/js-yaml': + specifier: ^4.0.6 + version: 4.0.6 '@types/mime-types': specifier: ^2.1.1 version: 2.1.1 @@ -9265,6 +9271,10 @@ packages: pretty-format: 29.6.3 dev: true + /@types/js-yaml@4.0.6: + resolution: {integrity: sha512-ACTuifTSIIbyksx2HTon3aFtCKWcID7/h3XEmRpDYdMCXxPbl+m9GteOJeaAkiAta/NJaSFuA7ahZ0NkwajDSw==} + dev: true + /@types/json-schema@7.0.12: resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} @@ -12938,7 +12948,7 @@ packages: dependencies: semver: 7.5.4 shelljs: 0.8.5 - typescript: 5.3.0-dev.20231003 + typescript: 5.3.0-dev.20231005 dev: true /dset@3.1.2: @@ -22159,8 +22169,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - /typescript@5.3.0-dev.20231003: - resolution: {integrity: sha512-OyUdPjo1wNYs+PVDr9ARcEPs0aOqdxterOFzQzWK6DR4tsadKPbrOx8JgTOvSUwhkNOxBOEh7BonqV2uNsTxvA==} + /typescript@5.3.0-dev.20231005: + resolution: {integrity: sha512-Twm3wBauTO94CSWbjXFMpsHsbaOUVssreq6pUo4wr8YsaIp0jim8EeCa9LfawFetQ+P4PODMmiM+uBhhWRVX0Q==} engines: {node: '>=14.17'} hasBin: true dev: true diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/basic.main.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/basic.main.w_compile_tf-aws.md new file mode 100644 index 00000000000..f5af8713a79 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/basic.main.w_compile_tf-aws.md @@ -0,0 +1,124 @@ +# [basic.main.w](../../../../../../examples/tests/sdk_tests/fs/basic.main.w) | compile | tf-aws + +## inflight.$Closure1-1.js +```js +module.exports = function({ $data, $filename, $fs_Util }) { + class $Closure1 { + constructor({ }) { + const $obj = (...args) => this.handle(...args); + Object.setPrototypeOf($obj, this); + return $obj; + } + async handle() { + (await $fs_Util.writeFile($filename,$data)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $fs_Util.exists($filename)),true)))}; + const content = (await $fs_Util.readFile($filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: content == data")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(content,$data)))}; + (await $fs_Util.remove($filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == false")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $fs_Util.exists($filename)),false)))}; + const nilContent = (await $fs_Util.tryReadFile($filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: nilContent == nil")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(nilContent,undefined)))}; + } + } + return $Closure1; +} + +``` + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.17.0" + }, + "outputs": { + "root": { + "Default": { + "cloud.TestRunner": { + "TestFunctionArns": "WING_TEST_RUNNER_FUNCTION_ARNS" + } + } + } + } + }, + "output": { + "WING_TEST_RUNNER_FUNCTION_ARNS": { + "value": "[]" + } + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +const $stdlib = require('@winglang/sdk'); +const $plugins = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLUGIN_PATHS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const fs = $stdlib.fs; +class $Root extends $stdlib.std.Resource { + constructor(scope, id) { + super(scope, id); + class $Closure1 extends $stdlib.std.Resource { + constructor(scope, id, ) { + super(scope, id); + (std.Node.of(this)).hidden = true; + } + static _toInflightType(context) { + return ` + require("./inflight.$Closure1-1.js")({ + $data: ${context._lift(data)}, + $filename: ${context._lift(filename)}, + $fs_Util: ${context._lift($stdlib.core.toLiftableModuleType(fs.Util, "@winglang/sdk/fs", "Util"))}, + }) + `; + } + _toInflight() { + return ` + (await (async () => { + const $Closure1Client = ${$Closure1._toInflightType(this)}; + const client = new $Closure1Client({ + }); + if (client.$inflight_init) { await client.$inflight_init(); } + return client; + })()) + `; + } + _getInflightOps() { + return ["handle", "$inflight_init"]; + } + _registerBind(host, ops) { + if (ops.includes("handle")) { + $Closure1._registerBindObject(data, host, []); + $Closure1._registerBindObject(filename, host, []); + } + super._registerBind(host, ops); + } + } + const filename = "hello.txt"; + const data = "Hello, Wing!"; + (fs.Util.writeFile(filename,data)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((fs.Util.exists(filename)),true)))}; + const content = (fs.Util.readFile(filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: content == data")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(content,data)))}; + (fs.Util.remove(filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == false")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((fs.Util.exists(filename)),false)))}; + const nilContent = (fs.Util.tryReadFile(filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: nilContent == nil")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(nilContent,undefined)))}; + this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:inflight file basic operations",new $Closure1(this,"$Closure1")); + } +} +const $App = $stdlib.core.App.for(process.env.WING_TARGET); +new $App({ outdir: $outdir, name: "basic.main", rootConstruct: $Root, plugins: $plugins, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }).synth(); + +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/basic.main.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/basic.main.w_test_sim.md new file mode 100644 index 00000000000..cd3caf3831d --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/basic.main.w_test_sim.md @@ -0,0 +1,12 @@ +# [basic.main.w](../../../../../../examples/tests/sdk_tests/fs/basic.main.w) | test | sim + +## stdout.log +```log +pass ─ basic.main.wsim » root/env0/test:inflight file basic operations + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/directory.main.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/directory.main.w_compile_tf-aws.md new file mode 100644 index 00000000000..69336a311b9 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/directory.main.w_compile_tf-aws.md @@ -0,0 +1,142 @@ +# [directory.main.w](../../../../../../examples/tests/sdk_tests/fs/directory.main.w) | compile | tf-aws + +## inflight.$Closure1-1.js +```js +module.exports = function({ $dirname, $filename, $fs_Util, $regex_Util }) { + class $Closure1 { + constructor({ }) { + const $obj = (...args) => this.handle(...args); + Object.setPrototypeOf($obj, this); + return $obj; + } + async handle() { + (await $fs_Util.mkdir($dirname)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(dirname) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $fs_Util.exists($dirname)),true)))}; + try { + (await $fs_Util.mkdir($dirname)); + } + catch ($error_e) { + const e = $error_e.message; + {((cond) => {if (!cond) throw new Error("assertion failed: regex.match(\"^EEXIST: file already exists\", e) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $regex_Util.match("^EEXIST: file already exists",e)),true)))}; + } + (await $fs_Util.writeFile((await $fs_Util.join($dirname,$filename)),"")); + const files = (await $fs_Util.readdir($dirname)); + {((cond) => {if (!cond) throw new Error("assertion failed: files.length == 1")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(files.length,1)))}; + (await $fs_Util.remove($dirname,({"recursive": true}))); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(dirname) == false")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $fs_Util.exists($dirname)),false)))}; + const nilFiles = (await $fs_Util.tryReaddir($dirname)); + {((cond) => {if (!cond) throw new Error("assertion failed: nilFiles == nil")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(nilFiles,undefined)))}; + } + } + return $Closure1; +} + +``` + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.17.0" + }, + "outputs": { + "root": { + "Default": { + "cloud.TestRunner": { + "TestFunctionArns": "WING_TEST_RUNNER_FUNCTION_ARNS" + } + } + } + } + }, + "output": { + "WING_TEST_RUNNER_FUNCTION_ARNS": { + "value": "[]" + } + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +const $stdlib = require('@winglang/sdk'); +const $plugins = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLUGIN_PATHS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const fs = $stdlib.fs; +const regex = $stdlib.regex; +class $Root extends $stdlib.std.Resource { + constructor(scope, id) { + super(scope, id); + class $Closure1 extends $stdlib.std.Resource { + constructor(scope, id, ) { + super(scope, id); + (std.Node.of(this)).hidden = true; + } + static _toInflightType(context) { + return ` + require("./inflight.$Closure1-1.js")({ + $dirname: ${context._lift(dirname)}, + $filename: ${context._lift(filename)}, + $fs_Util: ${context._lift($stdlib.core.toLiftableModuleType(fs.Util, "@winglang/sdk/fs", "Util"))}, + $regex_Util: ${context._lift($stdlib.core.toLiftableModuleType(regex.Util, "@winglang/sdk/regex", "Util"))}, + }) + `; + } + _toInflight() { + return ` + (await (async () => { + const $Closure1Client = ${$Closure1._toInflightType(this)}; + const client = new $Closure1Client({ + }); + if (client.$inflight_init) { await client.$inflight_init(); } + return client; + })()) + `; + } + _getInflightOps() { + return ["handle", "$inflight_init"]; + } + _registerBind(host, ops) { + if (ops.includes("handle")) { + $Closure1._registerBindObject(dirname, host, []); + $Closure1._registerBindObject(filename, host, []); + } + super._registerBind(host, ops); + } + } + const dirname = "wingdir"; + const filename = "temp.txt"; + (fs.Util.mkdir(dirname)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(dirname) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((fs.Util.exists(dirname)),true)))}; + try { + (fs.Util.mkdir(dirname)); + } + catch ($error_e) { + const e = $error_e.message; + {((cond) => {if (!cond) throw new Error("assertion failed: regex.match(\"^EEXIST: file already exists\", e) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((regex.Util.match("^EEXIST: file already exists",e)),true)))}; + } + (fs.Util.writeFile((fs.Util.join(dirname,filename)),"")); + const files = (fs.Util.readdir(dirname)); + {((cond) => {if (!cond) throw new Error("assertion failed: files.length == 1")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(files.length,1)))}; + (fs.Util.remove(dirname,({"recursive": true}))); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(dirname) == false")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((fs.Util.exists(dirname)),false)))}; + const nilFiles = (fs.Util.tryReaddir(dirname)); + {((cond) => {if (!cond) throw new Error("assertion failed: nilFiles == nil")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(nilFiles,undefined)))}; + this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:inflight create normal directory",new $Closure1(this,"$Closure1")); + } +} +const $App = $stdlib.core.App.for(process.env.WING_TARGET); +new $App({ outdir: $outdir, name: "directory.main", rootConstruct: $Root, plugins: $plugins, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }).synth(); + +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/directory.main.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/directory.main.w_test_sim.md new file mode 100644 index 00000000000..7af60bfa03f --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/directory.main.w_test_sim.md @@ -0,0 +1,12 @@ +# [directory.main.w](../../../../../../examples/tests/sdk_tests/fs/directory.main.w) | test | sim + +## stdout.log +```log +pass ─ directory.main.wsim » root/env0/test:inflight create normal directory + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/json.main.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/json.main.w_compile_tf-aws.md new file mode 100644 index 00000000000..83a0d95c485 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/json.main.w_compile_tf-aws.md @@ -0,0 +1,141 @@ +# [json.main.w](../../../../../../examples/tests/sdk_tests/fs/json.main.w) | compile | tf-aws + +## inflight.$Closure1-1.js +```js +module.exports = function({ $data, $filename, $fs_Util, $regex_Util, $std_Json }) { + class $Closure1 { + constructor({ }) { + const $obj = (...args) => this.handle(...args); + Object.setPrototypeOf($obj, this); + return $obj; + } + async handle() { + try { + (await $fs_Util.writeFile($filename,"invalid content")); + (await $fs_Util.readJson($filename)); + } + catch ($error_e) { + const e = $error_e.message; + {((cond) => {if (!cond) throw new Error("assertion failed: regex.match(\"^Unexpected token\", e) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $regex_Util.match("^Unexpected token",e)),true)))}; + } + (await $fs_Util.writeJson($filename,$data)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $fs_Util.exists($filename)),true)))}; + const obj = (await $fs_Util.readJson($filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: Json.stringify(obj) == Json.stringify(data)")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([obj]),((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([$data]))))}; + (await $fs_Util.remove($filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == false")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $fs_Util.exists($filename)),false)))}; + {((cond) => {if (!cond) throw new Error("assertion failed: fs.tryReadJson(filename) == nil")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $fs_Util.tryReadJson($filename)),undefined)))}; + } + } + return $Closure1; +} + +``` + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.17.0" + }, + "outputs": { + "root": { + "Default": { + "cloud.TestRunner": { + "TestFunctionArns": "WING_TEST_RUNNER_FUNCTION_ARNS" + } + } + } + } + }, + "output": { + "WING_TEST_RUNNER_FUNCTION_ARNS": { + "value": "[]" + } + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +const $stdlib = require('@winglang/sdk'); +const $plugins = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLUGIN_PATHS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const fs = $stdlib.fs; +const regex = $stdlib.regex; +class $Root extends $stdlib.std.Resource { + constructor(scope, id) { + super(scope, id); + class $Closure1 extends $stdlib.std.Resource { + constructor(scope, id, ) { + super(scope, id); + (std.Node.of(this)).hidden = true; + } + static _toInflightType(context) { + return ` + require("./inflight.$Closure1-1.js")({ + $data: ${context._lift(data)}, + $filename: ${context._lift(filename)}, + $fs_Util: ${context._lift($stdlib.core.toLiftableModuleType(fs.Util, "@winglang/sdk/fs", "Util"))}, + $regex_Util: ${context._lift($stdlib.core.toLiftableModuleType(regex.Util, "@winglang/sdk/regex", "Util"))}, + $std_Json: ${context._lift($stdlib.core.toLiftableModuleType(std.Json, "@winglang/sdk/std", "Json"))}, + }) + `; + } + _toInflight() { + return ` + (await (async () => { + const $Closure1Client = ${$Closure1._toInflightType(this)}; + const client = new $Closure1Client({ + }); + if (client.$inflight_init) { await client.$inflight_init(); } + return client; + })()) + `; + } + _getInflightOps() { + return ["handle", "$inflight_init"]; + } + _registerBind(host, ops) { + if (ops.includes("handle")) { + $Closure1._registerBindObject(data, host, []); + $Closure1._registerBindObject(filename, host, []); + } + super._registerBind(host, ops); + } + } + const filename = "test-json.json"; + const data = ({"foo": "bar","arr": [1, 2, 3, "test", ({"foo": "bar"})]}); + try { + (fs.Util.writeFile(filename,"invalid content")); + (fs.Util.readJson(filename)); + } + catch ($error_e) { + const e = $error_e.message; + {((cond) => {if (!cond) throw new Error("assertion failed: regex.match(\"^Unexpected token\", e) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((regex.Util.match("^Unexpected token",e)),true)))}; + } + (fs.Util.writeJson(filename,data)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((fs.Util.exists(filename)),true)))}; + const obj = (fs.Util.readJson(filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: Json.stringify(obj) == Json.stringify(data)")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([obj]),((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([data]))))}; + (fs.Util.remove(filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == false")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((fs.Util.exists(filename)),false)))}; + {((cond) => {if (!cond) throw new Error("assertion failed: fs.tryReadJson(filename) == nil")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((fs.Util.tryReadJson(filename)),undefined)))}; + this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:inflight json operations",new $Closure1(this,"$Closure1")); + } +} +const $App = $stdlib.core.App.for(process.env.WING_TARGET); +new $App({ outdir: $outdir, name: "json.main", rootConstruct: $Root, plugins: $plugins, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }).synth(); + +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/json.main.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/json.main.w_test_sim.md new file mode 100644 index 00000000000..f79d2942450 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/json.main.w_test_sim.md @@ -0,0 +1,12 @@ +# [json.main.w](../../../../../../examples/tests/sdk_tests/fs/json.main.w) | test | sim + +## stdout.log +```log +pass ─ json.main.wsim » root/env0/test:inflight json operations + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/path.main.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/path.main.w_compile_tf-aws.md new file mode 100644 index 00000000000..6013a0ab99f --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/path.main.w_compile_tf-aws.md @@ -0,0 +1,128 @@ +# [path.main.w](../../../../../../examples/tests/sdk_tests/fs/path.main.w) | compile | tf-aws + +## inflight.$Closure1-1.js +```js +module.exports = function({ $from, $fs_Util, $to }) { + class $Closure1 { + constructor({ }) { + const $obj = (...args) => this.handle(...args); + Object.setPrototypeOf($obj, this); + return $obj; + } + async handle() { + let result = (await $fs_Util.join($from,$to)); + {((cond) => {if (!cond) throw new Error("assertion failed: result == \"/a/b/c/d/a/b/e/f\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(result,"/a/b/c/d/a/b/e/f")))}; + result = (await $fs_Util.relative($from,$to)); + {((cond) => {if (!cond) throw new Error("assertion failed: result == \"../../e/f\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(result,"../../e/f")))}; + result = (await $fs_Util.dirname($from)); + {((cond) => {if (!cond) throw new Error("assertion failed: result == \"/a/b/c\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(result,"/a/b/c")))}; + result = (await $fs_Util.basename($from)); + {((cond) => {if (!cond) throw new Error("assertion failed: result == \"d\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(result,"d")))}; + result = (await $fs_Util.resolve($from,$to)); + {((cond) => {if (!cond) throw new Error("assertion failed: result == \"/a/b/e/f\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(result,"/a/b/e/f")))}; + } + } + return $Closure1; +} + +``` + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.17.0" + }, + "outputs": { + "root": { + "Default": { + "cloud.TestRunner": { + "TestFunctionArns": "WING_TEST_RUNNER_FUNCTION_ARNS" + } + } + } + } + }, + "output": { + "WING_TEST_RUNNER_FUNCTION_ARNS": { + "value": "[]" + } + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +const $stdlib = require('@winglang/sdk'); +const $plugins = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLUGIN_PATHS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const fs = $stdlib.fs; +class $Root extends $stdlib.std.Resource { + constructor(scope, id) { + super(scope, id); + class $Closure1 extends $stdlib.std.Resource { + constructor(scope, id, ) { + super(scope, id); + (std.Node.of(this)).hidden = true; + } + static _toInflightType(context) { + return ` + require("./inflight.$Closure1-1.js")({ + $from: ${context._lift(from)}, + $fs_Util: ${context._lift($stdlib.core.toLiftableModuleType(fs.Util, "@winglang/sdk/fs", "Util"))}, + $to: ${context._lift(to)}, + }) + `; + } + _toInflight() { + return ` + (await (async () => { + const $Closure1Client = ${$Closure1._toInflightType(this)}; + const client = new $Closure1Client({ + }); + if (client.$inflight_init) { await client.$inflight_init(); } + return client; + })()) + `; + } + _getInflightOps() { + return ["handle", "$inflight_init"]; + } + _registerBind(host, ops) { + if (ops.includes("handle")) { + $Closure1._registerBindObject(from, host, []); + $Closure1._registerBindObject(to, host, []); + } + super._registerBind(host, ops); + } + } + const from = "/a/b/c/d"; + const to = "/a/b/e/f"; + let result = (fs.Util.join(from,to)); + {((cond) => {if (!cond) throw new Error("assertion failed: result == \"/a/b/c/d/a/b/e/f\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(result,"/a/b/c/d/a/b/e/f")))}; + result = (fs.Util.relative(from,to)); + {((cond) => {if (!cond) throw new Error("assertion failed: result == \"../../e/f\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(result,"../../e/f")))}; + result = (fs.Util.dirname(from)); + {((cond) => {if (!cond) throw new Error("assertion failed: result == \"/a/b/c\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(result,"/a/b/c")))}; + result = (fs.Util.basename(from)); + {((cond) => {if (!cond) throw new Error("assertion failed: result == \"d\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(result,"d")))}; + result = (fs.Util.resolve(from,to)); + {((cond) => {if (!cond) throw new Error("assertion failed: result == \"/a/b/e/f\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(result,"/a/b/e/f")))}; + this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:inflight path conversion",new $Closure1(this,"$Closure1")); + } +} +const $App = $stdlib.core.App.for(process.env.WING_TARGET); +new $App({ outdir: $outdir, name: "path.main", rootConstruct: $Root, plugins: $plugins, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }).synth(); + +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/path.main.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/path.main.w_test_sim.md new file mode 100644 index 00000000000..05b2fae1072 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/path.main.w_test_sim.md @@ -0,0 +1,12 @@ +# [path.main.w](../../../../../../examples/tests/sdk_tests/fs/path.main.w) | test | sim + +## stdout.log +```log +pass ─ path.main.wsim » root/env0/test:inflight path conversion + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/temp_dir.main.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/temp_dir.main.w_compile_tf-aws.md new file mode 100644 index 00000000000..88766b875f2 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/temp_dir.main.w_compile_tf-aws.md @@ -0,0 +1,105 @@ +# [temp_dir.main.w](../../../../../../examples/tests/sdk_tests/fs/temp_dir.main.w) | compile | tf-aws + +## inflight.$Closure1-1.js +```js +module.exports = function({ $fs_Util }) { + class $Closure1 { + constructor({ }) { + const $obj = (...args) => this.handle(...args); + Object.setPrototypeOf($obj, this); + return $obj; + } + async handle() { + const tmpdir = (await $fs_Util.mkdtemp()); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(tmpdir) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $fs_Util.exists(tmpdir)),true)))}; + (await $fs_Util.remove(tmpdir,({"recursive": true}))); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(tmpdir) == false")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $fs_Util.exists(tmpdir)),false)))}; + } + } + return $Closure1; +} + +``` + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.17.0" + }, + "outputs": { + "root": { + "Default": { + "cloud.TestRunner": { + "TestFunctionArns": "WING_TEST_RUNNER_FUNCTION_ARNS" + } + } + } + } + }, + "output": { + "WING_TEST_RUNNER_FUNCTION_ARNS": { + "value": "[]" + } + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +const $stdlib = require('@winglang/sdk'); +const $plugins = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLUGIN_PATHS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const fs = $stdlib.fs; +class $Root extends $stdlib.std.Resource { + constructor(scope, id) { + super(scope, id); + class $Closure1 extends $stdlib.std.Resource { + constructor(scope, id, ) { + super(scope, id); + (std.Node.of(this)).hidden = true; + } + static _toInflightType(context) { + return ` + require("./inflight.$Closure1-1.js")({ + $fs_Util: ${context._lift($stdlib.core.toLiftableModuleType(fs.Util, "@winglang/sdk/fs", "Util"))}, + }) + `; + } + _toInflight() { + return ` + (await (async () => { + const $Closure1Client = ${$Closure1._toInflightType(this)}; + const client = new $Closure1Client({ + }); + if (client.$inflight_init) { await client.$inflight_init(); } + return client; + })()) + `; + } + _getInflightOps() { + return ["handle", "$inflight_init"]; + } + } + const tmpdir = (fs.Util.mkdtemp()); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(tmpdir) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((fs.Util.exists(tmpdir)),true)))}; + (fs.Util.remove(tmpdir,({"recursive": true}))); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(tmpdir) == false")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((fs.Util.exists(tmpdir)),false)))}; + this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:inflight create temporary directory",new $Closure1(this,"$Closure1")); + } +} +const $App = $stdlib.core.App.for(process.env.WING_TARGET); +new $App({ outdir: $outdir, name: "temp_dir.main", rootConstruct: $Root, plugins: $plugins, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }).synth(); + +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/temp_dir.main.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/temp_dir.main.w_test_sim.md new file mode 100644 index 00000000000..0548f3a6054 --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/temp_dir.main.w_test_sim.md @@ -0,0 +1,12 @@ +# [temp_dir.main.w](../../../../../../examples/tests/sdk_tests/fs/temp_dir.main.w) | test | sim + +## stdout.log +```log +pass ─ temp_dir.main.wsim » root/env0/test:inflight create temporary directory + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/yaml.main.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/yaml.main.w_compile_tf-aws.md new file mode 100644 index 00000000000..866e9f5b54f --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/yaml.main.w_compile_tf-aws.md @@ -0,0 +1,125 @@ +# [yaml.main.w](../../../../../../examples/tests/sdk_tests/fs/yaml.main.w) | compile | tf-aws + +## inflight.$Closure1-1.js +```js +module.exports = function({ $data, $filename, $fs_Util, $std_Json }) { + class $Closure1 { + constructor({ }) { + const $obj = (...args) => this.handle(...args); + Object.setPrototypeOf($obj, this); + return $obj; + } + async handle() { + (await $fs_Util.writeYaml($filename,$data,$data)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $fs_Util.exists($filename)),true)))}; + const objs = (await $fs_Util.readYaml($filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: objs.length == 2")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(objs.length,2)))}; + {((cond) => {if (!cond) throw new Error("assertion failed: Json.stringify(objs.at(0)) == Json.stringify(data)")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([(await objs.at(0))]),((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([$data]))))}; + {((cond) => {if (!cond) throw new Error("assertion failed: Json.stringify(objs.at(1)) == Json.stringify(data)")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([(await objs.at(1))]),((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([$data]))))}; + (await $fs_Util.remove($filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == false")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((await $fs_Util.exists($filename)),false)))}; + } + } + return $Closure1; +} + +``` + +## main.tf.json +```json +{ + "//": { + "metadata": { + "backend": "local", + "stackName": "root", + "version": "0.17.0" + }, + "outputs": { + "root": { + "Default": { + "cloud.TestRunner": { + "TestFunctionArns": "WING_TEST_RUNNER_FUNCTION_ARNS" + } + } + } + } + }, + "output": { + "WING_TEST_RUNNER_FUNCTION_ARNS": { + "value": "[]" + } + }, + "provider": { + "aws": [ + {} + ] + } +} +``` + +## preflight.js +```js +const $stdlib = require('@winglang/sdk'); +const $plugins = ((s) => !s ? [] : s.split(';'))(process.env.WING_PLUGIN_PATHS); +const $outdir = process.env.WING_SYNTH_DIR ?? "."; +const $wing_is_test = process.env.WING_IS_TEST === "true"; +const std = $stdlib.std; +const fs = $stdlib.fs; +class $Root extends $stdlib.std.Resource { + constructor(scope, id) { + super(scope, id); + class $Closure1 extends $stdlib.std.Resource { + constructor(scope, id, ) { + super(scope, id); + (std.Node.of(this)).hidden = true; + } + static _toInflightType(context) { + return ` + require("./inflight.$Closure1-1.js")({ + $data: ${context._lift(data)}, + $filename: ${context._lift(filename)}, + $fs_Util: ${context._lift($stdlib.core.toLiftableModuleType(fs.Util, "@winglang/sdk/fs", "Util"))}, + $std_Json: ${context._lift($stdlib.core.toLiftableModuleType(std.Json, "@winglang/sdk/std", "Json"))}, + }) + `; + } + _toInflight() { + return ` + (await (async () => { + const $Closure1Client = ${$Closure1._toInflightType(this)}; + const client = new $Closure1Client({ + }); + if (client.$inflight_init) { await client.$inflight_init(); } + return client; + })()) + `; + } + _getInflightOps() { + return ["handle", "$inflight_init"]; + } + _registerBind(host, ops) { + if (ops.includes("handle")) { + $Closure1._registerBindObject(data, host, []); + $Closure1._registerBindObject(filename, host, []); + } + super._registerBind(host, ops); + } + } + const filename = "test-yaml.yaml"; + const data = ({"foo": "bar","arr": [1, 2, 3, "test", ({"foo": "bar"})]}); + (fs.Util.writeYaml(filename,data,data)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == true")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((fs.Util.exists(filename)),true)))}; + const objs = (fs.Util.readYaml(filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: objs.length == 2")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(objs.length,2)))}; + {((cond) => {if (!cond) throw new Error("assertion failed: Json.stringify(objs.at(0)) == Json.stringify(data)")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([(objs.at(0))]),((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([data]))))}; + {((cond) => {if (!cond) throw new Error("assertion failed: Json.stringify(objs.at(1)) == Json.stringify(data)")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([(objs.at(1))]),((args) => { return JSON.stringify(args[0], null, args[1]?.indent) })([data]))))}; + (fs.Util.remove(filename)); + {((cond) => {if (!cond) throw new Error("assertion failed: fs.exists(filename) == false")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })((fs.Util.exists(filename)),false)))}; + this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:inflight yaml operations",new $Closure1(this,"$Closure1")); + } +} +const $App = $stdlib.core.App.for(process.env.WING_TARGET); +new $App({ outdir: $outdir, name: "yaml.main", rootConstruct: $Root, plugins: $plugins, isTestEnvironment: $wing_is_test, entrypointDir: process.env['WING_SOURCE_DIR'], rootId: process.env['WING_ROOT_ID'] }).synth(); + +``` + diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/yaml.main.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/yaml.main.w_test_sim.md new file mode 100644 index 00000000000..aae8441d32a --- /dev/null +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/fs/yaml.main.w_test_sim.md @@ -0,0 +1,12 @@ +# [yaml.main.w](../../../../../../examples/tests/sdk_tests/fs/yaml.main.w) | test | sim + +## stdout.log +```log +pass ─ yaml.main.wsim » root/env0/test:inflight yaml operations + + +Tests 1 passed (1) +Test Files 1 passed (1) +Duration +``` +