@ata-project/unplugin 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- package/package.json +1 -1
- package/src/compile-away.js +39 -2
- package/src/core.js +7 -0
package/README.md
CHANGED
|
@@ -179,7 +179,8 @@ away this way.
|
|
|
179
179
|
|
|
180
180
|
Where the code only ever calls `isValidObject()` or `isValidJSON()`, the plugin
|
|
181
181
|
uses a smaller wrapper without the error machinery (needs ata-validator 1.40.0):
|
|
182
|
-
a small app that only asks for a boolean bundles to 2.
|
|
182
|
+
a small app that only asks for a boolean bundles to 2.6 KB gzipped, against 12.1 KB with
|
|
183
|
+
the full wrapper and 102.0 KB for the runtime, on 0.5.0 with ata-validator 1.40.0.
|
|
183
184
|
|
|
184
185
|
The replacement answers `validate()`, `isValidObject()`, `validateJSON()` and
|
|
185
186
|
`isValidJSON()` as a `Validator` with default options does: the same verdicts,
|
|
@@ -194,7 +195,11 @@ otherwise:
|
|
|
194
195
|
- `Validator` is a named import from `ata-validator`;
|
|
195
196
|
- the schema argument is an object literal, a top-level `const` bound to one,
|
|
196
197
|
the default import of a relative `.json` file, or `defineSchema(...)` around
|
|
197
|
-
one of those;
|
|
198
|
+
one of those; calls to the `t` builder from `ata-validator/t` whose arguments are
|
|
199
|
+
such values are run at build time, since the builder returns plain JSON Schema,
|
|
200
|
+
and are marked pure so a schema only the replaced call used leaves the bundle
|
|
201
|
+
with the builder (`t.refine` and `t.recursive`, which take a function, stay on
|
|
202
|
+
the runtime);
|
|
198
203
|
- there is no second argument, or it is `{ useDefaults: false }` (or
|
|
199
204
|
`{ useDefaults: true }`), written as a literal or a top-level `const`; that
|
|
200
205
|
one option needs ata-validator 1.37.0, and older versions keep such calls on
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ata-project/unplugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Build-time JSON Schema for Vite, Webpack, Rollup, Rolldown, esbuild and Rspack. compileAway takes the runtime compiler out of the bundle.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
package/src/compile-away.js
CHANGED
|
@@ -29,6 +29,9 @@ import MagicString from 'magic-string'
|
|
|
29
29
|
|
|
30
30
|
const METHODS = new Set(['validate', 'isValidObject', 'validateJSON', 'isValidJSON'])
|
|
31
31
|
const NOT_STATIC = Symbol('not static')
|
|
32
|
+
// The builders of ata-validator/t that take only values. refine and
|
|
33
|
+
// recursive take a function and stay on the runtime.
|
|
34
|
+
const T_PURE = new Set(['string', 'number', 'integer', 'boolean', 'null', 'literal', 'const', 'enum', 'array', 'tuple', 'record', 'object', 'optional', 'union', 'intersect', 'ref', 'any', 'unknown', 'never', 'pick', 'omit', 'partial', 'required', 'composite'])
|
|
32
35
|
|
|
33
36
|
// Keys that hold child nodes. Types are left out on purpose: they are erased
|
|
34
37
|
// before anything runs, so a name used in a type annotation says nothing about
|
|
@@ -134,9 +137,30 @@ function staticValue(node, ctx, seen = new Set()) {
|
|
|
134
137
|
seen.delete(node.name)
|
|
135
138
|
return v
|
|
136
139
|
}
|
|
137
|
-
case 'CallExpression':
|
|
140
|
+
case 'CallExpression': {
|
|
138
141
|
if (node.callee.type === 'Identifier' && node.callee.name === ctx.defineSchema && node.arguments.length === 1) return staticValue(node.arguments[0], ctx, seen)
|
|
142
|
+
// `t.object(...)` and the rest of the builder from ata-validator/t. It
|
|
143
|
+
// returns plain JSON Schema and holds no state, so a call whose
|
|
144
|
+
// arguments the build can read gives here what it gives at run time.
|
|
145
|
+
// The builders that take a function are left out.
|
|
146
|
+
const c = node.callee
|
|
147
|
+
if (ctx.t && ctx.tName && c.type === 'MemberExpression' && !c.computed && c.object.type === 'Identifier' &&
|
|
148
|
+
c.object.name === ctx.tName && ctx.declared.get(ctx.tName) === 1 && c.property.type === 'Identifier' && T_PURE.has(c.property.name) &&
|
|
149
|
+
typeof ctx.t[c.property.name] === 'function') {
|
|
150
|
+
const args = []
|
|
151
|
+
for (const a of node.arguments) {
|
|
152
|
+
if (a.type === 'SpreadElement') return NOT_STATIC
|
|
153
|
+
const v = staticValue(a, ctx, seen)
|
|
154
|
+
if (v === NOT_STATIC) return NOT_STATIC
|
|
155
|
+
args.push(v)
|
|
156
|
+
}
|
|
157
|
+
let v
|
|
158
|
+
try { v = ctx.t[c.property.name](...args) } catch { return NOT_STATIC }
|
|
159
|
+
ctx.tCalls.add(node)
|
|
160
|
+
return v
|
|
161
|
+
}
|
|
139
162
|
return NOT_STATIC
|
|
163
|
+
}
|
|
140
164
|
}
|
|
141
165
|
return NOT_STATIC
|
|
142
166
|
}
|
|
@@ -244,6 +268,15 @@ export function compileAway(code, id, ata) {
|
|
|
244
268
|
}
|
|
245
269
|
}
|
|
246
270
|
if (!validatorName) return null
|
|
271
|
+
let tName = null
|
|
272
|
+
for (const stmt of ast.program.body) {
|
|
273
|
+
if (stmt.type !== 'ImportDeclaration' || stmt.source.value !== 'ata-validator/t' || stmt.importKind === 'type') continue
|
|
274
|
+
for (const sp of stmt.specifiers) {
|
|
275
|
+
if (sp.type !== 'ImportSpecifier' || sp.importKind === 'type') continue
|
|
276
|
+
const imported = sp.imported.type === 'Identifier' ? sp.imported.name : sp.imported.value
|
|
277
|
+
if (imported === 't') tName = sp.local.name
|
|
278
|
+
}
|
|
279
|
+
}
|
|
247
280
|
let withKeywords = null
|
|
248
281
|
for (const stmt of ast.program.body) {
|
|
249
282
|
if (stmt.type !== 'ImportDeclaration' || stmt.source.value !== '@ata-project/keywords' || stmt.importKind === 'type') continue
|
|
@@ -256,7 +289,7 @@ export function compileAway(code, id, ata) {
|
|
|
256
289
|
|
|
257
290
|
const { declared, refs } = scan(ast)
|
|
258
291
|
if (declared.get(validatorName) !== 1) return null
|
|
259
|
-
const ctx = { declared, refs, constants: constantsOf(ast, id), defineSchema, withKeywords, extendChecks: ata.compiledExtendChecks === true }
|
|
292
|
+
const ctx = { declared, refs, constants: constantsOf(ast, id), defineSchema, withKeywords, extendChecks: ata.compiledExtendChecks === true, t: ata.t || null, tName, tCalls: new Set() }
|
|
260
293
|
|
|
261
294
|
const s = new MagicString(code)
|
|
262
295
|
const modules = []
|
|
@@ -310,6 +343,10 @@ export function compileAway(code, id, ata) {
|
|
|
310
343
|
const clause = [def ? text(def) : null, named.length ? `{ ${named.map(text).join(', ')} }` : null].filter(Boolean).join(', ')
|
|
311
344
|
s.overwrite(importDecl.start, importDecl.end, `import ${clause} from ${code.slice(importDecl.source.start, importDecl.source.end)}`)
|
|
312
345
|
}
|
|
346
|
+
// The builder calls read here are pure, and marked so: a schema constant
|
|
347
|
+
// only the replaced call used, and the builder with it, can then leave the
|
|
348
|
+
// bundle.
|
|
349
|
+
for (const call of ctx.tCalls) s.appendLeft(call.start, '/*#__PURE__*/ ')
|
|
313
350
|
if (wrappers.verdict) s.prepend(`import { fromCompiledVerdict as __ataFromCompiledVerdict } from 'ata-validator/compiled-verdict';\n`)
|
|
314
351
|
if (wrappers.full) s.prepend(`import { fromCompiled as __ataFromCompiled } from 'ata-validator/compiled';\n`)
|
|
315
352
|
s.appendLeft(lastImportEnd, '\n' + modules.join(''))
|
package/src/core.js
CHANGED
|
@@ -74,6 +74,12 @@ async function loadAta() {
|
|
|
74
74
|
// withKeywords from @ata-project/keywords registers one; from 1.40.0. Asked
|
|
75
75
|
// of a wrapper itself, so an ata-validator without it keeps such calls on
|
|
76
76
|
// the runtime.
|
|
77
|
+
// The ata-validator/t builder, run at build time on calls whose arguments
|
|
78
|
+
// the build can read.
|
|
79
|
+
let t = null
|
|
80
|
+
if (canCompileAway) {
|
|
81
|
+
try { const m = await import('ata-validator/t'); t = (m.default ?? m).t ?? m.t ?? null } catch { t = null }
|
|
82
|
+
}
|
|
77
83
|
let compiledExtendChecks = false
|
|
78
84
|
if (canCompileAway) {
|
|
79
85
|
try {
|
|
@@ -92,6 +98,7 @@ async function loadAta() {
|
|
|
92
98
|
compiledOptions: canCompileAway && Array.isArray(build.compiledOptions) ? build.compiledOptions : [],
|
|
93
99
|
compiledVerdict,
|
|
94
100
|
compiledExtendChecks,
|
|
101
|
+
t,
|
|
95
102
|
}
|
|
96
103
|
}
|
|
97
104
|
|