diff --git a/.gitignore b/.gitignore index 8d8c8519..e5f0cf93 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ node_modules .merlin .bsb.lock -packages/tests/src/core/**/*_test.bs.mjs +packages/tests/src/core/**/*_test.res.mjs lib coverage dist diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3e56b7e..162d61ab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -123,6 +123,23 @@ LoginSchema.parse({ email: "", password: "" }); LoginSchema.parse({ email: "jane@example.com", password: "12345678" }); ``` +ArkType + +```ts +import { type } from "arktype@2.0.4"; + +const loginSchema = type({ + email: "string.email", + password: "string > 7", +}); + +loginSchema({ email: "", password: "" }); + +loginSchema({ email: "jane@example.com", password: "12345678" }); +``` + +https://bundlejs.com/?q=arktype%402.0.4&treeshake=%5B*%5D&text=%22const+loginSchema+%3D+type%28%7B%5Cn++email%3A+%5C%22string.email%5C%22%2C%5Cn++password%3A+%5C%22string+%3E+7%5C%22%2C%5Cn%7D%29%3B%5Cn%5CnloginSchema%28%7B+email%3A+%5C%22%5C%22%2C+password%3A+%5C%22%5C%22+%7D%29%3B%5Cn%5CnloginSchema%28%7B+email%3A+%5C%22jane%40example.com%5C%22%2C+password%3A+%5C%2212345678%5C%22+%7D%29%3B%22 + ## License By contributing your code to the rescript-schema GitHub repository, you agree to license your contribution under the MIT license. diff --git a/IDEAS.md b/IDEAS.md index 05a5ca7d..a026b08f 100644 --- a/IDEAS.md +++ b/IDEAS.md @@ -20,11 +20,17 @@ let trimContract: S.contract string> = S.contract(s => { ## v9.1 -- Add s.strict s.strip to ppx -- Add S.test +- [x] Update object type validation +- [ ] Support standard schema +- [ ] Make rescript an optional peer dependency ## v10 +- Rename S.to to S.reshape +- Change S.classify to something like S.input/S.output +- Add refinement info to the tagged type +- Add S.string->S.coerce(S.int) to coerce string to int and other types +- Add S.codegen - Add schema input to the error ??? What about build errors? - Remove Literal.parse in favor of S.literal and make it create Object/Tuple schema instead of Literal(Object) - S.transform(s => { @@ -39,7 +45,6 @@ let trimContract: S.contract string> = S.contract(s => { ## v??? -- Add S.string->S.coerce(S.int) to coerce string to int and other types - Rename S.inline to S.toRescriptCode + Codegen type + Codegen schema using type - Make `error.reason` tree-shakeable - S.toJSON/S.castToJson ??? diff --git a/README.md b/README.md index eb7600a2..997aca48 100644 --- a/README.md +++ b/README.md @@ -13,21 +13,24 @@ Highlights: - Works with plain JavaScript, TypeScript, and ReScript. You don't need to use any compiler. - The **fastest** parsing and validation library in the entire JavaScript ecosystem ([benchmark](https://moltar.github.io/typescript-runtime-type-benchmarks/)) - Small JS footprint & tree-shakable API ([Comparison with Zod and Valibot](#comparison)) -- Describe transformations in a schema without a performance loss +- Implements the [Standard Schema](https://standardschema.dev/) spec +- Declarative transformations in a schema without a performance loss - Reverse schema and convert values to the initial format (serializing) - Detailed and easy to understand error messages - Support for asynchronous transformations - Immutable API with 100+ different operation combinations - Easy to create _recursive_ schema - Opt-in strict mode for object schema to prevent unknown fields with ability to change it for the whole project -- Opt-in ReScript PPX to generate schema from type definition +- Opt-in ReScript Schema codegen from type definition (ppx) -Also, it has declarative API allowing you to use **rescript-schema** as a building block for other tools, such as: +Also, you can use **rescript-schema** as a building block for your tools. And there are many existing ones: - [rescript-rest](https://github.com/DZakh/rescript-rest) - RPC-like client, contract, and server implementation for a pure REST API - [rescript-envsafe](https://github.com/DZakh/rescript-envsafe) - Makes sure you don't accidentally deploy apps with missing or invalid environment variables - [rescript-json-schema](https://github.com/DZakh/rescript-json-schema) - Typesafe JSON schema for ReScript +- [rescript-stripe](https://github.com/enviodev/rescript-stripe) - Describe and manage Stripe billing in a declarative way with code - Internal form library at [Carla](https://www.carla.se/) +- [tRPC](https://trpc.io/), [TanStack Form](https://tanstack.com/form), [TanStack Router](https://tanstack.com/router), [Hono](https://hono.dev/) and 15+ more using [Standard Schema](https://standardschema.dev/) spec ## Documentation @@ -36,7 +39,7 @@ Also, it has declarative API allowing you to use **rescript-schema** as a buildi - [For PPX users](/packages/rescript-schema-ppx/README.md) - [For library maintainers](/docs/integration-guide.md) -## Content +## Resources - Building and consuming REST API in ReScript with rescript-rest and Fastify ([YouTube](https://youtu.be/37FY6a-zY20?si=72zT8Gecs5vmDPlD)) - ReScript Schema V9 Changes Overview ([Dev.to](https://dev.to/dzakh/rescript-schema-v9-zod-like-library-to-the-next-level-1dn6)) @@ -51,12 +54,12 @@ Besides the individual bundle size, the overall size of the library is also sign At the same time **rescript-schema** is the fastest composable validation library in the entire JavaScript ecosystem. This is achieved because of the JIT approach when an ultra optimized validator is created using `eval`. -| | rescript-schema@9.0.0 | Zod@3.24.1 | Valibot@0.42.1 | -| ---------------------------------------- | --------------------- | --------------- | -------------- | -| **Total size** (minified + gzipped) | 11 kB | 14.8 kB | 10.5 kB | -| **Example size** (minified + gzipped) | 4.45 kB | 13.5 kB | 1.22 kB | -| **Parse with the same schema** | 100,070 ops/ms | 1,277 ops/ms | 3,881 ops/ms | -| **Create schema & parse once** | 179 ops/ms | 112 ops/ms | 2,521 ops/ms | -| **Eval-free** | ❌ | ✅ | ✅ | -| **Codegen-free** (Doesn't need compiler) | ✅ | ✅ | ✅ | -| **Ecosystem** | ⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️ | +| | rescript-schema@9.1.0 | Zod@3.24.1 | Valibot@0.42.1 | ArkType@2.0.4 | +| ---------------------------------------- | --------------------- | --------------- | -------------- | ------------- | +| **Total size** (minified + gzipped) | 11 kB | 14.8 kB | 10.5 kB | 40.8 kB | +| **Example size** (minified + gzipped) | 4.45 kB | 13.5 kB | 1.22 kB | 40.7 kB | +| **Parse with the same schema** | 93,491 ops/ms | 1,191 ops/ms | 3,540 ops/ms | 84,772 ops/ms | +| **Create schema & parse once** | 166 ops/ms | 93 ops/ms | 2,302 ops/ms | 13 ops/ms | +| **Eval-free** | ❌ | ✅ | ✅ | ❓ | +| **Codegen-free** (Doesn't need compiler) | ✅ | ✅ | ✅ | ✅ | +| **Ecosystem** | ⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️ | ⭐️⭐️ | diff --git a/docs/js-usage.md b/docs/js-usage.md index d6e97821..bc2e4045 100644 --- a/docs/js-usage.md +++ b/docs/js-usage.md @@ -41,6 +41,7 @@ - [Built-in operations](#built-in-operations) - [`compile`](#compile) - [`reverse`](#reverse) + - [`standard`](#standard) - [`name`](#name) - [`setName`](#setname) - [Error handling](#error-handling) @@ -52,10 +53,10 @@ ## Install ```sh -npm install rescript-schema rescript@11 +npm install rescript-schema ``` -> 🧠 Even though `rescript` is a peer dependency, you don't need to use the compiler. It's only needed for a few lightweight runtime helpers. +> 🧠 You don't need to install [ReScript](https://rescript-lang.org/) compiler for the library to work. ## Basic usage @@ -828,6 +829,15 @@ S.parseOrThrow(123, reversed); Reverses the schema. This gets especially magical for schemas with transformations 🪄 +### **`standard`** + +```ts +S.standard(S.string); +// Returns StandardSchemaV1 +``` + +Converts ReScript Schema into [Standard Schema](https://standardschema.dev/). You can use it to integrate with 20+ other libraries. Checkout the [Standard Schema](https://standardschema.dev/) to learn more. 👀 + ### **`name`** ```ts diff --git a/docs/rescript-usage.md b/docs/rescript-usage.md index 3d754a26..1fa713ea 100644 --- a/docs/rescript-usage.md +++ b/docs/rescript-usage.md @@ -169,7 +169,7 @@ Compiled parser code ```javascript (i) => { - if (!i || i.constructor !== Object) { + if (typeof i !== "object" || !i) { e[7](i); } let v0 = i["Id"], @@ -1508,7 +1508,7 @@ let schema = S.object(s => s.field("abc", S.int))->S.removeTypeValidation { "abc": 123, -}->S.parseOrThrow(schema) // This doesn't have `if (!i || i.constructor !== Object) {` check. But field types are still validated. +}->S.parseOrThrow(schema) // This doesn't have `if (typeof i !== "object" || !i) {` check. But field types are still validated. // 123 ``` diff --git a/package.json b/package.json index c25a075c..165b7f49 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "rescript-schema", - "version": "9.1.0", + "version": "9.2.0", + "private": true, "description": "🧬 The fastest parser in the entire JavaScript ecosystem with a focus on small bundle size and top-notch DX", "keywords": [ "ReScript", @@ -35,21 +36,21 @@ "files": [ "dist", "src/S_Core.res", - "src/S_Core.bs.js", - "src/S_Core.bs.mjs", + "src/S_Core.res.js", + "src/S_Core.res.mjs", "src/S.res", "src/S.resi", - "src/S.bs.js", - "src/S.bs.mjs", + "src/S.res.js", + "src/S.res.mjs", "src/S.d.ts", "RescriptSchema.gen.d.ts", "rescript.json" ], "scripts": { - "benchmark": "node ./packages/tests/src/benchmark/Benchmark.bs.mjs", + "benchmark": "node ./packages/tests/src/benchmark/Benchmark.res.mjs", "benchmark:comparison": "node ./packages/tests/src/benchmark/comparison.js", "coverage": "c8 --reporter=lcov npm test", - "build": "node ./packages/prepack/src/Prepack.bs.mjs", + "build": "node ./packages/prepack/src/Prepack.res.mjs", "ppx:install": "node ./packages/rescript-schema-ppx/install.cjs", "res": "rescript -w", "res:build": "rescript build", @@ -63,7 +64,7 @@ "mjs": true }, "files": [ - "packages/tests/src/**/*_test.bs.mjs", + "packages/tests/src/**/*_test.res.mjs", "packages/tests/src/**/*_test.ts" ], "nodeArguments": [ @@ -84,10 +85,16 @@ "tsimp": "2.0.12", "typescript": "4.9.3", "valibot": "0.42.1", - "zod": "3.24.1" + "zod": "3.24.1", + "arktype": "2.0.4" }, "peerDependencies": { "rescript": "11.x" }, + "peerDependenciesMeta": { + "rescript": { + "optional": true + } + }, "packageManager": "pnpm@9.0.5" } diff --git a/packages/prepack/package.json b/packages/prepack/package.json index 50dafc02..b3089943 100644 --- a/packages/prepack/package.json +++ b/packages/prepack/package.json @@ -11,6 +11,8 @@ "dependencies": { "@rescript/core": "1.3.0", "@rollup/plugin-replace": "5.0.2", + "@rollup/plugin-node-resolve": "16.0.0", + "@rollup/plugin-commonjs": "28.0.2", "execa": "7.1.1", "rescript": "11.1.0", "rescript-nodejs": "16.1.0", diff --git a/packages/prepack/rescript.json b/packages/prepack/rescript.json index 9328c838..047bacf2 100644 --- a/packages/prepack/rescript.json +++ b/packages/prepack/rescript.json @@ -1,6 +1,6 @@ { "name": "prepack", - "suffix": ".bs.mjs", + "suffix": ".res.mjs", "package-specs": { "module": "esmodule", "in-source": true diff --git a/packages/prepack/src/Prepack.bs.mjs b/packages/prepack/src/Prepack.bs.mjs deleted file mode 100644 index b523849f..00000000 --- a/packages/prepack/src/Prepack.bs.mjs +++ /dev/null @@ -1,159 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as Fs from "fs"; -import * as Execa from "execa"; -import * as Rollup from "rollup"; -import * as Nodefs from "node:fs"; -import * as Nodepath from "node:path"; -import * as Core__JSON from "@rescript/core/src/Core__JSON.bs.mjs"; -import * as Core__List from "@rescript/core/src/Core__List.bs.mjs"; -import * as Core__Option from "@rescript/core/src/Core__Option.bs.mjs"; -import PluginReplace from "@rollup/plugin-replace"; - -var projectPath = "."; - -var artifactsPath = Nodepath.join(projectPath, "packages/artifacts"); - -var sourePaths = [ - "package.json", - "node_modules", - "src", - "rescript.json", - "README.md", - "RescriptSchema.gen.d.ts", -]; - -var jsInputPath = Nodepath.join(artifactsPath, "src/S.js"); - -function update(json, path, value) { - var dict = Core__JSON.Decode.object(json); - var dict$1 = dict !== undefined ? Object.assign({}, dict) : {}; - if (!path) { - return value; - } - var path$1 = path.tl; - var key = path.hd; - if (path$1) { - dict$1[key] = update(Core__Option.getOr(dict$1[key], {}), path$1, value); - return dict$1; - } else { - dict$1[key] = value; - return dict$1; - } -} - -if (Nodefs.existsSync(artifactsPath)) { - Fs.rmSync(artifactsPath, { - recursive: true, - force: true, - }); -} - -Nodefs.mkdirSync(artifactsPath); - -sourePaths.forEach(function (path) { - Fs.cpSync( - Nodepath.join(projectPath, path), - Nodepath.join(artifactsPath, path), - { - recursive: true, - } - ); -}); - -function updateJsonFile(src, path, value) { - var packageJsonData = Nodefs.readFileSync(src, { - encoding: "utf8", - }); - var packageJson = JSON.parse(packageJsonData.toString()); - var updatedPackageJson = JSON.stringify( - update(packageJson, Core__List.fromArray(path), value), - undefined, - 2 - ); - Nodefs.writeFileSync(src, Buffer.from(updatedPackageJson), { - encoding: "utf8", - }); -} - -Execa.execaSync("npm", ["run", "res:build"], { - cwd: artifactsPath, -}); - -var bundle = await Rollup.rollup({ - input: jsInputPath, - external: [/S_Core\.bs\.mjs/], -}); - -var output = [ - { - file: Nodepath.join(artifactsPath, "dist/S.js"), - format: "cjs", - exports: "named", - plugins: [ - PluginReplace({ - values: Object.fromEntries([ - ["S_Core.bs.mjs", "../src/S_Core.bs.js"], - ["rescript/lib/es6", "rescript/lib/js"], - ]), - }), - ], - }, - { - file: Nodepath.join(artifactsPath, "dist/S.mjs"), - format: "es", - exports: "named", - plugins: [ - PluginReplace({ - values: Object.fromEntries([["S_Core.bs.mjs", "../src/S_Core.bs.mjs"]]), - }), - ], - }, -]; - -for (var idx = 0, idx_finish = output.length; idx < idx_finish; ++idx) { - var outpuOptions = output[idx]; - await bundle.write(outpuOptions); -} - -await bundle.close(); - -Fs.rmSync(Nodepath.join(artifactsPath, "lib"), { - recursive: true, - force: true, -}); - -updateJsonFile( - Nodepath.join(artifactsPath, "rescript.json"), - ["package-specs", "module"], - "commonjs" -); - -updateJsonFile( - Nodepath.join(artifactsPath, "rescript.json"), - ["suffix"], - ".bs.js" -); - -Execa.execaSync("npm", ["run", "res:build"], { - cwd: artifactsPath, -}); - -updateJsonFile( - Nodepath.join(artifactsPath, "package.json"), - ["type"], - "commonjs" -); - -Fs.rmSync(Nodepath.join(artifactsPath, "lib"), { - recursive: true, - force: true, -}); - -Fs.rmSync(Nodepath.join(artifactsPath, "node_modules"), { - recursive: true, - force: true, -}); - -export {}; -/* artifactsPath Not a pure module */ diff --git a/packages/prepack/src/Prepack.res b/packages/prepack/src/Prepack.res index 066ff19f..64eb2cc2 100644 --- a/packages/prepack/src/Prepack.res +++ b/packages/prepack/src/Prepack.res @@ -72,9 +72,18 @@ module Rollup = { @module("@rollup/plugin-replace") external make: options => Plugin.t = "default" } + module NodeResolvePlugin = { + @module("@rollup/plugin-node-resolve") external make: unit => Plugin.t = "nodeResolve" + } + + module CommonjsPluggin = { + @module("@rollup/plugin-commonjs") external make: unit => Plugin.t = "default" + } + module InputOptions = { type t = { input?: string, + plugins?: array, @as("external") external_?: array, } @@ -144,7 +153,13 @@ let updateJsonFile = (~src, ~path, ~value) => { let _ = Execa.sync("npm", ["run", "res:build"], ~options={cwd: artifactsPath}, ()) -let bundle = await Rollup.Bundle.make({input: jsInputPath, external_: [%re("/S_Core\.bs\.mjs/")]}) +let bundle = await Rollup.Bundle.make({ + input: jsInputPath, + // Mark S_Core.res.mjs as external so it's not inlined + // and JS/TS can reuse the same code as ReScript version in mixed codebases + external_: [%re("/S_Core\.res\.mjs/")], + plugins: [], +}) let output: array = [ { file: NodeJs.Path.join2(artifactsPath, "dist/S.js"), @@ -153,7 +168,7 @@ let output: array = [ plugins: [ Rollup.ReplacePlugin.make({ values: Dict.fromArray([ - (`S_Core.bs.mjs`, `../src/S_Core.bs.js`), + (`S_Core.res.mjs`, `../src/S_Core.res.js`), (`rescript/lib/es6`, `rescript/lib/js`), ]), }), @@ -165,7 +180,7 @@ let output: array = [ exports: #named, plugins: [ Rollup.ReplacePlugin.make({ - values: Dict.fromArray([(`S_Core.bs.mjs`, `../src/S_Core.bs.mjs`)]), + values: Dict.fromArray([(`S_Core.res.mjs`, `../src/S_Core.res.mjs`)]), }), ], }, @@ -176,7 +191,20 @@ for idx in 0 to output->Array.length - 1 { } await bundle->Rollup.Bundle.close -// Clean up rescript artifacts so the compiled .bs.js files aren't removed on the .bs.mjs build +let resolveRescriptRuntime = async (~format, ~path) => { + let bundle = await Rollup.Bundle.make({ + input: NodeJs.Path.join2(artifactsPath, path), + plugins: [Rollup.NodeResolvePlugin.make(), Rollup.CommonjsPluggin.make()], + }) + let _ = await bundle->Rollup.Bundle.write({ + file: NodeJs.Path.join2(artifactsPath, path), + format, + exports: #named, + }) + await bundle->Rollup.Bundle.close +} + +// Clean up rescript artifacts so the compiled .res.js files aren't removed on the .res.mjs build FsX.rmSync(NodeJs.Path.join2(artifactsPath, "lib"), {force: true, recursive: true}) updateJsonFile( ~src=NodeJs.Path.join2(artifactsPath, "rescript.json"), @@ -186,7 +214,7 @@ updateJsonFile( updateJsonFile( ~src=NodeJs.Path.join2(artifactsPath, "rescript.json"), ~path=["suffix"], - ~value=JSON.Encode.string(".bs.js"), + ~value=JSON.Encode.string(".res.js"), ) let _ = Execa.sync("npm", ["run", "res:build"], ~options={cwd: artifactsPath}, ()) @@ -199,3 +227,11 @@ updateJsonFile( // Clean up before uploading artifacts FsX.rmSync(NodeJs.Path.join2(artifactsPath, "lib"), {force: true, recursive: true}) FsX.rmSync(NodeJs.Path.join2(artifactsPath, "node_modules"), {force: true, recursive: true}) + +// Inline "rescript" runtime dependencies, +// so it's not required for JS/TS to install ReScript compiler +// And if the package is used together by TS and ReScript, +// the file will be overwritten by compiler and share the same code +await resolveRescriptRuntime(~format=#es, ~path="src/S_Core.res.mjs") +// Event though the generated code is shitty, let's still have it for the sake of some users +await resolveRescriptRuntime(~format=#cjs, ~path="src/S_Core.res.js") diff --git a/packages/prepack/src/Prepack.res.mjs b/packages/prepack/src/Prepack.res.mjs new file mode 100644 index 00000000..326fe9cd --- /dev/null +++ b/packages/prepack/src/Prepack.res.mjs @@ -0,0 +1,178 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Fs from "fs"; +import * as Execa from "execa"; +import * as Rollup from "rollup"; +import * as Nodefs from "node:fs"; +import * as Nodepath from "node:path"; +import * as Core__JSON from "@rescript/core/src/Core__JSON.res.mjs"; +import * as Core__List from "@rescript/core/src/Core__List.res.mjs"; +import * as Core__Option from "@rescript/core/src/Core__Option.res.mjs"; +import PluginReplace from "@rollup/plugin-replace"; +import PluginCommonjs from "@rollup/plugin-commonjs"; +import * as PluginNodeResolve from "@rollup/plugin-node-resolve"; + +var projectPath = "."; + +var artifactsPath = Nodepath.join(projectPath, "packages/artifacts"); + +var sourePaths = [ + "package.json", + "node_modules", + "src", + "rescript.json", + "README.md", + "RescriptSchema.gen.d.ts" +]; + +var jsInputPath = Nodepath.join(artifactsPath, "src/S.js"); + +function update(json, path, value) { + var dict = Core__JSON.Decode.object(json); + var dict$1 = dict !== undefined ? Object.assign({}, dict) : ({}); + if (!path) { + return value; + } + var path$1 = path.tl; + var key = path.hd; + if (path$1) { + dict$1[key] = update(Core__Option.getOr(dict$1[key], {}), path$1, value); + return dict$1; + } else { + dict$1[key] = value; + return dict$1; + } +} + +if (Nodefs.existsSync(artifactsPath)) { + Fs.rmSync(artifactsPath, { + recursive: true, + force: true + }); +} + +Nodefs.mkdirSync(artifactsPath); + +sourePaths.forEach(function (path) { + Fs.cpSync(Nodepath.join(projectPath, path), Nodepath.join(artifactsPath, path), { + recursive: true + }); + }); + +function updateJsonFile(src, path, value) { + var packageJsonData = Nodefs.readFileSync(src, { + encoding: "utf8" + }); + var packageJson = JSON.parse(packageJsonData.toString()); + var updatedPackageJson = JSON.stringify(update(packageJson, Core__List.fromArray(path), value), undefined, 2); + Nodefs.writeFileSync(src, Buffer.from(updatedPackageJson), { + encoding: "utf8" + }); +} + +Execa.execaSync("npm", [ + "run", + "res:build" + ], { + cwd: artifactsPath + }); + +var bundle = await Rollup.rollup({ + input: jsInputPath, + plugins: [], + external: [/S_Core\.res\.mjs/] + }); + +var output = [ + { + file: Nodepath.join(artifactsPath, "dist/S.js"), + format: "cjs", + exports: "named", + plugins: [PluginReplace({ + values: Object.fromEntries([ + [ + "S_Core.res.mjs", + "../src/S_Core.res.js" + ], + [ + "rescript/lib/es6", + "rescript/lib/js" + ] + ]) + })] + }, + { + file: Nodepath.join(artifactsPath, "dist/S.mjs"), + format: "es", + exports: "named", + plugins: [PluginReplace({ + values: Object.fromEntries([[ + "S_Core.res.mjs", + "../src/S_Core.res.mjs" + ]]) + })] + } +]; + +for(var idx = 0 ,idx_finish = output.length; idx < idx_finish; ++idx){ + var outpuOptions = output[idx]; + await bundle.write(outpuOptions); +} + +await bundle.close(); + +async function resolveRescriptRuntime(format, path) { + var bundle = await Rollup.rollup({ + input: Nodepath.join(artifactsPath, path), + plugins: [ + PluginNodeResolve.nodeResolve(), + PluginCommonjs() + ] + }); + await bundle.write({ + file: Nodepath.join(artifactsPath, path), + format: format, + exports: "named" + }); + return await bundle.close(); +} + +Fs.rmSync(Nodepath.join(artifactsPath, "lib"), { + recursive: true, + force: true + }); + +updateJsonFile(Nodepath.join(artifactsPath, "rescript.json"), [ + "package-specs", + "module" + ], "commonjs"); + +updateJsonFile(Nodepath.join(artifactsPath, "rescript.json"), ["suffix"], ".res.js"); + +Execa.execaSync("npm", [ + "run", + "res:build" + ], { + cwd: artifactsPath + }); + +updateJsonFile(Nodepath.join(artifactsPath, "package.json"), ["type"], "commonjs"); + +Fs.rmSync(Nodepath.join(artifactsPath, "lib"), { + recursive: true, + force: true + }); + +Fs.rmSync(Nodepath.join(artifactsPath, "node_modules"), { + recursive: true, + force: true + }); + +await resolveRescriptRuntime("es", "src/S_Core.res.mjs"); + +await resolveRescriptRuntime("cjs", "src/S_Core.res.js"); + +export { + +} +/* artifactsPath Not a pure module */ diff --git a/packages/tests/rescript.json b/packages/tests/rescript.json index ffa16410..09d42b46 100644 --- a/packages/tests/rescript.json +++ b/packages/tests/rescript.json @@ -11,7 +11,7 @@ "module": "esmodule", "in-source": true }, - "suffix": ".bs.mjs", + "suffix": ".res.mjs", "bs-dependencies": ["rescript-schema"], "bs-dev-dependencies": ["@rescript/core", "@dzakh/rescript-ava"], "ppx-flags": ["../rescript-schema-ppx/bin"], diff --git a/packages/tests/src/benchmark/Benchmark.bs.mjs b/packages/tests/src/benchmark/Benchmark.res.mjs similarity index 99% rename from packages/tests/src/benchmark/Benchmark.bs.mjs rename to packages/tests/src/benchmark/Benchmark.res.mjs index 4f57b40b..42d7a744 100644 --- a/packages/tests/src/benchmark/Benchmark.bs.mjs +++ b/packages/tests/src/benchmark/Benchmark.res.mjs @@ -1,8 +1,8 @@ // Generated by ReScript, PLEASE EDIT WITH CARE import * as Benchmark from "benchmark"; -import * as Core__Array from "@rescript/core/src/Core__Array.bs.mjs"; -import * as S$RescriptSchema from "rescript-schema/src/S.bs.mjs"; +import * as Core__Array from "@rescript/core/src/Core__Array.res.mjs"; +import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs"; function addWithPrepare(suite, name, fn) { return suite.add(name, fn()); diff --git a/packages/tests/src/benchmark/comparison.js b/packages/tests/src/benchmark/comparison.js index c687944b..1d27747e 100644 --- a/packages/tests/src/benchmark/comparison.js +++ b/packages/tests/src/benchmark/comparison.js @@ -2,6 +2,7 @@ import B from "benchmark"; import { z } from "zod"; import * as V from "valibot"; import * as S from "rescript-schema/src/S.js"; +import { type } from "arktype"; const data = Object.freeze({ number: 1, @@ -18,6 +19,20 @@ const data = Object.freeze({ }, }); +const arkType = type({ + number: "number", + negNumber: "number", + maxNumber: "number", + string: "string", + longString: "string", + boolean: "boolean", + deeplyNested: { + foo: "string", + num: "number", + bool: "boolean", + }, +}); + const zodSchema = z.object({ number: z.number(), negNumber: z.number(), @@ -136,7 +151,6 @@ new B.Suite() }); return zodSchema.parse(data); }) - .add("Valibot (create)", () => { return V.object({ number: V.number(), @@ -171,7 +185,40 @@ new B.Suite() }); return V.parse(valibotSchema, data); }) - + .add("ArkType (create)", () => { + return type({ + number: "number", + negNumber: "number", + maxNumber: "number", + string: "string", + longString: "string", + boolean: "boolean", + deeplyNested: { + foo: "string", + num: "number", + bool: "boolean", + }, + }); + }) + .add("ArkType (parse)", () => { + return arkType(data); + }) + .add("ArkType (create + parse)", () => { + const arkType = type({ + number: "number", + negNumber: "number", + maxNumber: "number", + string: "string", + longString: "string", + boolean: "boolean", + deeplyNested: { + foo: "string", + num: "number", + bool: "boolean", + }, + }); + return arkType(data); + }) .on("cycle", (event) => { console.log(String(event.target)); }) diff --git a/packages/tests/src/core/Example_test.res b/packages/tests/src/core/Example_test.res index ff32ba1a..3ae24134 100644 --- a/packages/tests/src/core/Example_test.res +++ b/packages/tests/src/core/Example_test.res @@ -69,7 +69,7 @@ test("Compiled parse code snapshot", t => { t->U.assertCompiledCode( ~schema=filmSchema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[7](i)}let v0=i["Id"],v1=i["Title"],v2=i["Tags"],v6=i["Rating"],v7=i["Age"];if(typeof v0!=="number"||Number.isNaN(v0)){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}if(v2!==void 0&&(!Array.isArray(v2))){e[2](v2)}if(v2!==void 0){for(let v3=0;v32147483647||v7<-2147483648||v7%1!==0)){e[6](v7)}return {"id":v0,"title":v1,"tags":v2===void 0?e[4]:v2,"rating":v6,"deprecatedAgeRestriction":v7,}}`, + `i=>{if(typeof i!=="object"||!i){e[7](i)}let v0=i["Id"],v1=i["Title"],v2=i["Tags"],v6=i["Rating"],v7=i["Age"];if(typeof v0!=="number"||Number.isNaN(v0)){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}if(v2!==void 0&&(!Array.isArray(v2))){e[2](v2)}if(v2!==void 0){for(let v3=0;v32147483647||v7<-2147483648||v7%1!==0)){e[6](v7)}return {"id":v0,"title":v1,"tags":v2===void 0?e[4]:v2,"rating":v6,"deprecatedAgeRestriction":v7,}}`, ) }) diff --git a/packages/tests/src/core/S_dict_test.res b/packages/tests/src/core/S_dict_test.res index 2adc6be7..631825f2 100644 --- a/packages/tests/src/core/S_dict_test.res +++ b/packages/tests/src/core/S_dict_test.res @@ -52,7 +52,7 @@ module CommonWithNested = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[1](i)}for(let v0 in i){let v2=i[v0];try{if(typeof v2!=="string"){e[0](v2)}}catch(v1){if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1}}return i}`, + `i=>{if(typeof i!=="object"||!i){e[1](i)}for(let v0 in i){let v2=i[v0];try{if(typeof v2!=="string"){e[0](v2)}}catch(v1){if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1}}return i}`, ) }) @@ -62,7 +62,7 @@ module CommonWithNested = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[1](i)}let v3={};for(let v0 in i){let v2;try{v2=e[0](i[v0]).catch(v1=>{if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1})}catch(v1){if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1}v3[v0]=v2}return new Promise((v4,v5)=>{let v7=Object.keys(v3).length;for(let v0 in v3){v3[v0].then(v6=>{v3[v0]=v6;if(v7--===1){v4(v3)}},v5)}})}`, + `i=>{if(typeof i!=="object"||!i){e[1](i)}let v3={};for(let v0 in i){let v2;try{v2=e[0](i[v0]).catch(v1=>{if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1})}catch(v1){if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1}v3[v0]=v2}return new Promise((v4,v5)=>{let v7=Object.keys(v3).length;for(let v0 in v3){v3[v0].then(v6=>{v3[v0]=v6;if(v7--===1){v4(v3)}},v5)}})}`, ) }) diff --git a/packages/tests/src/core/S_literal_Object_test.res b/packages/tests/src/core/S_literal_Object_test.res index c1e2a1d4..58ed1669 100644 --- a/packages/tests/src/core/S_literal_Object_test.res +++ b/packages/tests/src/core/S_literal_Object_test.res @@ -94,20 +94,10 @@ module Common = { ) }) - test("Fails to parse non plain objects", t => { + test("Can parse non plain objects", t => { let schema = factory() - t->U.assertRaised( - () => makeNotPlainValue()->S.parseOrThrow(schema), - { - code: InvalidType({ - expected: S.literal(Dict.fromArray([("foo", "bar")]))->S.toUnknown, - received: makeNotPlainValue()->U.castAnyToUnknown, - }), - operation: Parse, - path: S.Path.empty, - }, - ) + t->Assert.deepEqual(makeNotPlainValue()->S.parseOrThrow(schema), makeNotPlainValue(), ()) }) test("Compiled parse code snapshot", t => { @@ -116,7 +106,7 @@ module Common = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(i!==e[0]&&(!i||i.constructor!==Object||Object.keys(i).length!==1||i["foo"]!=="bar")){e[1](i)}return i}`, + `i=>{if(i!==e[0]&&(typeof i!=="object"||!i||Object.keys(i).length!==1||i["foo"]!=="bar")){e[1](i)}return i}`, ) }) @@ -126,7 +116,7 @@ module Common = { t->U.assertCompiledCode( ~schema, ~op=#ReverseConvert, - `i=>{if(i!==e[0]&&(!i||i.constructor!==Object||Object.keys(i).length!==1||i["foo"]!=="bar")){e[1](i)}return i}`, + `i=>{if(i!==e[0]&&(typeof i!=="object"||!i||Object.keys(i).length!==1||i["foo"]!=="bar")){e[1](i)}return i}`, ) }) @@ -196,7 +186,7 @@ module EmptyDict = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(i!==e[0]&&(!i||i.constructor!==Object||Object.keys(i).length!==0)){e[1](i)}return i}`, + `i=>{if(i!==e[0]&&(typeof i!=="object"||!i||Object.keys(i).length!==0)){e[1](i)}return i}`, ) }) @@ -206,7 +196,7 @@ module EmptyDict = { t->U.assertCompiledCode( ~schema, ~op=#ReverseConvert, - `i=>{if(i!==e[0]&&(!i||i.constructor!==Object||Object.keys(i).length!==0)){e[1](i)}return i}`, + `i=>{if(i!==e[0]&&(typeof i!=="object"||!i||Object.keys(i).length!==0)){e[1](i)}return i}`, ) }) diff --git a/packages/tests/src/core/S_object_flatten_test.res b/packages/tests/src/core/S_object_flatten_test.res index c0611742..74a21a94 100644 --- a/packages/tests/src/core/S_object_flatten_test.res +++ b/packages/tests/src/core/S_object_flatten_test.res @@ -20,7 +20,7 @@ test("Has correct tagged type", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"bar":v0,"foo":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"bar":v0,"foo":v1,}}`, ) }) @@ -51,7 +51,7 @@ test("Can flatten S.schema", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"baz":{"bar":v0,},"foo":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"baz":{"bar":v0,},"foo":v1,}}`, ) t->U.assertCompiledCode( ~schema, @@ -81,7 +81,7 @@ test("Can flatten & destructure S.schema", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"bar":v0,"foo":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"bar":v0,"foo":v1,}}`, ) t->U.assertCompiledCode( ~schema, @@ -118,7 +118,7 @@ test("Can flatten strict object", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"bar":v0,"foo":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"bar":v0,"foo":v1,}}`, ) }) @@ -142,7 +142,7 @@ test("Flatten inside of a strict object", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v0=i["bar"],v1=i["foo"],v2;if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}for(v2 in i){if(v2!=="bar"&&v2!=="foo"){e[2](v2)}}return {"bar":v0,"foo":v1,}}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)){e[3](i)}let v0=i["bar"],v1=i["foo"],v2;if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}for(v2 in i){if(v2!=="bar"&&v2!=="foo"){e[2](v2)}}return {"bar":v0,"foo":v1,}}`, ) }) @@ -185,7 +185,7 @@ test("Flatten schema with duplicated field of the same type (flatten last)", t = t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[1](i)}let v0=i["foo"];if(typeof v0!=="string"){e[0](v0)}return {"foo":v0,"bar":v0,}}`, + `i=>{if(typeof i!=="object"||!i){e[1](i)}let v0=i["foo"];if(typeof v0!=="string"){e[0](v0)}return {"foo":v0,"bar":v0,}}`, ) // FIXME: Should validate that the fields are equal and choose the right one depending on the order t->U.assertCompiledCode(~schema, ~op=#ReverseConvert, `i=>{return {"foo":i["bar"],}}`) @@ -229,7 +229,7 @@ test("Can flatten renamed object schema", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"bar":v0,"foo":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"bar":v0,"foo":v1,}}`, ) t->Assert.is(schema->S.name, `{ bar: string; foo: string; }`, ()) }) @@ -253,7 +253,7 @@ test("Can flatten transformed object schema", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"bar":e[2](v0),"foo":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[3](i)}let v0=i["bar"],v1=i["foo"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"bar":e[2](v0),"foo":v1,}}`, ) }) @@ -321,7 +321,7 @@ test("Can destructure flattened schema", t => { t->U.assertCompiledCode( ~op=#Parse, ~schema=entitySchema, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v0=i["name"],v1=i["age"],v2=i["id"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="number"||v1>2147483647||v1<-2147483648||v1%1!==0){e[1](v1)}if(typeof v2!=="string"){e[2](v2)}return {"id":v2,"name":v0,"age":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[3](i)}let v0=i["name"],v1=i["age"],v2=i["id"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="number"||v1>2147483647||v1<-2147483648||v1%1!==0){e[1](v1)}if(typeof v2!=="string"){e[2](v2)}return {"id":v2,"name":v0,"age":v1,}}`, ) t->Assert.deepEqual( diff --git a/packages/tests/src/core/S_object_nested_test.res b/packages/tests/src/core/S_object_nested_test.res index d5bae7c6..ff0757f5 100644 --- a/packages/tests/src/core/S_object_nested_test.res +++ b/packages/tests/src/core/S_object_nested_test.res @@ -12,7 +12,7 @@ test("Object with a single nested field", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"];if(typeof v1!=="string"){e[1](v1)}return v1}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["foo"];if(typeof v1!=="string"){e[1](v1)}return v1}`, ) t->U.assertCompiledCode(~schema, ~op=#ReverseConvert, `i=>{return {"nested":{"foo":i,},}}`) }) @@ -28,7 +28,7 @@ test("Object with a single nested field with S.null", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"],v2;if(v1!==null&&(typeof v1!=="string")){e[1](v1)}if(v1!==null){v2=v1}else{v2=void 0}return v2}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["foo"],v2;if(v1!==null&&(typeof v1!=="string")){e[1](v1)}if(v1!==null){v2=v1}else{v2=void 0}return v2}`, ) t->U.assertCompiledCode( ~schema, @@ -68,7 +68,7 @@ test("Object with a single nested field with S.transform", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"];if(typeof v1!=="number"||Number.isNaN(v1)){e[1](v1)}return e[2](v1)}`, + `i=>{if(typeof i!=="object"||!i){e[3](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["foo"];if(typeof v1!=="number"||Number.isNaN(v1)){e[1](v1)}return e[2](v1)}`, ) t->U.assertCompiledCode(~schema, ~op=#ReverseConvert, `i=>{return {"nested":{"foo":e[0](i),},}}`) t->Assert.deepEqual( @@ -106,7 +106,7 @@ test("Object with a nested tag and optional field", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[4](i)}let v0=i["nested"],v2=i["bar"];if(!v0||v0.constructor!==Object||v0["tag"]!=="value"){e[0](v0)}let v1=v0["foo"];if(v1!==void 0&&(typeof v1!=="string")){e[1](v1)}if(typeof v2!=="string"){e[3](v2)}return {"foo":v1===void 0?e[2]:v1,"bar":v2,}}`, + `i=>{if(typeof i!=="object"||!i){e[4](i)}let v0=i["nested"],v2=i["bar"];if(typeof v0!=="object"||!v0||v0["tag"]!=="value"){e[0](v0)}let v1=v0["foo"];if(v1!==void 0&&(typeof v1!=="string")){e[1](v1)}if(typeof v2!=="string"){e[3](v2)}return {"foo":v1===void 0?e[2]:v1,"bar":v2,}}`, ) t->U.assertCompiledCode( ~schema, @@ -143,7 +143,7 @@ test("Object with a two nested field using the same ctx", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"],v2=v0["bar"];if(typeof v1!=="string"){e[1](v1)}if(typeof v2!=="string"){e[2](v2)}return {"foo":v1,"bar":v2,}}`, + `i=>{if(typeof i!=="object"||!i){e[3](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["foo"],v2=v0["bar"];if(typeof v1!=="string"){e[1](v1)}if(typeof v2!=="string"){e[2](v2)}return {"foo":v1,"bar":v2,}}`, ) t->U.assertCompiledCode( ~schema, @@ -165,7 +165,7 @@ test("Object with a single nested nested field", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["deeply"];if(!v1||v1.constructor!==Object){e[1](v1)}let v2=v1["foo"];if(typeof v2!=="string"){e[2](v2)}return v2}`, + `i=>{if(typeof i!=="object"||!i){e[3](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["deeply"];if(typeof v1!=="object"||!v1){e[1](v1)}let v2=v1["foo"];if(typeof v2!=="string"){e[2](v2)}return v2}`, ) t->U.assertCompiledCode( ~schema, @@ -201,7 +201,7 @@ test("Object with a two nested field calling s.nested twice", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"],v2=v0["bar"];if(typeof v1!=="string"){e[1](v1)}if(typeof v2!=="string"){e[2](v2)}return {"foo":v1,"bar":v2,}}`, + `i=>{if(typeof i!=="object"||!i){e[3](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["foo"],v2=v0["bar"];if(typeof v1!=="string"){e[1](v1)}if(typeof v2!=="string"){e[2](v2)}return {"foo":v1,"bar":v2,}}`, ) t->U.assertCompiledCode( ~schema, @@ -240,7 +240,7 @@ test("Object with a flattened nested field", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"];if(typeof v1!=="string"){e[1](v1)}return {"foo":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["foo"];if(typeof v1!=="string"){e[1](v1)}return {"foo":v1,}}`, ) t->U.assertCompiledCode(~schema, ~op=#ReverseConvert, `i=>{return {"nested":{"foo":i["foo"],},}}`) }) @@ -275,7 +275,7 @@ test("Object with a strict flattened nested field", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"];if(typeof v1!=="string"){e[1](v1)}return {"foo":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["foo"];if(typeof v1!=="string"){e[1](v1)}return {"foo":v1,}}`, ) t->U.assertCompiledCode(~schema, ~op=#ReverseConvert, `i=>{return {"nested":{"foo":i["foo"],},}}`) }) @@ -307,7 +307,7 @@ test("S.schema object with a deep strict applied to the nested field parent", t t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[4](i)}let v0=i["nested"],v3;if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"],v2;if(typeof v1!=="string"){e[1](v1)}for(v2 in v0){if(v2!=="foo"){e[2](v2)}}for(v3 in i){if(v3!=="nested"){e[3](v3)}}return i}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)){e[4](i)}let v0=i["nested"],v3;if(typeof v0!=="object"||!v0||Array.isArray(v0)){e[0](v0)}let v1=v0["foo"],v2;if(typeof v1!=="string"){e[1](v1)}for(v2 in v0){if(v2!=="foo"){e[2](v2)}}for(v3 in i){if(v3!=="nested"){e[3](v3)}}return i}`, ) t->U.assertCompiledCode(~schema, ~op=#ReverseConvert, `i=>{let v0=i["nested"];return i}`) }) @@ -342,7 +342,7 @@ test("S.schema object with a deep strict applied to the nested field parent + re t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[4](i)}let v0=i["nested"],v4;if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"],v2,v3;if(v1!==void 0&&(typeof v1!=="string")){e[1](v1)}if(v1!==void 0){v2=v1}else{v2=null}for(v3 in v0){if(v3!=="foo"){e[2](v3)}}for(v4 in i){if(v4!=="nested"){e[3](v4)}}return {"nested":{"foo":v2,},}}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)){e[4](i)}let v0=i["nested"],v4;if(typeof v0!=="object"||!v0||Array.isArray(v0)){e[0](v0)}let v1=v0["foo"],v2,v3;if(v1!==void 0&&(typeof v1!=="string")){e[1](v1)}if(v1!==void 0){v2=v1}else{v2=null}for(v3 in v0){if(v3!=="foo"){e[2](v3)}}for(v4 in i){if(v4!=="nested"){e[3](v4)}}return {"nested":{"foo":v2,},}}`, ) t->U.assertCompiledCode( ~schema, @@ -372,7 +372,7 @@ test("Object with a deep strict applied to the nested field parent", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[4](i)}let v0=i["nested"],v3;if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"],v2;if(typeof v1!=="string"){e[1](v1)}for(v2 in v0){if(v2!=="foo"){e[2](v2)}}for(v3 in i){if(v3!=="nested"){e[3](v3)}}return v1}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)){e[4](i)}let v0=i["nested"],v3;if(typeof v0!=="object"||!v0||Array.isArray(v0)){e[0](v0)}let v1=v0["foo"],v2;if(typeof v1!=="string"){e[1](v1)}for(v2 in v0){if(v2!=="foo"){e[2](v2)}}for(v3 in i){if(v3!=="nested"){e[3](v3)}}return v1}`, ) t->U.assertCompiledCode(~schema, ~op=#ReverseConvert, `i=>{return {"nested":{"foo":i,},}}`) }) @@ -399,7 +399,7 @@ test("Object with a deep strict applied to the nested field parent + reverse", t // FIXME: Test for deepStrict applying to flattened nested fields // Test deepStrict for reversed schema // Test strict & deepStrict for S.to - `i=>{if(!i||i.constructor!==Object){e[1](i)}let v0;for(v0 in i){if(v0!=="foo"){e[0](v0)}}return {"nested":{"foo":i["foo"],},}}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)){e[1](i)}let v0;for(v0 in i){if(v0!=="foo"){e[0](v0)}}return {"nested":{"foo":i["foo"],},}}`, ) t->U.assertCompiledCode(~schema, ~op=#ReverseConvert, `i=>{return {"nested":{"foo":i["foo"],},}}`) }) @@ -438,7 +438,7 @@ test("Object with nested field together with flatten", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"],v2=v0["bar"];if(typeof v1!=="string"){e[1](v1)}if(typeof v2!=="string"){e[2](v2)}return {"flattened":{"foo":v1,},"field":v2,}}`, + `i=>{if(typeof i!=="object"||!i){e[3](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["foo"],v2=v0["bar"];if(typeof v1!=="string"){e[1](v1)}if(typeof v2!=="string"){e[2](v2)}return {"flattened":{"foo":v1,},"field":v2,}}`, ) t->U.assertCompiledCode( ~schema, @@ -557,7 +557,7 @@ test("s.nested.flattened works with S.schema->S.to to self", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"];if(typeof v1!=="string"){e[1](v1)}return {"foo":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["foo"];if(typeof v1!=="string"){e[1](v1)}return {"foo":v1,}}`, ) t->U.assertCompiledCode(~schema, ~op=#ReverseConvert, `i=>{return {"nested":{"foo":i["foo"],},}}`) }) diff --git a/packages/tests/src/core/S_object_test.res b/packages/tests/src/core/S_object_test.res index 8f696a1f..22f4ebea 100644 --- a/packages/tests/src/core/S_object_test.res +++ b/packages/tests/src/core/S_object_test.res @@ -683,7 +683,7 @@ test("Parse reversed schema with nested objects and tuples has type validation", } ), ~op=#ReverseParse, - `i=>{if(!i||i.constructor!==Object){e[1](i)}let v0=i["foo"];if(typeof v0!=="boolean"){e[0](v0)}return {"foo":v0,}}`, + `i=>{if(typeof i!=="object"||!i){e[1](i)}let v0=i["foo"];if(typeof v0!=="boolean"){e[0](v0)}return {"foo":v0,}}`, ) }) @@ -739,7 +739,7 @@ module BenchmarkWithSObject = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[10](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"];if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(!v6||v6.constructor!==Object){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"];if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}return {"number":v0,"negNumber":v1,"maxNumber":v2,"string":v3,"longString":v4,"boolean":v5,"deeplyNested":{"foo":v7,"num":v8,"bool":v9,},}}`, + `i=>{if(typeof i!=="object"||!i){e[10](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"];if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(typeof v6!=="object"||!v6){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"];if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}return {"number":v0,"negNumber":v1,"maxNumber":v2,"string":v3,"longString":v4,"boolean":v5,"deeplyNested":{"foo":v7,"num":v8,"bool":v9,},}}`, ) S.setGlobalConfig({}) }) @@ -755,7 +755,7 @@ module BenchmarkWithSObject = { t->U.assertCompiledCode( ~schema, ~op=#Assert, - `i=>{if(!i||i.constructor!==Object){e[10](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"];if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(!v6||v6.constructor!==Object){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"];if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}return void 0}`, + `i=>{if(typeof i!=="object"||!i){e[10](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"];if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(typeof v6!=="object"||!v6){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"];if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}return void 0}`, ) S.setGlobalConfig({}) }) @@ -772,7 +772,7 @@ module BenchmarkWithSObject = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[12](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"],v11;if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(!v6||v6.constructor!==Object){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"],v10;if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}for(v10 in v6){if(v10!=="foo"&&v10!=="num"&&v10!=="bool"){e[10](v10)}}for(v11 in i){if(v11!=="number"&&v11!=="negNumber"&&v11!=="maxNumber"&&v11!=="string"&&v11!=="longString"&&v11!=="boolean"&&v11!=="deeplyNested"){e[11](v11)}}return {"number":v0,"negNumber":v1,"maxNumber":v2,"string":v3,"longString":v4,"boolean":v5,"deeplyNested":{"foo":v7,"num":v8,"bool":v9,},}}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)){e[12](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"],v11;if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(typeof v6!=="object"||!v6||Array.isArray(v6)){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"],v10;if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}for(v10 in v6){if(v10!=="foo"&&v10!=="num"&&v10!=="bool"){e[10](v10)}}for(v11 in i){if(v11!=="number"&&v11!=="negNumber"&&v11!=="maxNumber"&&v11!=="string"&&v11!=="longString"&&v11!=="boolean"&&v11!=="deeplyNested"){e[11](v11)}}return {"number":v0,"negNumber":v1,"maxNumber":v2,"string":v3,"longString":v4,"boolean":v5,"deeplyNested":{"foo":v7,"num":v8,"bool":v9,},}}`, ) S.setGlobalConfig({}) }) @@ -789,7 +789,7 @@ module BenchmarkWithSObject = { t->U.assertCompiledCode( ~schema, ~op=#Assert, - `i=>{if(!i||i.constructor!==Object){e[12](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"],v11;if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(!v6||v6.constructor!==Object){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"],v10;if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}for(v10 in v6){if(v10!=="foo"&&v10!=="num"&&v10!=="bool"){e[10](v10)}}for(v11 in i){if(v11!=="number"&&v11!=="negNumber"&&v11!=="maxNumber"&&v11!=="string"&&v11!=="longString"&&v11!=="boolean"&&v11!=="deeplyNested"){e[11](v11)}}return void 0}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)){e[12](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"],v11;if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(typeof v6!=="object"||!v6||Array.isArray(v6)){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"],v10;if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}for(v10 in v6){if(v10!=="foo"&&v10!=="num"&&v10!=="bool"){e[10](v10)}}for(v11 in i){if(v11!=="number"&&v11!=="negNumber"&&v11!=="maxNumber"&&v11!=="string"&&v11!=="longString"&&v11!=="boolean"&&v11!=="deeplyNested"){e[11](v11)}}return void 0}`, ) S.setGlobalConfig({}) }) @@ -856,7 +856,7 @@ module Benchmark = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[10](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"];if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(!v6||v6.constructor!==Object){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"];if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}return {"number":v0,"negNumber":v1,"maxNumber":v2,"string":v3,"longString":v4,"boolean":v5,"deeplyNested":{"foo":v7,"num":v8,"bool":v9,},}}`, + `i=>{if(typeof i!=="object"||!i){e[10](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"];if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(typeof v6!=="object"||!v6){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"];if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}return {"number":v0,"negNumber":v1,"maxNumber":v2,"string":v3,"longString":v4,"boolean":v5,"deeplyNested":{"foo":v7,"num":v8,"bool":v9,},}}`, ) t->Assert.deepEqual(makeTestObject()->S.parseOrThrow(schema), makeTestObject(), ()) @@ -875,7 +875,7 @@ module Benchmark = { t->U.assertCompiledCode( ~schema, ~op=#Assert, - `i=>{if(!i||i.constructor!==Object){e[10](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"];if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(!v6||v6.constructor!==Object){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"];if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}return void 0}`, + `i=>{if(typeof i!=="object"||!i){e[10](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"];if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(typeof v6!=="object"||!v6){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"];if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}return void 0}`, ) S.setGlobalConfig({}) }) @@ -892,7 +892,7 @@ module Benchmark = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[12](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"],v11;if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(!v6||v6.constructor!==Object){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"],v10;if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}for(v10 in v6){if(v10!=="foo"&&v10!=="num"&&v10!=="bool"){e[10](v10)}}for(v11 in i){if(v11!=="number"&&v11!=="negNumber"&&v11!=="maxNumber"&&v11!=="string"&&v11!=="longString"&&v11!=="boolean"&&v11!=="deeplyNested"){e[11](v11)}}return i}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)){e[12](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"],v11;if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(typeof v6!=="object"||!v6||Array.isArray(v6)){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"],v10;if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}for(v10 in v6){if(v10!=="foo"&&v10!=="num"&&v10!=="bool"){e[10](v10)}}for(v11 in i){if(v11!=="number"&&v11!=="negNumber"&&v11!=="maxNumber"&&v11!=="string"&&v11!=="longString"&&v11!=="boolean"&&v11!=="deeplyNested"){e[11](v11)}}return i}`, ) S.setGlobalConfig({}) }) @@ -909,7 +909,7 @@ module Benchmark = { t->U.assertCompiledCode( ~schema, ~op=#Assert, - `i=>{if(!i||i.constructor!==Object){e[12](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"],v11;if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(!v6||v6.constructor!==Object){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"],v10;if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}for(v10 in v6){if(v10!=="foo"&&v10!=="num"&&v10!=="bool"){e[10](v10)}}for(v11 in i){if(v11!=="number"&&v11!=="negNumber"&&v11!=="maxNumber"&&v11!=="string"&&v11!=="longString"&&v11!=="boolean"&&v11!=="deeplyNested"){e[11](v11)}}return void 0}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)){e[12](i)}let v0=i["number"],v1=i["negNumber"],v2=i["maxNumber"],v3=i["string"],v4=i["longString"],v5=i["boolean"],v6=i["deeplyNested"],v11;if(typeof v0!=="number"){e[0](v0)}if(typeof v1!=="number"){e[1](v1)}if(typeof v2!=="number"){e[2](v2)}if(typeof v3!=="string"){e[3](v3)}if(typeof v4!=="string"){e[4](v4)}if(typeof v5!=="boolean"){e[5](v5)}if(typeof v6!=="object"||!v6||Array.isArray(v6)){e[6](v6)}let v7=v6["foo"],v8=v6["num"],v9=v6["bool"],v10;if(typeof v7!=="string"){e[7](v7)}if(typeof v8!=="number"){e[8](v8)}if(typeof v9!=="boolean"){e[9](v9)}for(v10 in v6){if(v10!=="foo"&&v10!=="num"&&v10!=="bool"){e[10](v10)}}for(v11 in i){if(v11!=="number"&&v11!=="negNumber"&&v11!=="maxNumber"&&v11!=="string"&&v11!=="longString"&&v11!=="boolean"&&v11!=="deeplyNested"){e[11](v11)}}return void 0}`, ) S.setGlobalConfig({}) }) @@ -1048,7 +1048,7 @@ test("Can destructure fields of simple nested objects", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["foo"],v2=v0["bar"];if(typeof v1!=="string"){e[1](v1)}if(typeof v2!=="string"){e[2](v2)}return {"baz":v2,"foz":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[3](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["foo"],v2=v0["bar"];if(typeof v1!=="string"){e[1](v1)}if(typeof v2!=="string"){e[2](v2)}return {"baz":v2,"foz":v1,}}`, ) t->Assert.deepEqual( @@ -1138,7 +1138,7 @@ module Compiled = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["foo"],v1=i["bar"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="boolean"){e[1](v1)}return {"foo":v0,"bar":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["foo"],v1=i["bar"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="boolean"){e[1](v1)}return {"foo":v0,"bar":v1,}}`, ) t->U.assertCompiledCode( ~schema, @@ -1165,7 +1165,7 @@ module Compiled = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object||i["foo"]!==12){e[3](i)}let v2;let v0=i["bar"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["baz"];if(typeof v1!=="string"){e[1](v1)}v2={"baz":v1,};e[2](v2);return {"foo":i["foo"],"bar":v2,}}`, + `i=>{if(typeof i!=="object"||!i||i["foo"]!==12){e[3](i)}let v2;let v0=i["bar"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["baz"];if(typeof v1!=="string"){e[1](v1)}v2={"baz":v1,};e[2](v2);return {"foo":i["foo"],"bar":v2,}}`, ) t->U.assertCompiledCode( ~schema, @@ -1185,7 +1185,7 @@ module Compiled = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["bar"];if(typeof v0!=="boolean"){e[1](v0)}return Promise.all([e[0](i["foo"]),]).then(a=>({"foo":a[0],"bar":v0,}))}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["bar"];if(typeof v0!=="boolean"){e[1](v0)}return Promise.all([e[0](i["foo"]),]).then(a=>({"foo":a[0],"bar":v0,}))}`, ) }) @@ -1197,7 +1197,7 @@ module Compiled = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[1](i)}return e[0](i["foo"])}`, + `i=>{if(typeof i!=="object"||!i){e[1](i)}return e[0](i["foo"])}`, ) }) @@ -1212,7 +1212,7 @@ module Compiled = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v0=i["foo"],v1=i["bar"],v2;if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="boolean"){e[1](v1)}for(v2 in i){if(v2!=="foo"&&v2!=="bar"){e[2](v2)}}return {"foo":v0,"bar":v1,}}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)){e[3](i)}let v0=i["foo"],v1=i["bar"],v2;if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="boolean"){e[1](v1)}for(v2 in i){if(v2!=="foo"&&v2!=="bar"){e[2](v2)}}return {"foo":v0,"bar":v1,}}`, ) }) @@ -1241,7 +1241,7 @@ module Compiled = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v0=i["nested"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1;for(v1 in v0){if(true){e[1](v1)}}return {"nested":e[2],}}`, + `i=>{if(typeof i!=="object"||!i){e[3](i)}let v0=i["nested"];if(typeof v0!=="object"||!v0||Array.isArray(v0)){e[0](v0)}let v1;for(v1 in v0){if(true){e[1](v1)}}return {"nested":e[2],}}`, ) t->U.assertCompiledCode( ~schema, @@ -1265,7 +1265,7 @@ module Compiled = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object||i["tag"]!==0){e[4](i)}let v0=i["FOO"],v1=i["BAR"],v2;if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="boolean"){e[1](v1)}for(v2 in i){if(v2!=="tag"&&v2!=="FOO"&&v2!=="BAR"){e[2](v2)}}return {"foo":v0,"bar":v1,"zoo":e[3],}}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)||i["tag"]!==0){e[4](i)}let v0=i["FOO"],v1=i["BAR"],v2;if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="boolean"){e[1](v1)}for(v2 in i){if(v2!=="tag"&&v2!=="FOO"&&v2!=="BAR"){e[2](v2)}}return {"foo":v0,"bar":v1,"zoo":e[3],}}`, ) }, ) diff --git a/packages/tests/src/core/S_object_withoutDeclaredFields_test.res b/packages/tests/src/core/S_object_withoutDeclaredFields_test.res index e2e8f14d..22b081d7 100644 --- a/packages/tests/src/core/S_object_withoutDeclaredFields_test.res +++ b/packages/tests/src/core/S_object_withoutDeclaredFields_test.res @@ -41,15 +41,8 @@ test("Successfully serializes transformed value to empty object", t => { t->Assert.deepEqual(transformedValue->S.reverseConvertOrThrow(schema), %raw("{}"), ()) }) -test("Fails to parse array data", t => { +test("Allows to pass array to object value", t => { let schema = S.object(_ => ()) - t->U.assertRaised( - () => %raw(`[]`)->S.parseOrThrow(schema), - { - code: InvalidType({expected: schema->S.toUnknown, received: %raw(`[]`)}), - operation: Parse, - path: S.Path.empty, - }, - ) + t->Assert.deepEqual(%raw(`[]`)->S.parseOrThrow(schema), (), ()) }) diff --git a/packages/tests/src/core/S_preprocess_test.res b/packages/tests/src/core/S_preprocess_test.res index 58bcc0ca..6c114814 100644 --- a/packages/tests/src/core/S_preprocess_test.res +++ b/packages/tests/src/core/S_preprocess_test.res @@ -265,7 +265,7 @@ test("Compiled async parse code snapshot for object", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{return e[0](i).then(v0=>{if(!v0||v0.constructor!==Object){e[1](v0)}let v1=v0["foo"];if(typeof v1!=="string"){e[2](v1)}return {"foo":v1,}})}`, + `i=>{return e[0](i).then(v0=>{if(typeof v0!=="object"||!v0){e[1](v0)}let v1=v0["foo"];if(typeof v1!=="string"){e[2](v1)}return {"foo":v1,}})}`, ) }) diff --git a/packages/tests/src/core/S_recursive_test.res b/packages/tests/src/core/S_recursive_test.res index 952f3cf5..1abb3171 100644 --- a/packages/tests/src/core/S_recursive_test.res +++ b/packages/tests/src/core/S_recursive_test.res @@ -237,7 +237,7 @@ test("Parses multiple nested recursive object inside of another object", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[8](i)}let v0=i["recursive1"],v9,v10=i["recursive2"],v19;if(!v0||v0.constructor!==Object){e[0](v0)}let r0=v0=>{let v1=v0["Id"],v2=v0["Children"],v7=new Array(v2.length);if(typeof v1!=="string"){e[1](v1)}if(!Array.isArray(v2)){e[2](v2)}for(let v3=0;v3{let v11=v10["Id"],v12=v10["Children"],v17=new Array(v12.length);if(typeof v11!=="string"){e[5](v11)}if(!Array.isArray(v12)){e[6](v12)}for(let v13=0;v13{if(typeof i!=="object"||!i){e[8](i)}let v0=i["recursive1"],v9,v10=i["recursive2"],v19;if(typeof v0!=="object"||!v0){e[0](v0)}let r0=v0=>{let v1=v0["Id"],v2=v0["Children"],v7=new Array(v2.length);if(typeof v1!=="string"){e[1](v1)}if(!Array.isArray(v2)){e[2](v2)}for(let v3=0;v3{let v11=v10["Id"],v12=v10["Children"],v17=new Array(v12.length);if(typeof v11!=="string"){e[5](v11)}if(!Array.isArray(v12)){e[6](v12)}for(let v13=0;v13Assert.deepEqual( @@ -324,7 +324,7 @@ test( t->U.assertCompiledCode( ~schema=nodeSchema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[4](i)}let r3=i=>{let v0=i["Id"],v1=i["Children"],v6=new Array(v1.length);if(typeof v0!=="string"){e[0](v0)}if(!Array.isArray(v1)){e[1](v1)}for(let v2=0;v2{if(typeof i!=="object"||!i){e[4](i)}let r3=i=>{let v0=i["Id"],v1=i["Children"],v6=new Array(v1.length);if(typeof v0!=="string"){e[0](v0)}if(!Array.isArray(v1)){e[1](v1)}for(let v2=0;v2Assert.deepEqual( { @@ -470,7 +470,7 @@ test("Shallowly transforms object when added transform to the S.recursive result t->U.assertCompiledCode( ~schema=nodeSchema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[4](i)}let r5=i=>{let v0=i["Id"],v1=i["Children"],v6=new Array(v1.length);if(typeof v0!=="string"){e[0](v0)}if(!Array.isArray(v1)){e[1](v1)}for(let v2=0;v2{if(typeof i!=="object"||!i){e[4](i)}let r5=i=>{let v0=i["Id"],v1=i["Children"],v6=new Array(v1.length);if(typeof v0!=="string"){e[0](v0)}if(!Array.isArray(v1)){e[1](v1)}for(let v2=0;v2U.assertCompiledCode( ~schema=nodeSchema, @@ -524,7 +524,7 @@ asyncTest("Successfully parses recursive object with async parse function", t => t->U.assertCompiledCode( ~schema=nodeSchema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[4](i)}let r0=i=>{let v0=i["Id"],v1=i["Children"],v6=new Array(v1.length);if(typeof v0!=="string"){e[0](v0)}if(!Array.isArray(v1)){e[2](v1)}for(let v2=0;v2{if(v3&&v3.s===s){v3.path="[\\"Children\\"]"+\'["\'+v2+\'"]\'+v3.path}throw v3})}catch(v3){if(v3&&v3.s===s){v3.path="[\\"Children\\"]"+\'["\'+v2+\'"]\'+v3.path}throw v3}v6[v2]=v5}return Promise.all([e[1](v0),Promise.all(v6),]).then(a=>({"id":a[0],"children":a[1],}))};return r0(i)}`, + `i=>{if(typeof i!=="object"||!i){e[4](i)}let r0=i=>{let v0=i["Id"],v1=i["Children"],v6=new Array(v1.length);if(typeof v0!=="string"){e[0](v0)}if(!Array.isArray(v1)){e[2](v1)}for(let v2=0;v2{if(v3&&v3.s===s){v3.path="[\\"Children\\"]"+\'["\'+v2+\'"]\'+v3.path}throw v3})}catch(v3){if(v3&&v3.s===s){v3.path="[\\"Children\\"]"+\'["\'+v2+\'"]\'+v3.path}throw v3}v6[v2]=v5}return Promise.all([e[1](v0),Promise.all(v6),]).then(a=>({"id":a[0],"children":a[1],}))};return r0(i)}`, ) %raw(`{ @@ -598,6 +598,6 @@ test("Compiled parse code snapshot", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let r0=i=>{let v0=i["Id"],v1=i["Children"],v6=new Array(v1.length);if(typeof v0!=="string"){e[0](v0)}if(!Array.isArray(v1)){e[1](v1)}for(let v2=0;v2{if(typeof i!=="object"||!i){e[3](i)}let r0=i=>{let v0=i["Id"],v1=i["Children"],v6=new Array(v1.length);if(typeof v0!=="string"){e[0](v0)}if(!Array.isArray(v1)){e[1](v1)}for(let v2=0;v2 { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v2;let v0=i["foo"],v1=i["bar"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="boolean"){e[1](v1)}v2={"foo":v0,"bar":v1,};e[2](v2);return v2}`, + `i=>{if(typeof i!=="object"||!i){e[3](i)}let v2;let v0=i["foo"],v1=i["bar"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="boolean"){e[1](v1)}v2={"foo":v0,"bar":v1,};e[2](v2);return v2}`, ) }) @@ -112,7 +112,7 @@ module Issue79 = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["myField"],v2;if(v0!==void 0&&(v0!==null&&(typeof v0!=="string"))){e[0](v0)}if(v0!==void 0){let v1;if(v0!==null){v1=v0}else{v1=void 0}v2=v1}e[1](v2);return v2}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["myField"],v2;if(v0!==void 0&&(v0!==null&&(typeof v0!=="string"))){e[0](v0)}if(v0!==void 0){let v1;if(v0!==null){v1=v0}else{v1=void 0}v2=v1}e[1](v2);return v2}`, ) t->Assert.deepEqual(jsonString->S.parseJsonStringOrThrow(schema), Some("test"), ()) diff --git a/packages/tests/src/core/S_schema_test.res b/packages/tests/src/core/S_schema_test.res index e363d218..0aa140c6 100644 --- a/packages/tests/src/core/S_schema_test.res +++ b/packages/tests/src/core/S_schema_test.res @@ -106,7 +106,7 @@ test("Strict object with embeded returns input without object recreation", t => t->Assert.is( schema->U.getCompiledCodeString(~op=#Parse), - `i=>{if(!i||i.constructor!==Object||i["foo"]!=="bar"){e[2](i)}let v0=i["zoo"],v1;if(typeof v0!=="number"||v0>2147483647||v0<-2147483648||v0%1!==0){e[0](v0)}for(v1 in i){if(v1!=="foo"&&v1!=="zoo"){e[1](v1)}}return i}`, + `i=>{if(typeof i!=="object"||!i||Array.isArray(i)||i["foo"]!=="bar"){e[2](i)}let v0=i["zoo"],v1;if(typeof v0!=="number"||v0>2147483647||v0<-2147483648||v0%1!==0){e[0](v0)}for(v1 in i){if(v1!=="foo"&&v1!=="zoo"){e[1](v1)}}return i}`, (), ) t->Assert.is( @@ -246,3 +246,29 @@ test("Example", t => { S.tuple(s => (s.item(0, S.literal(#id)), s.item(1, S.string))), ) }) + +test( + "Strict schema should also check that object is not Array. Otherwise it will incorrectly return array input", + t => { + let schema = S.schema(s => + { + "0": s.matches(S.string), + "1": s.matches(S.bool), + } + ) + + t->Assert.deepEqual(%raw(`["foo", true]`)->S.parseOrThrow(schema), {"0": "foo", "1": true}, ()) + + t->U.assertRaised( + () => %raw(`["foo", true]`)->S.parseOrThrow(schema->S.strict), + { + code: InvalidType({ + expected: schema->S.strict->S.toUnknown, + received: %raw(`["foo", true]`), + }), + operation: Parse, + path: S.Path.empty, + }, + ) + }, +) diff --git a/packages/tests/src/core/S_test.ts b/packages/tests/src/core/S_test.ts index f401746d..f1988187 100644 --- a/packages/tests/src/core/S_test.ts +++ b/packages/tests/src/core/S_test.ts @@ -1,3 +1,4 @@ +import { StandardSchemaV1 } from "./../../../../src/S.d"; import test, { ExecutionContext } from "ava"; import { expectType, TypeEqual } from "ts-expect"; @@ -1708,6 +1709,35 @@ test("Tuple types", (t) => { t.pass(); }); +test("Standard schema", (t) => { + const schema = S.standard(S.nullable(S.string)); + + t.deepEqual(schema["~standard"]["vendor"], "rescript-schema"); + t.deepEqual(schema["~standard"]["version"], 1); + t.deepEqual(schema["~standard"]["validate"](undefined), { + issues: [ + { + message: + "Failed parsing at root. Reason: Expected string | null, received undefined", + path: undefined, + }, + ], + }); + t.deepEqual(schema["~standard"]["validate"]("foo"), { + value: "foo", + }); + t.deepEqual(schema["~standard"]["validate"](null), { + value: undefined, + }); + + expectType< + TypeEqual, string | null> + >(true); + expectType< + TypeEqual, string | undefined> + >(true); +}); + test("Unnest schema", (t) => { const schema = S.unnest( S.schema({ diff --git a/packages/tests/src/core/S_to_test.res b/packages/tests/src/core/S_to_test.res index ea530acd..8f6faeb7 100644 --- a/packages/tests/src/core/S_to_test.res +++ b/packages/tests/src/core/S_to_test.res @@ -113,7 +113,7 @@ test( t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[1](i)}let v0=i["foo"];if(typeof v0!=="string"){e[0](v0)}return v0}`, + `i=>{if(typeof i!=="object"||!i){e[1](i)}let v0=i["foo"];if(typeof v0!=="string"){e[0](v0)}return v0}`, ) }, ) @@ -139,7 +139,7 @@ test( t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["foo"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["bar"];if(typeof v1!=="string"){e[1](v1)}return v1}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["foo"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["bar"];if(typeof v1!=="string"){e[1](v1)}return v1}`, ) }, ) @@ -164,7 +164,7 @@ test( t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v1;let v0=i["foo"];if(typeof v0!=="string"){e[0](v0)}v1=e[1]({"foo":v0,});return v1["faz"]}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v1;let v0=i["foo"];if(typeof v0!=="string"){e[0](v0)}v1=e[1]({"foo":v0,});return v1["faz"]}`, ) t->Assert.deepEqual( { @@ -255,7 +255,7 @@ test("Can destructure object value passed to S.to", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["foo"],v1=i["bar"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"foo":v0,"bar":v1,}}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["foo"],v1=i["bar"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}return {"foo":v0,"bar":v1,}}`, ) // FIXME: Can be improved t->U.assertCompiledCode( @@ -271,7 +271,7 @@ test("Compiled code snapshot of variant applied to object", t => { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=i["foo"];if(typeof v0!=="string"){e[0](v0)}return {"TAG":e[1],"_0":v0,}}`, + `i=>{if(typeof i!=="object"||!i){e[2](i)}let v0=i["foo"];if(typeof v0!=="string"){e[0](v0)}return {"TAG":e[1],"_0":v0,}}`, ) t->U.assertCompiledCode( ~schema, diff --git a/packages/tests/src/core/S_union_test.res b/packages/tests/src/core/S_union_test.res index 62a48546..a94a0af5 100644 --- a/packages/tests/src/core/S_union_test.res +++ b/packages/tests/src/core/S_union_test.res @@ -372,7 +372,7 @@ module Advanced = { t->U.assertCompiledCode( ~schema=shapeSchema, ~op=#Parse, - `i=>{let v1=i;if(!i||i.constructor!==Object||i["kind"]!=="circle"){if(!i||i.constructor!==Object||i["kind"]!=="square"){if(!i||i.constructor!==Object||i["kind"]!=="triangle"){e[7](i)}else{let v3=i["x"],v4=i["y"];if(typeof v3!=="number"||Number.isNaN(v3)){e[4](v3)}if(typeof v4!=="number"||Number.isNaN(v4)){e[5](v4)}v1={"TAG":e[6],"x":v3,"y":v4,}}}else{let v2=i["x"];if(typeof v2!=="number"||Number.isNaN(v2)){e[2](v2)}v1={"TAG":e[3],"x":v2,}}}else{let v0=i["radius"];if(typeof v0!=="number"||Number.isNaN(v0)){e[0](v0)}v1={"TAG":e[1],"radius":v0,}}return v1}`, + `i=>{let v1=i;if(typeof i!=="object"||!i||i["kind"]!=="circle"){if(typeof i!=="object"||!i||i["kind"]!=="square"){if(typeof i!=="object"||!i||i["kind"]!=="triangle"){e[7](i)}else{let v3=i["x"],v4=i["y"];if(typeof v3!=="number"||Number.isNaN(v3)){e[4](v3)}if(typeof v4!=="number"||Number.isNaN(v4)){e[5](v4)}v1={"TAG":e[6],"x":v3,"y":v4,}}}else{let v2=i["x"];if(typeof v2!=="number"||Number.isNaN(v2)){e[2](v2)}v1={"TAG":e[3],"x":v2,}}}else{let v0=i["radius"];if(typeof v0!=="number"||Number.isNaN(v0)){e[0](v0)}v1={"TAG":e[1],"radius":v0,}}return v1}`, ) }) @@ -380,7 +380,7 @@ module Advanced = { t->U.assertCompiledCode( ~schema=shapeSchema, ~op=#ReverseConvert, - `i=>{let v1=i;if(!i||i.constructor!==Object||i["TAG"]!=="Circle"){if(!i||i.constructor!==Object||i["TAG"]!=="Square"){if(!i||i.constructor!==Object||i["TAG"]!=="Triangle"){e[6](i)}else{let v3=i["TAG"];if(v3!=="Triangle"){e[4](v3)}v1={"kind":e[5],"x":i["x"],"y":i["y"],}}}else{let v2=i["TAG"];if(v2!=="Square"){e[2](v2)}v1={"kind":e[3],"x":i["x"],}}}else{let v0=i["TAG"];if(v0!=="Circle"){e[0](v0)}v1={"kind":e[1],"radius":i["radius"],}}return v1}`, + `i=>{let v1=i;if(typeof i!=="object"||!i||i["TAG"]!=="Circle"){if(typeof i!=="object"||!i||i["TAG"]!=="Square"){if(typeof i!=="object"||!i||i["TAG"]!=="Triangle"){e[6](i)}else{let v3=i["TAG"];if(v3!=="Triangle"){e[4](v3)}v1={"kind":e[5],"x":i["x"],"y":i["y"],}}}else{let v2=i["TAG"];if(v2!=="Square"){e[2](v2)}v1={"kind":e[3],"x":i["x"],}}}else{let v0=i["TAG"];if(v0!=="Circle"){e[0](v0)}v1={"kind":e[1],"radius":i["radius"],}}return v1}`, ) }) } @@ -458,7 +458,7 @@ test("Union with nested variant", t => { t->U.assertCompiledCode( ~schema, ~op=#ReverseConvert, - `i=>{let v5=i;if(!i||i.constructor!==Object){e[3](i)}else{try{let v0=i["foo"];let v1=v0["tag"];let v2=v1["NAME"],v3=v1["VAL"],v4;if(v2!=="Null"){e[0](v2)}if(v3!==void 0){v4=v3}else{v4=null}v5={"foo":{"tag":{"NAME":v2,"VAL":v4,},},}}catch(e0){try{let v6=i["foo"];let v7=v6["tag"];let v8=v7["NAME"];if(v8!=="Option"){e[1](v8)}v5=i}catch(e1){e[2]([e0,e1,])}}}return v5}`, + `i=>{let v5=i;if(typeof i!=="object"||!i){e[3](i)}else{try{let v0=i["foo"];let v1=v0["tag"];let v2=v1["NAME"],v3=v1["VAL"],v4;if(v2!=="Null"){e[0](v2)}if(v3!==void 0){v4=v3}else{v4=null}v5={"foo":{"tag":{"NAME":v2,"VAL":v4,},},}}catch(e0){try{let v6=i["foo"];let v7=v6["tag"];let v8=v7["NAME"];if(v8!=="Option"){e[1](v8)}v5=i}catch(e1){e[2]([e0,e1,])}}}return v5}`, ) }) @@ -528,7 +528,7 @@ module CknittelBugReport = { t->U.assertCompiledCode( ~schema, ~op=#ReverseConvert, - `i=>{let v3=i;if(!i||i.constructor!==Object||i["TAG"]!=="A"){if(!i||i.constructor!==Object||i["TAG"]!=="B"){e[2](i)}else{let v4=i["TAG"],v5=i["_0"];if(v4!=="B"){e[1](v4)}let v6=v5["payload"];v3=v5}}else{let v0=i["TAG"],v1=i["_0"];if(v0!=="A"){e[0](v0)}let v2=v1["payload"];v3=v1}return v3}`, + `i=>{let v3=i;if(typeof i!=="object"||!i||i["TAG"]!=="A"){if(typeof i!=="object"||!i||i["TAG"]!=="B"){e[2](i)}else{let v4=i["TAG"],v5=i["_0"];if(v4!=="B"){e[1](v4)}let v6=v5["payload"];v3=v5}}else{let v0=i["TAG"],v1=i["_0"];if(v0!=="A"){e[0](v0)}let v2=v1["payload"];v3=v1}return v3}`, ) let x = { @@ -567,7 +567,7 @@ module CknittelBugReport2 = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{if(!i||i.constructor!==Object){e[5](i)}let v0=i["test"],v4;if(v0!==void 0){let v2=v0;if(!v0||v0.constructor!==Object||v0["type"]!=="a"){if(!v0||v0.constructor!==Object||v0["type"]!=="b"){e[4](v0)}else{let v3=v0["y"];if(typeof v3!=="string"){e[2](v3)}v2={"TAG":e[3],"_0":{"y":v3,},}}}else{let v1=v0["x"];if(typeof v1!=="number"||v1>2147483647||v1<-2147483648||v1%1!==0){e[0](v1)}v2={"TAG":e[1],"_0":{"x":v1,},}}v4=v2}return {"test":v4,}}`, + `i=>{if(typeof i!=="object"||!i){e[5](i)}let v0=i["test"],v4;if(v0!==void 0){let v2=v0;if(typeof v0!=="object"||!v0||v0["type"]!=="a"){if(typeof v0!=="object"||!v0||v0["type"]!=="b"){e[4](v0)}else{let v3=v0["y"];if(typeof v3!=="string"){e[2](v3)}v2={"TAG":e[3],"_0":{"y":v3,},}}}else{let v1=v0["x"];if(typeof v1!=="number"||v1>2147483647||v1<-2147483648||v1%1!==0){e[0](v1)}v2={"TAG":e[1],"_0":{"x":v1,},}}v4=v2}return {"test":v4,}}`, ) t->Assert.deepEqual(S.parseJsonStringOrThrow("{}", schema), {test: None}, ()) @@ -594,7 +594,7 @@ module CknittelBugReport2 = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{let v3=i;if(!i||i.constructor!==Object){e[10](i)}else{try{let v0=i["statusCode"];if(!v0||v0.constructor!==Object||v0["kind"]!=="ok"||false){e[0](v0)}let v1=v0["text"];try{if(v1!==""){e[2](v1)}}catch(v2){if(v2&&v2.s===s){v1=e[1](v1,v2)}else{throw v2}}v3={"TAG":e[3],"_0":e[4],}}catch(e0){try{let v4=i["statusCode"];if(!v4||v4.constructor!==Object||v4["kind"]!=="serviceError"){e[5](v4)}let v5=v4["serviceCode"],v6=v4["text"];if(typeof v5!=="string"){e[6](v5)}if(typeof v6!=="string"){e[7](v6)}v3={"TAG":e[8],"_0":{"serviceCode":v5,"text":v6,},}}catch(e1){e[9]([e0,e1,])}}}return v3}`, + `i=>{let v3=i;if(typeof i!=="object"||!i){e[10](i)}else{try{let v0=i["statusCode"];if(typeof v0!=="object"||!v0||v0["kind"]!=="ok"||false){e[0](v0)}let v1=v0["text"];try{if(v1!==""){e[2](v1)}}catch(v2){if(v2&&v2.s===s){v1=e[1](v1,v2)}else{throw v2}}v3={"TAG":e[3],"_0":e[4],}}catch(e0){try{let v4=i["statusCode"];if(typeof v4!=="object"||!v4||v4["kind"]!=="serviceError"){e[5](v4)}let v5=v4["serviceCode"],v6=v4["text"];if(typeof v5!=="string"){e[6](v5)}if(typeof v6!=="string"){e[7](v6)}v3={"TAG":e[8],"_0":{"serviceCode":v5,"text":v6,},}}catch(e1){e[9]([e0,e1,])}}}return v3}`, ) t->Assert.deepEqual( @@ -677,13 +677,13 @@ module CrazyUnion = { t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{let r0=i=>{let v5=i;if(!i||i.constructor!==Object||i["type"]!=="A"){if(i!=="B"){if(i!=="C"){if(i!=="D"){if(i!=="E"){if(i!=="F"){if(i!=="G"){if(i!=="H"){if(i!=="I"){if(i!=="J"){if(i!=="K"){if(i!=="L"){if(i!=="M"){if(i!=="N"){if(i!=="O"){if(i!=="P"){if(i!=="Q"){if(i!=="R"){if(i!=="S"){if(i!=="T"){if(i!=="U"){if(i!=="V"){if(i!=="W"){if(i!=="X"){if(i!=="Y"){if(!i||i.constructor!==Object||i["type"]!=="Z"){e[4](i)}else{let v6=i["nested"],v10=new Array(v6.length);if(!Array.isArray(v6)){e[2](v6)}for(let v7=0;v7{let r0=i=>{let v5=i;if(typeof i!=="object"||!i||i["type"]!=="A"){if(i!=="B"){if(i!=="C"){if(i!=="D"){if(i!=="E"){if(i!=="F"){if(i!=="G"){if(i!=="H"){if(i!=="I"){if(i!=="J"){if(i!=="K"){if(i!=="L"){if(i!=="M"){if(i!=="N"){if(i!=="O"){if(i!=="P"){if(i!=="Q"){if(i!=="R"){if(i!=="S"){if(i!=="T"){if(i!=="U"){if(i!=="V"){if(i!=="W"){if(i!=="X"){if(i!=="Y"){if(typeof i!=="object"||!i||i["type"]!=="Z"){e[4](i)}else{let v6=i["nested"],v10=new Array(v6.length);if(!Array.isArray(v6)){e[2](v6)}for(let v7=0;v7 { S.setGlobalConfig({}) - let code = `i=>{let r0=i=>{let v6=i;if(!i||i.constructor!==Object||i["TAG"]!=="A"){if(i!=="B"){if(i!=="C"){if(i!=="D"){if(i!=="E"){if(i!=="F"){if(i!=="G"){if(i!=="H"){if(i!=="I"){if(i!=="J"){if(i!=="K"){if(i!=="L"){if(i!=="M"){if(i!=="N"){if(i!=="O"){if(i!=="P"){if(i!=="Q"){if(i!=="R"){if(i!=="S"){if(i!=="T"){if(i!=="U"){if(i!=="V"){if(i!=="W"){if(i!=="X"){if(i!=="Y"){if(!i||i.constructor!==Object||i["TAG"]!=="Z"){e[4](i)}else{let v7=i["TAG"],v8=i["_0"],v12=new Array(v8.length);if(v7!=="Z"){e[2](v7)}for(let v9=0;v9{let r0=i=>{let v6=i;if(typeof i!=="object"||!i||i["TAG"]!=="A"){if(i!=="B"){if(i!=="C"){if(i!=="D"){if(i!=="E"){if(i!=="F"){if(i!=="G"){if(i!=="H"){if(i!=="I"){if(i!=="J"){if(i!=="K"){if(i!=="L"){if(i!=="M"){if(i!=="N"){if(i!=="O"){if(i!=="P"){if(i!=="Q"){if(i!=="R"){if(i!=="S"){if(i!=="T"){if(i!=="U"){if(i!=="V"){if(i!=="W"){if(i!=="X"){if(i!=="Y"){if(typeof i!=="object"||!i||i["TAG"]!=="Z"){e[4](i)}else{let v7=i["TAG"],v8=i["_0"],v12=new Array(v8.length);if(v7!=="Z"){e[2](v7)}for(let v9=0;v9U.assertCompiledCode(~schema, ~op=#ReverseConvert, code) // There was an issue with reverse when it doesn't return the same code on second run t->U.assertCompiledCode(~schema, ~op=#ReverseConvert, code) @@ -765,12 +765,12 @@ test("Issue https://github.com/DZakh/rescript-schema/issues/101", t => { t->U.assertCompiledCode( ~schema, ~op=#ReverseConvert, - `i=>{let v2=i;if(!i||i.constructor!==Object||i["NAME"]!=="request"){if(!i||i.constructor!==Object||i["NAME"]!=="response"){e[3](i)}else{let v3=i["NAME"],v4=i["VAL"];if(v3!=="response"){e[1](v3)}let v5=v4["response"];if(v5!=="accepted"){if(v5!=="rejected"){e[2](v5)}}v2={"NAME":v3,"VAL":{"collectionName":v4["collectionName"],"response":v5,},}}}else{let v0=i["NAME"],v1=i["VAL"];if(v0!=="request"){e[0](v0)}v2=i}return v2}`, + `i=>{let v2=i;if(typeof i!=="object"||!i||i["NAME"]!=="request"){if(typeof i!=="object"||!i||i["NAME"]!=="response"){e[3](i)}else{let v3=i["NAME"],v4=i["VAL"];if(v3!=="response"){e[1](v3)}let v5=v4["response"];if(v5!=="accepted"){if(v5!=="rejected"){e[2](v5)}}v2={"NAME":v3,"VAL":{"collectionName":v4["collectionName"],"response":v5,},}}}else{let v0=i["NAME"],v1=i["VAL"];if(v0!=="request"){e[0](v0)}v2=i}return v2}`, ) t->U.assertCompiledCode( ~schema, ~op=#Parse, - `i=>{let v2=i;if(!i||i.constructor!==Object||i["NAME"]!=="request"){if(!i||i.constructor!==Object||i["NAME"]!=="response"){e[5](i)}else{let v3=i["VAL"];if(!v3||v3.constructor!==Object){e[2](v3)}let v4=v3["collectionName"],v5=v3["response"];if(typeof v4!=="string"){e[3](v4)}if(v5!=="accepted"){if(v5!=="rejected"){e[4](v5)}}v2={"NAME":i["NAME"],"VAL":{"collectionName":v4,"response":v5,},}}}else{let v0=i["VAL"];if(!v0||v0.constructor!==Object){e[0](v0)}let v1=v0["collectionName"];if(typeof v1!=="string"){e[1](v1)}v2={"NAME":i["NAME"],"VAL":{"collectionName":v1,},}}return v2}`, + `i=>{let v2=i;if(typeof i!=="object"||!i||i["NAME"]!=="request"){if(typeof i!=="object"||!i||i["NAME"]!=="response"){e[5](i)}else{let v3=i["VAL"];if(typeof v3!=="object"||!v3){e[2](v3)}let v4=v3["collectionName"],v5=v3["response"];if(typeof v4!=="string"){e[3](v4)}if(v5!=="accepted"){if(v5!=="rejected"){e[4](v5)}}v2={"NAME":i["NAME"],"VAL":{"collectionName":v4,"response":v5,},}}}else{let v0=i["VAL"];if(typeof v0!=="object"||!v0){e[0](v0)}let v1=v0["collectionName"];if(typeof v1!=="string"){e[1](v1)}v2={"NAME":i["NAME"],"VAL":{"collectionName":v1,},}}return v2}`, ) t->Assert.deepEqual( diff --git a/packages/tests/src/core/S_unnest_test.res b/packages/tests/src/core/S_unnest_test.res index f888da36..3a4b7ca7 100644 --- a/packages/tests/src/core/S_unnest_test.res +++ b/packages/tests/src/core/S_unnest_test.res @@ -28,7 +28,7 @@ test("Successfully parses and reverse converts a simple object with unnest", t = t->U.assertCompiledCode( ~schema, ~op=#ReverseParse, - `i=>{if(!Array.isArray(i)){e[3](i)}let v1=[new Array(i.length),new Array(i.length),];for(let v0=0;v02147483647||v5<-2147483648||v5%1!==0){e[2](v5)}v1[0][v0]=v4;v1[1][v0]=v5;}catch(v2){if(v2&&v2.s===s){v2.path=""+\'["\'+v0+\'"]\'+v2.path}throw v2}}return v1}`, + `i=>{if(!Array.isArray(i)){e[3](i)}let v1=[new Array(i.length),new Array(i.length),];for(let v0=0;v02147483647||v5<-2147483648||v5%1!==0){e[2](v5)}v1[0][v0]=v4;v1[1][v0]=v5;}catch(v2){if(v2&&v2.s===s){v2.path=""+\'["\'+v0+\'"]\'+v2.path}throw v2}}return v1}`, ) t->Assert.deepEqual( diff --git a/packages/tests/src/genType/GenType.gen.ts b/packages/tests/src/genType/GenType.gen.ts index 91da293c..09c42842 100644 --- a/packages/tests/src/genType/GenType.gen.ts +++ b/packages/tests/src/genType/GenType.gen.ts @@ -3,7 +3,7 @@ /* eslint-disable */ /* tslint:disable */ -import * as GenTypeJS from './GenType.bs.mjs'; +import * as GenTypeJS from './GenType.res.mjs'; import type {S_error as RescriptSchema_S_error} from 'rescript-schema/RescriptSchema.gen'; diff --git a/packages/tests/src/genType/GenType.bs.mjs b/packages/tests/src/genType/GenType.res.mjs similarity index 76% rename from packages/tests/src/genType/GenType.bs.mjs rename to packages/tests/src/genType/GenType.res.mjs index 75deb151..7354eec2 100644 --- a/packages/tests/src/genType/GenType.bs.mjs +++ b/packages/tests/src/genType/GenType.res.mjs @@ -1,7 +1,7 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as U from "../utils/U.bs.mjs"; -import * as S$RescriptSchema from "rescript-schema/src/S.bs.mjs"; +import * as U from "../utils/U.res.mjs"; +import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs"; var error = U.error({ operation: "Parse", diff --git a/packages/tests/src/ppx/Ppx_Example_test.bs.mjs b/packages/tests/src/ppx/Ppx_Example_test.res.mjs similarity index 97% rename from packages/tests/src/ppx/Ppx_Example_test.bs.mjs rename to packages/tests/src/ppx/Ppx_Example_test.res.mjs index a14e59b0..a8135dc4 100644 --- a/packages/tests/src/ppx/Ppx_Example_test.bs.mjs +++ b/packages/tests/src/ppx/Ppx_Example_test.res.mjs @@ -1,8 +1,8 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as U from "../utils/U.bs.mjs"; +import * as U from "../utils/U.res.mjs"; import Ava from "ava"; -import * as S$RescriptSchema from "rescript-schema/src/S.bs.mjs"; +import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs"; var ratingSchema = S$RescriptSchema.union([ S$RescriptSchema.literal("G"), diff --git a/packages/tests/src/ppx/Ppx_General_test.bs.mjs b/packages/tests/src/ppx/Ppx_General_test.res.mjs similarity index 96% rename from packages/tests/src/ppx/Ppx_General_test.bs.mjs rename to packages/tests/src/ppx/Ppx_General_test.res.mjs index e273eefa..1d3bb390 100644 --- a/packages/tests/src/ppx/Ppx_General_test.bs.mjs +++ b/packages/tests/src/ppx/Ppx_General_test.res.mjs @@ -1,8 +1,8 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as U from "../utils/U.bs.mjs"; +import * as U from "../utils/U.res.mjs"; import Ava from "ava"; -import * as S$RescriptSchema from "rescript-schema/src/S.bs.mjs"; +import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs"; Ava("Creates schema with the name schema from t type", (function (t) { U.assertEqualSchemas(t, S$RescriptSchema.string, S$RescriptSchema.string, undefined); diff --git a/packages/tests/src/ppx/Ppx_Object_test.bs.mjs b/packages/tests/src/ppx/Ppx_Object_test.res.mjs similarity index 94% rename from packages/tests/src/ppx/Ppx_Object_test.bs.mjs rename to packages/tests/src/ppx/Ppx_Object_test.res.mjs index b3215d6e..47927fae 100644 --- a/packages/tests/src/ppx/Ppx_Object_test.bs.mjs +++ b/packages/tests/src/ppx/Ppx_Object_test.res.mjs @@ -1,8 +1,8 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as U from "../utils/U.bs.mjs"; +import * as U from "../utils/U.res.mjs"; import Ava from "ava"; -import * as S$RescriptSchema from "rescript-schema/src/S.bs.mjs"; +import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs"; var simpleObjectSchema = S$RescriptSchema.schema(function (s) { return { diff --git a/packages/tests/src/ppx/Ppx_Polyvariant_test.bs.mjs b/packages/tests/src/ppx/Ppx_Polyvariant_test.res.mjs similarity index 95% rename from packages/tests/src/ppx/Ppx_Polyvariant_test.bs.mjs rename to packages/tests/src/ppx/Ppx_Polyvariant_test.res.mjs index b1249a90..a0f43435 100644 --- a/packages/tests/src/ppx/Ppx_Polyvariant_test.bs.mjs +++ b/packages/tests/src/ppx/Ppx_Polyvariant_test.res.mjs @@ -1,8 +1,8 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as U from "../utils/U.bs.mjs"; +import * as U from "../utils/U.res.mjs"; import Ava from "ava"; -import * as S$RescriptSchema from "rescript-schema/src/S.bs.mjs"; +import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs"; var polySchema = S$RescriptSchema.union([ S$RescriptSchema.literal("one"), diff --git a/packages/tests/src/ppx/Ppx_Primitive_test.bs.mjs b/packages/tests/src/ppx/Ppx_Primitive_test.res.mjs similarity index 98% rename from packages/tests/src/ppx/Ppx_Primitive_test.bs.mjs rename to packages/tests/src/ppx/Ppx_Primitive_test.res.mjs index 7414a88a..ee7fd013 100644 --- a/packages/tests/src/ppx/Ppx_Primitive_test.bs.mjs +++ b/packages/tests/src/ppx/Ppx_Primitive_test.res.mjs @@ -1,8 +1,8 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as U from "../utils/U.bs.mjs"; +import * as U from "../utils/U.res.mjs"; import Ava from "ava"; -import * as S$RescriptSchema from "rescript-schema/src/S.bs.mjs"; +import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs"; Ava("String schema", (function (t) { U.assertEqualSchemas(t, S$RescriptSchema.string, S$RescriptSchema.string, undefined); diff --git a/packages/tests/src/ppx/Ppx_Record_test.bs.mjs b/packages/tests/src/ppx/Ppx_Record_test.res.mjs similarity index 97% rename from packages/tests/src/ppx/Ppx_Record_test.bs.mjs rename to packages/tests/src/ppx/Ppx_Record_test.res.mjs index f8ac5ed6..f70b0676 100644 --- a/packages/tests/src/ppx/Ppx_Record_test.bs.mjs +++ b/packages/tests/src/ppx/Ppx_Record_test.res.mjs @@ -1,8 +1,8 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as U from "../utils/U.bs.mjs"; +import * as U from "../utils/U.res.mjs"; import Ava from "ava"; -import * as S$RescriptSchema from "rescript-schema/src/S.bs.mjs"; +import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs"; var simpleRecordSchema = S$RescriptSchema.schema(function (s) { return { diff --git a/packages/tests/src/ppx/Ppx_Variant_test.bs.mjs b/packages/tests/src/ppx/Ppx_Variant_test.res.mjs similarity index 98% rename from packages/tests/src/ppx/Ppx_Variant_test.bs.mjs rename to packages/tests/src/ppx/Ppx_Variant_test.res.mjs index b9fabd68..16d853c2 100644 --- a/packages/tests/src/ppx/Ppx_Variant_test.bs.mjs +++ b/packages/tests/src/ppx/Ppx_Variant_test.res.mjs @@ -1,8 +1,8 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as U from "../utils/U.bs.mjs"; +import * as U from "../utils/U.res.mjs"; import Ava from "ava"; -import * as S$RescriptSchema from "rescript-schema/src/S.bs.mjs"; +import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs"; var variantSchema = S$RescriptSchema.union([ S$RescriptSchema.literal("One"), diff --git a/packages/tests/src/utils/U.bs.mjs b/packages/tests/src/utils/U.res.mjs similarity index 98% rename from packages/tests/src/utils/U.bs.mjs rename to packages/tests/src/utils/U.res.mjs index e37e95b2..224d08c1 100644 --- a/packages/tests/src/utils/U.bs.mjs +++ b/packages/tests/src/utils/U.res.mjs @@ -2,7 +2,7 @@ import * as Caml_option from "rescript/lib/es6/caml_option.js"; import * as Caml_exceptions from "rescript/lib/es6/caml_exceptions.js"; -import * as S$RescriptSchema from "rescript-schema/src/S.bs.mjs"; +import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs"; import * as Caml_js_exceptions from "rescript/lib/es6/caml_js_exceptions.js"; function unsafeGetVariantPayload(variant) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 96afacc6..08f2389a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@rescript/core': specifier: ^1.3.0 version: 1.3.0(rescript@11.1.0) + arktype: + specifier: 2.0.4 + version: 2.0.4 ava: specifier: 5.2.0 version: 5.2.0 @@ -53,6 +56,12 @@ importers: '@rescript/core': specifier: 1.3.0 version: 1.3.0(rescript@11.1.0) + '@rollup/plugin-commonjs': + specifier: 28.0.2 + version: 28.0.2(rollup@3.21.0) + '@rollup/plugin-node-resolve': + specifier: 16.0.0 + version: 16.0.0(rollup@3.21.0) '@rollup/plugin-replace': specifier: 5.0.2 version: 5.0.2(rollup@3.21.0) @@ -82,6 +91,12 @@ importers: packages: + '@ark/schema@0.39.0': + resolution: {integrity: sha512-LQbQUb3Sj461LgklXObAyUJNtsUUCBxZlO2HqRLYvRSqpStm0xTMrXn51DwBNNxeSULvKVpXFwoxiSec9kwKww==} + + '@ark/util@0.39.0': + resolution: {integrity: sha512-90APHVklk8BP4kku7hIh1BgrhuyKYqoZ4O7EybtFRo7cDl9mIyc/QUbGvYDg//73s0J2H0I/gW9pzroA1R4IBQ==} + '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} @@ -115,6 +130,9 @@ packages: '@jridgewell/sourcemap-codec@1.4.15': resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/trace-mapping@0.3.18': resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} @@ -139,6 +157,24 @@ packages: peerDependencies: rescript: ^11.1.0-rc.7 + '@rollup/plugin-commonjs@28.0.2': + resolution: {integrity: sha512-BEFI2EDqzl+vA1rl97IDRZ61AIwGH093d9nz8+dThxJNH8oSoB7MjWvPCX3dkaK1/RCJ/1v/R1XB15FuSs0fQw==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@16.0.0': + resolution: {integrity: sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/plugin-replace@5.0.2': resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==} engines: {node: '>=14.0.0'} @@ -163,6 +199,9 @@ packages: '@types/istanbul-lib-coverage@2.0.4': resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + acorn-walk@8.3.4: resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} engines: {node: '>=0.4.0'} @@ -199,6 +238,9 @@ packages: argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + arktype@2.0.4: + resolution: {integrity: sha512-S68rWVDnJauwH7/QCm8zCUM3aTe9Xk6oRihdcc3FSUAtxCo/q1Fwq46JhcwB5Ufv1YStwdQRz+00Y/URlvbhAQ==} + array-find-index@1.0.2: resolution: {integrity: sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==} engines: {node: '>=0.10.0'} @@ -311,6 +353,9 @@ packages: common-path-prefix@3.0.0: resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -346,6 +391,10 @@ packages: supports-color: optional: true + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + del@7.0.0: resolution: {integrity: sha512-tQbV/4u5WVB8HMJr08pgw0b6nG4RGt/tj+7Numvq+zqcvUFeMaIWWOUFltiU+6go8BSO2/ogsB4EasDaj0y68Q==} engines: {node: '>=14.16'} @@ -405,6 +454,14 @@ packages: fastq@1.15.0: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + figures@5.0.0: resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} engines: {node: '>=14'} @@ -437,6 +494,9 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -460,6 +520,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globby@13.2.1: resolution: {integrity: sha512-DPCBxctI7dN4EeIqjW2KGqgdcUMbrhJ9AzON+PlxCtvppWhubTLD4+a0GFxiym14ZvacUydTPjLPc2DlKz7EIg==} @@ -472,6 +533,10 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -497,6 +562,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -509,6 +575,10 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + is-error@2.2.2: resolution: {integrity: sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==} @@ -528,6 +598,9 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -547,6 +620,9 @@ packages: is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -615,6 +691,9 @@ packages: resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} engines: {node: '>=12'} + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -754,6 +833,9 @@ packages: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.11.1: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} @@ -770,6 +852,10 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -814,6 +900,7 @@ packages: rescript-struct@5.1.1: resolution: {integrity: sha512-e2WOrwMvAgZaJBFAhMBdGZcSoieK6DKkzgQVqTvfTga+3vFGkvpH3sDVNF2qLEcyEC9wIcx1qcNYWaAVvlCKhQ==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. peerDependencies: rescript: 11.0.x || ~11.0.0-rc @@ -835,12 +922,18 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rimraf@5.0.10: @@ -884,10 +977,6 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - signal-exit@4.0.2: - resolution: {integrity: sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==} - engines: {node: '>=14'} - signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -946,6 +1035,10 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + temp-dir@3.0.0: resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} engines: {node: '>=14.16'} @@ -1057,6 +1150,12 @@ packages: snapshots: + '@ark/schema@0.39.0': + dependencies: + '@ark/util': 0.39.0 + + '@ark/util@0.39.0': {} + '@bcoe/v8-coverage@0.2.3': {} '@dzakh/rescript-ava@2.3.0(ava@5.2.0)(rescript@11.1.0)': @@ -1087,6 +1186,8 @@ snapshots: '@jridgewell/sourcemap-codec@1.4.15': {} + '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/trace-mapping@0.3.18': dependencies: '@jridgewell/resolve-uri': 3.1.0 @@ -1111,6 +1212,28 @@ snapshots: dependencies: rescript: 11.1.0 + '@rollup/plugin-commonjs@28.0.2(rollup@3.21.0)': + dependencies: + '@rollup/pluginutils': 5.0.2(rollup@3.21.0) + commondir: 1.0.1 + estree-walker: 2.0.2 + fdir: 6.4.3(picomatch@4.0.2) + is-reference: 1.2.1 + magic-string: 0.30.17 + picomatch: 4.0.2 + optionalDependencies: + rollup: 3.21.0 + + '@rollup/plugin-node-resolve@16.0.0(rollup@3.21.0)': + dependencies: + '@rollup/pluginutils': 5.0.2(rollup@3.21.0) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.10 + optionalDependencies: + rollup: 3.21.0 + '@rollup/plugin-replace@5.0.2(rollup@3.21.0)': dependencies: '@rollup/pluginutils': 5.0.2(rollup@3.21.0) @@ -1130,6 +1253,8 @@ snapshots: '@types/istanbul-lib-coverage@2.0.4': {} + '@types/resolve@1.20.2': {} + acorn-walk@8.3.4: dependencies: acorn: 8.14.0 @@ -1160,6 +1285,11 @@ snapshots: dependencies: sprintf-js: 1.0.3 + arktype@2.0.4: + dependencies: + '@ark/schema': 0.39.0 + '@ark/util': 0.39.0 + array-find-index@1.0.2: {} arrgv@1.0.2: {} @@ -1318,6 +1448,8 @@ snapshots: common-path-prefix@3.0.0: {} + commondir@1.0.1: {} + concat-map@0.0.1: {} concordance@5.0.4: @@ -1353,6 +1485,8 @@ snapshots: dependencies: ms: 2.1.3 + deepmerge@4.3.1: {} + del@7.0.0: dependencies: globby: 13.2.1 @@ -1414,6 +1548,10 @@ snapshots: dependencies: reusify: 1.0.4 + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + figures@5.0.0: dependencies: escape-string-regexp: 5.0.0 @@ -1448,6 +1586,8 @@ snapshots: fsevents@2.3.2: optional: true + function-bind@1.1.2: {} + get-caller-file@2.0.5: {} get-stream@6.0.1: {} @@ -1495,6 +1635,10 @@ snapshots: has-flag@4.0.0: {} + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + html-escaper@2.0.2: {} human-signals@4.3.1: {} @@ -1520,6 +1664,10 @@ snapshots: dependencies: binary-extensions: 2.2.0 + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + is-error@2.2.2: {} is-extglob@2.1.1: {} @@ -1532,6 +1680,8 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-module@1.0.0: {} + is-number@7.0.0: {} is-path-cwd@3.0.0: {} @@ -1542,6 +1692,10 @@ snapshots: is-promise@4.0.0: {} + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.1 + is-stream@3.0.0: {} is-unicode-supported@1.3.0: {} @@ -1602,6 +1756,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.4.15 + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + make-dir@3.1.0: dependencies: semver: 6.3.0 @@ -1712,6 +1870,8 @@ snapshots: path-key@4.0.0: {} + path-parse@1.0.7: {} + path-scurry@1.11.1: dependencies: lru-cache: 10.4.3 @@ -1726,6 +1886,8 @@ snapshots: picomatch@2.3.1: {} + picomatch@4.0.2: {} + pirates@4.0.6: {} pkg-conf@4.0.0: @@ -1778,6 +1940,12 @@ snapshots: resolve-from@5.0.0: {} + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + reusify@1.0.4: {} rimraf@3.0.2: @@ -1819,8 +1987,6 @@ snapshots: signal-exit@3.0.7: {} - signal-exit@4.0.2: {} - signal-exit@4.1.0: {} slash@3.0.0: {} @@ -1879,6 +2045,8 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} + temp-dir@3.0.0: {} test-exclude@6.0.0: @@ -1947,7 +2115,7 @@ snapshots: write-file-atomic@5.0.1: dependencies: imurmurhash: 0.1.4 - signal-exit: 4.0.2 + signal-exit: 4.1.0 y18n@5.0.8: {} diff --git a/rescript.json b/rescript.json index 6d3e1f0d..46a771bc 100644 --- a/rescript.json +++ b/rescript.json @@ -1,7 +1,7 @@ { "name": "rescript-schema", "namespace": true, - "suffix": ".bs.mjs", + "suffix": ".res.mjs", "package-specs": { "module": "esmodule", "in-source": true diff --git a/src/S.d.ts b/src/S.d.ts index 30603941..27e70a4c 100644 --- a/src/S.d.ts +++ b/src/S.d.ts @@ -1,6 +1,77 @@ import { Json, Result, S_t } from "../RescriptSchema.gen"; export { Json, Result, S_error as Error } from "../RescriptSchema.gen"; +/** The Standard Schema interface. */ +export interface StandardSchemaV1 { + /** The Standard Schema properties. */ + readonly "~standard": StandardSchemaV1.Props; +} + +export declare namespace StandardSchemaV1 { + /** The Standard Schema properties interface. */ + export interface Props { + /** The version number of the standard. */ + readonly version: 1; + /** The vendor name of the schema library. */ + readonly vendor: string; + /** Validates unknown input values. */ + readonly validate: ( + value: unknown + ) => Result | Promise>; + /** Inferred types associated with the schema. */ + readonly types?: Types | undefined; + } + + /** The result interface of the validate function. */ + export type Result = SuccessResult | FailureResult; + + /** The result interface if validation succeeds. */ + export interface SuccessResult { + /** The typed output value. */ + readonly value: Output; + /** The non-existent issues. */ + readonly issues?: undefined; + } + + /** The result interface if validation fails. */ + export interface FailureResult { + /** The issues of failed validation. */ + readonly issues: ReadonlyArray; + } + + /** The issue interface of the failure output. */ + export interface Issue { + /** The error message of the issue. */ + readonly message: string; + /** The path of the issue, if any. */ + readonly path?: ReadonlyArray | undefined; + } + + /** The path segment interface of the issue. */ + export interface PathSegment { + /** The key representing a path segment. */ + readonly key: PropertyKey; + } + + /** The Standard Schema types interface. */ + export interface Types { + /** The input type of the schema. */ + readonly input: Input; + /** The output type of the schema. */ + readonly output: Output; + } + + /** Infers the input type of a Standard Schema. */ + export type InferInput = NonNullable< + Schema["~standard"]["types"] + >["input"]; + + /** Infers the output type of a Standard Schema. */ + export type InferOutput = NonNullable< + Schema["~standard"]["types"] + >["output"]; +} + export type EffectCtx = { schema: Schema; fail: (message: string) => never; @@ -441,3 +512,9 @@ export function compile< : ModeOption extends "Async" ? Promise[OutputOption]> : never; + +export function standard( + schema: Schema +): { + ["~standard"]: StandardSchemaV1.Props; +}; diff --git a/src/S.js b/src/S.js index 14e41fee..c03b89d7 100644 --- a/src/S.js +++ b/src/S.js @@ -1,4 +1,4 @@ -import * as S from "./S_Core.bs.mjs"; +import * as S from "./S_Core.res.mjs"; export const Error = S.$$Error.$$class; export const string = S.string; @@ -42,6 +42,7 @@ export const deepStrict = S.deepStrict; export const strip = S.strip; export const deepStrip = S.deepStrip; export const custom = S.js_custom; +export const standard = S.standard; export const tuple = S.tuple; export const asyncParserRefine = S.js_asyncParserRefine; export const refine = S.js_refine; diff --git a/src/S.bs.mjs b/src/S.res.mjs similarity index 99% rename from src/S.bs.mjs rename to src/S.res.mjs index cd0deb7a..62567532 100644 --- a/src/S.bs.mjs +++ b/src/S.res.mjs @@ -1,6 +1,6 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as S_Core$RescriptSchema from "./S_Core.bs.mjs"; +import * as S_Core$RescriptSchema from "./S_Core.res.mjs"; var Path = S_Core$RescriptSchema.Path; diff --git a/src/S_Core.res b/src/S_Core.res index 200be7c8..22a63414 100644 --- a/src/S_Core.res +++ b/src/S_Core.res @@ -1137,7 +1137,7 @@ module Literal = { `${inputVar}!==${b->B.embed( value, - )}&&(!${inputVar}||${inputVar}.constructor!==Object||Object.keys(${inputVar}).length!==${numberOfFields->Stdlib.Int.unsafeToString}` ++ + )}&&(typeof ${inputVar}!=="object"||!${inputVar}||Object.keys(${inputVar}).length!==${numberOfFields->Stdlib.Int.unsafeToString}` ++ (numberOfFields > 0 ? "||" ++ fields @@ -2127,8 +2127,12 @@ module Object = { } let typeFilter = (b, ~inputVar) => { - let code = ref(`!${inputVar}||${inputVar}.constructor!==Object`) let tagged = %raw(`this`)->classify->Obj.magic + let code = ref( + `typeof ${inputVar}!=="object"||!${inputVar}` ++ ( + tagged["unknownKeys"] === Strict ? `||Array.isArray(${inputVar})` : "" + ), + ) let items = tagged["items"] for idx in 0 to items->Js.Array2.length - 1 { let {schema, inlinedLocation} = items->Js.Array2.unsafe_get(idx) @@ -2251,7 +2255,7 @@ module Tuple = { } module Dict = { - let typeFilter = (_b, ~inputVar) => `!${inputVar}||${inputVar}.constructor!==Object` + let typeFilter = (_b, ~inputVar) => `typeof ${inputVar}!=="object"||!${inputVar}` let rec factory = schema => { let schema = schema->toUnknown @@ -4752,6 +4756,33 @@ let js_merge = (s1, s2) => { let js_name = name +let standard = schema => { + let parseOrThrow = compile(schema, ~input=Any, ~output=Value, ~mode=Sync, ~typeValidation=true) + { + "~standard": { + "version": 1, + "vendor": "rescript-schema", + "validate": input => { + try { + {"value": parseOrThrow(input)} + } catch { + | _ => { + let error = %raw(`exn`)->InternalError.getOrRethrow + { + "issues": [ + { + "message": error->Error.message, + "path": error.path === Path.empty ? None : Some(error.path->Path.toArray), + }, + ], + }->Obj.magic + } + } + }, + }, + } +} + let resetOperationsCache: schema<'value> => unit = %raw(`(schema) => { for (let key in schema) { if (+key) { diff --git a/src/S_Core.bs.mjs b/src/S_Core.res.mjs similarity index 99% rename from src/S_Core.bs.mjs rename to src/S_Core.res.mjs index a8e0bc70..1fae3461 100644 --- a/src/S_Core.bs.mjs +++ b/src/S_Core.res.mjs @@ -603,7 +603,7 @@ function dictFilterBuilder(b, inputVar, literal) { var items = literal.i; var fields = Object.keys(items); var numberOfFields = fields.length; - return inputVar + "!==" + embed(b, value) + "&&(!" + inputVar + "||" + inputVar + ".constructor!==Object||Object.keys(" + inputVar + ").length!==" + numberOfFields + ( + return inputVar + "!==" + embed(b, value) + "&&(typeof " + inputVar + "!==\"object\"||!" + inputVar + "||Object.keys(" + inputVar + ").length!==" + numberOfFields + ( numberOfFields > 0 ? "||" + fields.map(function (field) { var literal = items[field]; return literal.f(b, inputVar + "[" + fromString(field) + "]", literal); @@ -1404,8 +1404,10 @@ function factory$2(schema) { } function typeFilter$1(b, inputVar) { - var code = "!" + inputVar + "||" + inputVar + ".constructor!==Object"; var tagged = this.t; + var code = "typeof " + inputVar + "!==\"object\"||!" + inputVar + ( + tagged.unknownKeys === "Strict" ? "||Array.isArray(" + inputVar + ")" : "" + ); var items = tagged.items; for(var idx = 0 ,idx_finish = items.length; idx < idx_finish; ++idx){ var match = items[idx]; @@ -1522,7 +1524,7 @@ function typeFilter$2(b, inputVar) { } function typeFilter$3(_b, inputVar) { - return "!" + inputVar + "||" + inputVar + ".constructor!==Object"; + return "typeof " + inputVar + "!==\"object\"||!" + inputVar; } function factory$3(schema) { @@ -3637,6 +3639,32 @@ function js_name(prim) { return prim.n(); } +function standard(schema) { + var parseOrThrow = compile$1(schema, "Any", "Output", "Sync", true); + return { + "~standard": { + version: 1, + vendor: "rescript-schema", + validate: (function (input) { + try { + return { + value: parseOrThrow(input) + }; + } + catch (exn){ + var error = getOrRethrow(exn); + return { + issues: [{ + message: message(error), + path: error.path === "" ? undefined : toArray(error.path) + }] + }; + } + }) + } + }; +} + var resetOperationsCache = ((schema) => { for (let key in schema) { if (+key) { @@ -3875,6 +3903,7 @@ export { js_schema , js_merge , js_name , + standard , setGlobalConfig , } /* symbol Not a pure module */ diff --git a/src/S_Core.resi b/src/S_Core.resi index d0e1bffc..99ab45f9 100644 --- a/src/S_Core.resi +++ b/src/S_Core.resi @@ -437,6 +437,10 @@ let js_merge: (t, t) => t let js_name: t<'value> => string +let standard: t<'value> => { + "~standard": {"validate": 'any => {"value": 'value}, "vendor": string, "version": int}, +} + type globalConfigOverride = { defaultUnknownKeys?: unknownKeys, disableNanNumberValidation?: bool, diff --git a/test.js b/test.js index 96a99a5e..b793313e 100644 --- a/test.js +++ b/test.js @@ -1,7 +1,7 @@ (i) => { let v3 = i; - if (!i || i.constructor !== Object || i["NAME"] !== "request") { - if (!i || i.constructor !== Object || i["NAME"] !== "response") { + if (typeof i !== "object" || !i || i["NAME"] !== "request") { + if (typeof i !== "object" || !i || i["NAME"] !== "response") { e[3](i); } else { if (v0 !== "response") { diff --git a/wallaby.conf.js b/wallaby.conf.js index 1323d6aa..315867e5 100644 --- a/wallaby.conf.js +++ b/wallaby.conf.js @@ -7,10 +7,10 @@ const tests = packageJson.ava.files; export default () => ({ files: [ "package.json", - "src/S.bs.mjs", - "src/S_Core.bs.mjs", + "src/S.res.mjs", + "src/S_Core.res.mjs", "src/S.js", - "packages/tests/src/utils/U.bs.mjs", + "packages/tests/src/utils/U.res.mjs", ], tests, env: {