Skip to content

Commit

Permalink
Fix commonjs build
Browse files Browse the repository at this point in the history
  • Loading branch information
DZakh committed Feb 8, 2025
1 parent a44eee7 commit 3a2be71
Show file tree
Hide file tree
Showing 14 changed files with 573 additions and 342 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ node_modules
packages/tests/src/core/**/*_test.res.mjs
lib
coverage
dist
packages/artifacts
.tsimp
6 changes: 0 additions & 6 deletions IDEAS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ let trimContract: S.contract<string => string> = S.contract(s => {

- Use internal transform for trim

## v9.1

- [x] Update object type validation
- [ ] Support standard schema
- [ ] Make rescript an optional peer dependency

## v10

- Rename S.to to S.reshape
Expand Down
10 changes: 8 additions & 2 deletions docs/js-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -832,8 +832,14 @@ Reverses the schema. This gets especially magical for schemas with transformatio
### **`standard`**

```ts
S.standard(S.string);
// Returns StandardSchemaV1<string>
const docsSchema = S.schema({
id: S.number,
content: S.string,
});

// ┌─── StandardSchemaV1<{ id: number; content: string; }>
//
const standardSchema = S.standard(docsSchema);
```

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. 👀
Expand Down
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rescript-schema",
"version": "9.2.0",
"version": "9.2.1",
"private": true,
"description": "🧬 The fastest parser in the entire JavaScript ecosystem with a focus on small bundle size and top-notch DX",
"keywords": [
Expand Down Expand Up @@ -30,18 +30,19 @@
"license": "MIT",
"author": "Dmitry Zakharov <[email protected]>",
"type": "module",
"main": "./dist/S.js",
"module": "./dist/S.mjs",
"main": "./src/S.js",
"module": "./src/S.mjs",
"types": "./src/S.d.ts",
"files": [
"dist",
"src/S_Core.res",
"src/S_Core.res.js",
"src/S_Core.res.mjs",
"src/S.res",
"src/S.resi",
"src/S.res.js",
"src/S.res.mjs",
"src/S.js",
"src/S.mjs",
"src/S.d.ts",
"RescriptSchema.gen.d.ts",
"rescript.json"
Expand Down
2 changes: 0 additions & 2 deletions packages/prepack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
},
"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",
Expand Down
188 changes: 115 additions & 73 deletions packages/prepack/src/Prepack.res
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ let sourePaths = [
"README.md",
"RescriptSchema.gen.d.ts",
]
let jsInputPath = NodeJs.Path.join2(artifactsPath, "src/S.js")

module Stdlib = {
module Dict = {
Expand Down Expand Up @@ -67,19 +66,10 @@ module Rollup = {
type t
}

module ReplacePlugin = {
type options = {values: dict<string>}
@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,
Expand Down Expand Up @@ -124,6 +114,102 @@ if NodeJs.Fs.existsSync(artifactsPath) {
}
NodeJs.Fs.mkdirSync(artifactsPath)

let filesMapping = [
("Error", "S.$$Error.$$class"),
("string", "S.string"),
("boolean", "S.bool"),
("int32", "S.$$int"),
("number", "S.$$float"),
("bigint", "S.bigint"),
("json", "S.json"),
("never", "S.never"),
("unknown", "S.unknown"),
("undefined", "S.unit"),
("optional", "S.js_optional"),
("nullable", "S.$$null"),
("nullish", "S.nullable"),
("array", "S.array"),
("unnest", "S.unnest"),
("record", "S.dict"),
("jsonString", "S.jsonString"),
("union", "S.js_union"),
("object", "S.object"),
("schema", "S.js_schema"),
("safe", "S.js_safe"),
("safeAsync", "S.js_safeAsync"),
("reverse", "S.reverse"),
("convertOrThrow", "S.convertOrThrow"),
("convertToJsonOrThrow", "S.convertToJsonOrThrow"),
("convertToJsonStringOrThrow", "S.convertToJsonStringOrThrow"),
("reverseConvertOrThrow", "S.reverseConvertOrThrow"),
("reverseConvertToJsonOrThrow", "S.reverseConvertToJsonOrThrow"),
("reverseConvertToJsonStringOrThrow", " S.reverseConvertToJsonStringOrThrow"),
("parseOrThrow", "S.parseOrThrow"),
("parseJsonOrThrow", "S.parseJsonOrThrow"),
("parseJsonStringOrThrow", "S.parseJsonStringOrThrow"),
("parseAsyncOrThrow", "S.parseAsyncOrThrow"),
("assertOrThrow", "S.assertOrThrow"),
("recursive", "S.recursive"),
("merge", "S.js_merge"),
("strict", "S.strict"),
("deepStrict", "S.deepStrict"),
("strip", "S.strip"),
("deepStrip", "S.deepStrip"),
("custom", "S.js_custom"),
("standard", "S.standard"),
("tuple", "S.tuple"),
("asyncParserRefine", "S.js_asyncParserRefine"),
("refine", "S.js_refine"),
("transform", "S.js_transform"),
("description", "S.description"),
("describe", "S.describe"),
("name", "S.js_name"),
("setName", "S.setName"),
("removeTypeValidation", "S.removeTypeValidation"),
("compile", "S.compile"),
("port", "S.port"),
("numberMin", "S.floatMin"),
("numberMax", "S.floatMax"),
("arrayMinLength", "S.arrayMinLength"),
("arrayMaxLength", "S.arrayMaxLength"),
("arrayLength", "S.arrayLength"),
("stringMinLength", "S.stringMinLength"),
("stringMaxLength", "S.stringMaxLength"),
("stringLength", "S.stringLength"),
("email", "S.email"),
("uuid", "S.uuid"),
("cuid", "S.cuid"),
("url", "S.url"),
("pattern", "S.pattern"),
("datetime", "S.datetime"),
("trim", "S.trim"),
("setGlobalConfig", "S.setGlobalConfig"),
]

NodeJs.Fs.writeFileSyncWith(
"./src/S.mjs",
["import * as S from \"./S_Core.res.mjs\";"]
->Js.Array2.concat(
filesMapping->Js.Array2.map(((name, value)) => `export const ${name} = ${value}`),
)
->Js.Array2.joinWith("\n")
->NodeJs.Buffer.fromString,
{
encoding: "utf8",
},
)

NodeJs.Fs.writeFileSyncWith(
"./src/S.js",
["var S = require(\"./S_Core.res.mjs\");"]
->Js.Array2.concat(filesMapping->Js.Array2.map(((name, value)) => `exports.${name} = ${value}`))
->Js.Array2.joinWith("\n")
->NodeJs.Buffer.fromString,
{
encoding: "utf8",
},
)

sourePaths->Array.forEach(path => {
FsX.cpSync(
~src=NodeJs.Path.join2(projectPath, path),
Expand Down Expand Up @@ -153,85 +239,41 @@ let updateJsonFile = (~src, ~path, ~value) => {

let _ = Execa.sync("npm", ["run", "res:build"], ~options={cwd: artifactsPath}, ())

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<Rollup.OutputOptions.t> = [
{
file: NodeJs.Path.join2(artifactsPath, "dist/S.js"),
format: #cjs,
exports: #named,
plugins: [
Rollup.ReplacePlugin.make({
values: Dict.fromArray([
(`S_Core.res.mjs`, `../src/S_Core.res.js`),
(`rescript/lib/es6`, `rescript/lib/js`),
]),
}),
],
},
{
file: NodeJs.Path.join2(artifactsPath, "dist/S.mjs"),
format: #es,
exports: #named,
plugins: [
Rollup.ReplacePlugin.make({
values: Dict.fromArray([(`S_Core.res.mjs`, `../src/S_Core.res.mjs`)]),
}),
],
},
]
for idx in 0 to output->Array.length - 1 {
let outpuOptions = output->Array.getUnsafe(idx)
let _ = await bundle->Rollup.Bundle.write(outpuOptions)
}
await bundle->Rollup.Bundle.close

let resolveRescriptRuntime = async (~format, ~path) => {
let resolveRescriptRuntime = async (~format, ~input, ~output) => {
let bundle = await Rollup.Bundle.make({
input: NodeJs.Path.join2(artifactsPath, path),
plugins: [Rollup.NodeResolvePlugin.make(), Rollup.CommonjsPluggin.make()],
input: NodeJs.Path.join2(artifactsPath, input),
plugins: [Rollup.NodeResolvePlugin.make()],
})
let _ = await bundle->Rollup.Bundle.write({
file: NodeJs.Path.join2(artifactsPath, path),
file: NodeJs.Path.join2(artifactsPath, output),
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"),
~path=["package-specs", "module"],
~value=JSON.Encode.string("commonjs"),
)
updateJsonFile(
~src=NodeJs.Path.join2(artifactsPath, "rescript.json"),
~path=["suffix"],
~value=JSON.Encode.string(".res.js"),
)
let _ = Execa.sync("npm", ["run", "res:build"], ~options={cwd: artifactsPath}, ())
// 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, ~input="src/S_Core.res.mjs", ~output="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, ~input="src/S_Core.res.mjs", ~output="src/S_Core.res.js")
// Also build cjs version, in case some ReScript libraries will use rescript-schema without running a compiler (rescript-stdlib-vendorer)
await resolveRescriptRuntime(~format=#cjs, ~input="src/S.res.mjs", ~output="src/S.res.js")

// ReScript applications don't work with type: module set on packages
updateJsonFile(
~src=NodeJs.Path.join2(artifactsPath, "package.json"),
~path=["type"],
~value=JSON.Encode.string("commonjs"),
)
updateJsonFile(
~src=NodeJs.Path.join2(artifactsPath, "package.json"),
~path=["private"],
~value=JSON.Encode.bool(false),
)

// 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")
Loading

1 comment on commit 3a2be71

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 3a2be71 Previous: a44eee7 Ratio
S.schema - make 1354165 ops/sec (±0.56%) 1354467 ops/sec (±1.69%) 1.00
S.schema - make + parse 105485 ops/sec (±1.76%) 107084 ops/sec (±0.76%) 1.02
S.schema - parse 48875554 ops/sec (±3.08%) 59295398 ops/sec (±2.15%) 1.21
S.schema - parse strict 22455329 ops/sec (±1.92%) 23128983 ops/sec (±1.08%) 1.03
S.schema - make + reverse 923614 ops/sec (±0.85%) 485145 ops/sec (±1.01%) 0.53
S.schema - make + reverse convert 187479 ops/sec (±0.77%) 153040 ops/sec (±1.04%) 0.82
S.schema - reverse convert 57157218 ops/sec (±1.87%) 67243399 ops/sec (±2.39%) 1.18
S.schema - reverse convert (compiled) 132819948 ops/sec (±5.35%) 132052574 ops/sec (±4.16%) 0.99
S.schema - assert 50889930 ops/sec (±2.00%) 63079730 ops/sec (±3.00%) 1.24
S.schema - assert (compiled) 72129213 ops/sec (±2.84%) 72857233 ops/sec (±2.59%) 1.01
S.schema - assert strict 21096361 ops/sec (±0.84%) 23133197 ops/sec (±1.07%) 1.10
S.object - make 973424 ops/sec (±0.41%) 995948 ops/sec (±0.34%) 1.02
S.object - make + parse 88830 ops/sec (±0.19%) 91218 ops/sec (±0.17%) 1.03
S.object - parse 36343039 ops/sec (±1.57%) 35466302 ops/sec (±1.60%) 0.98
S.object - make + reverse 133490 ops/sec (±1.51%) 131621 ops/sec (±1.09%) 0.99
S.object - make + reverse convert 86184 ops/sec (±1.02%) 83663 ops/sec (±0.93%) 0.97
S.object - reverse convert 46295779 ops/sec (±1.90%) 47267567 ops/sec (±1.74%) 1.02
S.string - parse 68361099 ops/sec (±2.04%) 67102209 ops/sec (±2.23%) 0.98
S.string - reverse convert 67132161 ops/sec (±3.02%) 69673135 ops/sec (±2.34%) 1.04

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.