@zod-to-form/vite 0.1.1

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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/dist/cache.d.ts +39 -0
  4. package/dist/cache.d.ts.map +1 -0
  5. package/dist/cache.js +56 -0
  6. package/dist/cache.js.map +1 -0
  7. package/dist/config/load.d.ts +59 -0
  8. package/dist/config/load.d.ts.map +1 -0
  9. package/dist/config/load.js +117 -0
  10. package/dist/config/load.js.map +1 -0
  11. package/dist/errors.d.ts +50 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +62 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/generate-mode/babel-traverse.d.ts +5 -0
  16. package/dist/generate-mode/babel-traverse.d.ts.map +1 -0
  17. package/dist/generate-mode/babel-traverse.js +16 -0
  18. package/dist/generate-mode/babel-traverse.js.map +1 -0
  19. package/dist/generate-mode/generate-source.d.ts +51 -0
  20. package/dist/generate-mode/generate-source.d.ts.map +1 -0
  21. package/dist/generate-mode/generate-source.js +187 -0
  22. package/dist/generate-mode/generate-source.js.map +1 -0
  23. package/dist/generate-mode/resolve-schema.d.ts +43 -0
  24. package/dist/generate-mode/resolve-schema.d.ts.map +1 -0
  25. package/dist/generate-mode/resolve-schema.js +182 -0
  26. package/dist/generate-mode/resolve-schema.js.map +1 -0
  27. package/dist/generate-mode/scan-jsx.d.ts +86 -0
  28. package/dist/generate-mode/scan-jsx.d.ts.map +1 -0
  29. package/dist/generate-mode/scan-jsx.js +161 -0
  30. package/dist/generate-mode/scan-jsx.js.map +1 -0
  31. package/dist/hmr.d.ts +44 -0
  32. package/dist/hmr.d.ts.map +1 -0
  33. package/dist/hmr.js +28 -0
  34. package/dist/hmr.js.map +1 -0
  35. package/dist/index.d.ts +61 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +59 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/logger.d.ts +27 -0
  40. package/dist/logger.d.ts.map +1 -0
  41. package/dist/logger.js +46 -0
  42. package/dist/logger.js.map +1 -0
  43. package/dist/plugin.d.ts +61 -0
  44. package/dist/plugin.d.ts.map +1 -0
  45. package/dist/plugin.js +650 -0
  46. package/dist/plugin.js.map +1 -0
  47. package/dist/query-mode/parse-specifier.d.ts +23 -0
  48. package/dist/query-mode/parse-specifier.d.ts.map +1 -0
  49. package/dist/query-mode/parse-specifier.js +83 -0
  50. package/dist/query-mode/parse-specifier.js.map +1 -0
  51. package/dist/query-mode/resolve-id.d.ts +12 -0
  52. package/dist/query-mode/resolve-id.d.ts.map +1 -0
  53. package/dist/query-mode/resolve-id.js +61 -0
  54. package/dist/query-mode/resolve-id.js.map +1 -0
  55. package/dist/query-mode/transform.d.ts +33 -0
  56. package/dist/query-mode/transform.d.ts.map +1 -0
  57. package/dist/query-mode/transform.js +90 -0
  58. package/dist/query-mode/transform.js.map +1 -0
  59. package/dist/resolver-strip.d.ts +58 -0
  60. package/dist/resolver-strip.d.ts.map +1 -0
  61. package/dist/resolver-strip.js +141 -0
  62. package/dist/resolver-strip.js.map +1 -0
  63. package/dist/tsconfig.tsbuildinfo +1 -0
  64. package/dist/types.d.ts +242 -0
  65. package/dist/types.d.ts.map +1 -0
  66. package/dist/types.js +2 -0
  67. package/dist/types.js.map +1 -0
  68. package/dist/write-guard.d.ts +26 -0
  69. package/dist/write-guard.d.ts.map +1 -0
  70. package/dist/write-guard.js +32 -0
  71. package/dist/write-guard.js.map +1 -0
  72. package/package.json +69 -0
@@ -0,0 +1,187 @@
1
+ import { parse as parseBabel } from '@babel/parser';
2
+ import MagicString from 'magic-string';
3
+ export function generateSource(input) {
4
+ const { source, resolved, onWarn } = input;
5
+ if (resolved.length === 0) {
6
+ // Nothing to do — but still hand back a valid magic-string sourcemap
7
+ // so downstream Vite plumbing has something to chain against.
8
+ const ms = new MagicString(source);
9
+ return {
10
+ code: source,
11
+ map: ms.generateMap({ hires: true }),
12
+ rewritten: 0
13
+ };
14
+ }
15
+ const ms = new MagicString(source);
16
+ // Process sites in source order. magic-string supports overlapping
17
+ // edits as long as we use append/prepend instead of overwrite for
18
+ // adjacent ranges, but our per-site edits never overlap because
19
+ // they're confined to the opening/closing tag of distinct elements.
20
+ for (const site of resolved) {
21
+ const { candidate, generatedIdentifier } = site;
22
+ const openingSlice = source.slice(candidate.openingRange.start, candidate.openingRange.end);
23
+ // Build the new opening tag: replace `ZodForm` and remove the schema attr.
24
+ const newOpening = buildNewOpening(openingSlice, generatedIdentifier, candidate);
25
+ ms.overwrite(candidate.openingRange.start, candidate.openingRange.end, newOpening);
26
+ // Closing tag — `</ZodForm>` becomes `</_z2fGeneratedForm_N>`.
27
+ if (candidate.closingRange !== null) {
28
+ const closingSlice = source.slice(candidate.closingRange.start, candidate.closingRange.end);
29
+ const newClosing = closingSlice.replace(/ZodForm/, generatedIdentifier);
30
+ ms.overwrite(candidate.closingRange.start, candidate.closingRange.end, newClosing);
31
+ }
32
+ }
33
+ // Insert the generated imports AFTER any leading shebang / block
34
+ // comments / string directives (`'use client'`, `'use strict'`) and
35
+ // AFTER the last existing top-level `import` statement — not blindly
36
+ // at byte 0. Prepending at byte 0 would demote a `'use client'`
37
+ // directive past the first import, invalidating it, and would push
38
+ // header comments below the generated block.
39
+ //
40
+ // Every generate-mode variant emits its component under the fixed
41
+ // export name `Form`; see `isGenerateVariant` in query-mode/transform.ts.
42
+ const importLines = [];
43
+ for (let i = 0; i < resolved.length; i++) {
44
+ const site = resolved[i];
45
+ const variant = `__generate_${i + 1}`;
46
+ importLines.push(`import { Form as ${site.generatedIdentifier} } from '${site.schemaFile}?z2f=${variant}';`);
47
+ }
48
+ const insertAt = findImportInsertionPoint(source, onWarn);
49
+ // When the scanner can't find a trailing newline after the preamble
50
+ // (e.g. a preamble-only file, or a shebang file with no final `\n`),
51
+ // prepend one to the inserted text so `#!/usr/bin/env node` + generated
52
+ // import can't collapse to `#!/usr/bin/env nodeimport { … }` on the
53
+ // same line. No-op in the common case where `insertAt` already points
54
+ // at the start of a line.
55
+ const needsLeadingNewline = insertAt > 0 &&
56
+ insertAt < source.length &&
57
+ source[insertAt - 1] !== '\n' &&
58
+ source[insertAt - 1] !== '\r';
59
+ const prefix = needsLeadingNewline ? '\n' : '';
60
+ ms.appendLeft(insertAt, prefix + importLines.join('\n') + '\n');
61
+ return {
62
+ code: ms.toString(),
63
+ map: ms.generateMap({ hires: true }),
64
+ rewritten: resolved.length
65
+ };
66
+ }
67
+ /**
68
+ * Find the byte offset at which to insert generated imports. The target
69
+ * is "immediately after the last thing that must come first": the file's
70
+ * shebang, its leading string directives (`'use client'`, `'use strict'`),
71
+ * and any existing top-level `import` statements. If none of those exist,
72
+ * the result is byte 0 (the file starts with user code and the generated
73
+ * imports go at the very top).
74
+ *
75
+ * Uses Babel's parser — the same dependency scan-jsx and resolve-schema
76
+ * already rely on — so directive detection, multi-line imports,
77
+ * TypeScript-specific forms (`import type`), side-effect-only imports,
78
+ * BOM handling, and escape sequences inside string literals are all
79
+ * handled by the production-grade parser instead of a hand-rolled
80
+ * textual walker.
81
+ *
82
+ * On parse failure (e.g. the user is mid-save with broken syntax) we
83
+ * warn via `onWarn` and return 0. This is defense-in-depth: `scanJsx`'s
84
+ * upstream parse normally filters broken sources before this code runs,
85
+ * but a future Babel plugin-flag drift between the two parsers could
86
+ * make them disagree, and silent corruption is worse than a warn line.
87
+ *
88
+ * `onWarn` MUST NOT throw — exceptions in the callback would kill the
89
+ * transform and turn a recoverable warning into a hard build failure.
90
+ * Any throw is caught and ignored below.
91
+ */
92
+ // Exported for direct unit testing. Not part of the plugin's public API —
93
+ // callers outside this file should go through `generateSource`.
94
+ export function findImportInsertionPoint(source, onWarn) {
95
+ const safeWarn = (message) => {
96
+ if (onWarn === undefined)
97
+ return;
98
+ try {
99
+ onWarn(message);
100
+ }
101
+ catch {
102
+ // A throwing logger must not mask the fallback return path.
103
+ }
104
+ };
105
+ let ast;
106
+ try {
107
+ ast = parseBabel(source, {
108
+ sourceType: 'module',
109
+ plugins: ['jsx', 'typescript'],
110
+ errorRecovery: false
111
+ });
112
+ }
113
+ catch (err) {
114
+ const msg = err instanceof Error ? err.message : String(err);
115
+ safeWarn(`generate-mode: re-parse failed inside findImportInsertionPoint (${msg}); ` +
116
+ 'inserting at byte 0 as a safety fallback');
117
+ return 0;
118
+ }
119
+ // Seed from the furthest end across every preamble-flavored node:
120
+ // - `program.interpreter` holds the shebang (`#!...`). Babel models it
121
+ // outside `body`, so a shebang would otherwise slip past the walk.
122
+ // - `program.directives` holds every leading string-literal directive.
123
+ // Babel lifts them out of `body` under `sourceType: 'module'`.
124
+ let lastPreambleEnd = Math.max(0, ast.program.interpreter?.end ?? 0, ...ast.program.directives.map((d) => d.end ?? 0));
125
+ // Walk top-level statements. Imports always extend the preamble. For
126
+ // defense-in-depth against Babel versions (< 7.21) that may leave a
127
+ // hashbang-following directive as a body `ExpressionStatement` instead
128
+ // of lifting it to `program.directives`, also treat a leading
129
+ // `ExpressionStatement` whose expression is a `StringLiteral` as
130
+ // preamble and keep walking.
131
+ for (const stmt of ast.program.body) {
132
+ if (stmt.type === 'ImportDeclaration' && stmt.end != null) {
133
+ lastPreambleEnd = stmt.end;
134
+ continue;
135
+ }
136
+ if (stmt.type === 'ExpressionStatement') {
137
+ const expr = stmt.expression;
138
+ if (expr.type === 'StringLiteral' && stmt.end != null) {
139
+ lastPreambleEnd = Math.max(lastPreambleEnd, stmt.end);
140
+ continue;
141
+ }
142
+ }
143
+ // Anything else stops the preamble.
144
+ break;
145
+ }
146
+ // Babel ranges don't include a trailing newline. Advance past any
147
+ // horizontal whitespace followed by a single line terminator (any of
148
+ // `\n`, `\r\n`, or bare `\r`) so the inserted imports land on their
149
+ // own line rather than appended to the last preamble statement.
150
+ const match = /^[ \t]*(?:\r\n|\n|\r)/.exec(source.slice(lastPreambleEnd));
151
+ if (match !== null) {
152
+ lastPreambleEnd += match[0].length;
153
+ }
154
+ return lastPreambleEnd;
155
+ }
156
+ /**
157
+ * Build the replacement opening tag from the original source slice.
158
+ * Strategy: walk attributes from end to start so removing the schema
159
+ * attribute doesn't shift earlier offsets. We work with the slice
160
+ * (origin-relative offsets) to keep the math local.
161
+ */
162
+ function buildNewOpening(openingSlice, generatedIdentifier, candidate) {
163
+ // Convert absolute attribute ranges to slice-local offsets.
164
+ const sliceStart = candidate.openingRange.start;
165
+ let result = openingSlice;
166
+ // Process attributes in REVERSE order so each removal/replacement
167
+ // doesn't invalidate earlier offsets.
168
+ const sortedAttrs = [...candidate.attributes].sort((a, b) => b.range.start - a.range.start);
169
+ for (const attr of sortedAttrs) {
170
+ if (attr.kind !== 'named' || attr.name !== 'schema')
171
+ continue;
172
+ const start = attr.range.start - sliceStart;
173
+ const end = attr.range.end - sliceStart;
174
+ // Trim a leading whitespace character if present so we don't leave
175
+ // a double space between adjacent props.
176
+ const before = result.slice(0, start);
177
+ const after = result.slice(end);
178
+ const trimmedBefore = before.endsWith(' ') ? before.slice(0, -1) : before;
179
+ result = trimmedBefore + after;
180
+ }
181
+ // Replace the element name (the FIRST occurrence of `ZodForm`, which
182
+ // is the tag name). Subsequent occurrences inside attributes — vanishingly
183
+ // rare but possible — are left alone.
184
+ result = result.replace(/ZodForm/, generatedIdentifier);
185
+ return result;
186
+ }
187
+ //# sourceMappingURL=generate-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-source.js","sourceRoot":"","sources":["../../src/generate-mode/generate-source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { CandidateSite } from './scan-jsx.js';
2
+ export interface ImportBinding {
3
+ /** The raw import specifier (e.g. `'./schemas/signup'` or `'@acme/lib'`). */
4
+ source: string;
5
+ /** Local identifier name (after any `as` alias). */
6
+ localName: string;
7
+ /** Imported name from the source module (`signupSchema`, `default`). */
8
+ importedName: string;
9
+ }
10
+ export interface ResolvedSite {
11
+ /** The candidate site this resolution applies to. */
12
+ candidate: CandidateSite;
13
+ /** Absolute path to the schema file (post-resolveImport). */
14
+ schemaFile: string;
15
+ /** Imported name of the schema from the source module. */
16
+ schemaExportName: string;
17
+ /** The local identifier that will replace `ZodForm` at this site ( (`_z2fGeneratedForm_<n>`). */
18
+ generatedIdentifier: string;
19
+ }
20
+ export type SkipReason = string;
21
+ export interface ResolveSchemaInput {
22
+ source: string;
23
+ candidates: CandidateSite[];
24
+ /** Absolute path to the file containing the candidates (importer). */
25
+ sourceFile: string;
26
+ /**
27
+ * Resolves an import specifier (e.g. `'./schemas/signup'`) against the
28
+ * importing source file and returns an absolute path, or null when the
29
+ * resolver can't find it. Wraps Vite's `this.resolve` in the caller.
30
+ */
31
+ resolveImport: (specifier: string, importer: string) => Promise<string | null>;
32
+ /** Vite root — schema files outside this dir are skipped. */
33
+ viteRoot: string;
34
+ }
35
+ export interface ResolveSchemaOutput {
36
+ resolved: ResolvedSite[];
37
+ skipped: Array<{
38
+ candidate: CandidateSite;
39
+ reason: SkipReason;
40
+ }>;
41
+ }
42
+ export declare function resolveSchemas(input: ResolveSchemaInput): Promise<ResolveSchemaOutput>;
43
+ //# sourceMappingURL=resolve-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-schema.d.ts","sourceRoot":"","sources":["../../src/generate-mode/resolve-schema.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAInD,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,SAAS,EAAE,aAAa,CAAC;IACzB,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,gBAAgB,EAAE,MAAM,CAAC;IACzB,iGAAiG;IACjG,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC;AAEhC,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,OAAO,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,aAAa,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;CAClE;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAgK5F"}
@@ -0,0 +1,182 @@
1
+ /**
2
+ * resolveSchema — given a `CandidateSite` and the source file's path,
3
+ * walk the AST scope to validate that:
4
+ *
5
+ * 1. The `ZodForm` identifier resolves to a named import from the literal
6
+ * specifier `'@zod-to-form/react'` (no aliased re-exports).
7
+ * 2. The `schema` identifier resolves to a named import whose source
8
+ * module path is inside the Vite root.
9
+ *
10
+ * Returns a fully-resolved `GenerateSite` on success, or a `SkipReason`
11
+ * string on failure. The caller buffers the skip reason through the
12
+ * logger.
13
+ *
14
+ * Pure: takes the parsed AST + source + candidate, returns a result.
15
+ * No I/O. The path-resolution portion (turning a string specifier into
16
+ * an absolute file path) is delegated to a `resolveImport` callback that
17
+ * the plugin's `transform` hook supplies — it wraps Vite's `this.resolve`.
18
+ */
19
+ import { parse } from '@babel/parser';
20
+ import { traverse } from './babel-traverse.js';
21
+ const ZOD_FORM_PACKAGE = '@zod-to-form/react';
22
+ export async function resolveSchemas(input) {
23
+ const { source, candidates, sourceFile, resolveImport, viteRoot } = input;
24
+ if (candidates.length === 0) {
25
+ return { resolved: [], skipped: [] };
26
+ }
27
+ // Re-parse the source to pick up the program-level import declarations.
28
+ // We could pass the AST through from scanJsx, but keeping resolveSchemas
29
+ // self-contained makes it easier to unit-test in isolation. The parse
30
+ // cost is bounded by the file size, not by the number of candidates.
31
+ let ast;
32
+ try {
33
+ ast = parse(source, {
34
+ sourceType: 'module',
35
+ plugins: ['jsx', 'typescript'],
36
+ errorRecovery: false
37
+ });
38
+ }
39
+ catch (err) {
40
+ const message = err instanceof Error ? err.message : String(err);
41
+ return {
42
+ resolved: [],
43
+ skipped: candidates.map((c) => ({
44
+ candidate: c,
45
+ reason: `source file failed to re-parse: ${message}`
46
+ }))
47
+ };
48
+ }
49
+ // Build a map of local identifier name → import binding for every
50
+ // top-level import. We only care about top-level imports because
51
+ // <ZodForm> can't validly use a function-scoped import.
52
+ const bindings = new Map();
53
+ traverse(ast, {
54
+ Program(path) {
55
+ for (const node of path.node.body) {
56
+ if (node.type !== 'ImportDeclaration')
57
+ continue;
58
+ const decl = node;
59
+ const sourceLiteral = decl.source.value;
60
+ for (const specifier of decl.specifiers) {
61
+ if (specifier.type === 'ImportSpecifier') {
62
+ const s = specifier;
63
+ const importedName = s.imported.type === 'Identifier' ? s.imported.name : s.imported.value;
64
+ bindings.set(s.local.name, {
65
+ source: sourceLiteral,
66
+ localName: s.local.name,
67
+ importedName
68
+ });
69
+ }
70
+ else if (specifier.type === 'ImportDefaultSpecifier') {
71
+ const s = specifier;
72
+ bindings.set(s.local.name, {
73
+ source: sourceLiteral,
74
+ localName: s.local.name,
75
+ importedName: 'default'
76
+ });
77
+ }
78
+ else if (specifier.type === 'ImportNamespaceSpecifier') {
79
+ const s = specifier;
80
+ bindings.set(s.local.name, {
81
+ source: sourceLiteral,
82
+ localName: s.local.name,
83
+ importedName: '*'
84
+ });
85
+ }
86
+ }
87
+ }
88
+ path.stop();
89
+ }
90
+ });
91
+ const resolved = [];
92
+ const skipped = [];
93
+ let counter = 0;
94
+ for (const candidate of candidates) {
95
+ // 1. ZodForm must come from @zod-to-form/react
96
+ const zodFormBinding = bindings.get('ZodForm');
97
+ if (zodFormBinding === undefined) {
98
+ skipped.push({
99
+ candidate,
100
+ reason: `<ZodForm> at ${candidate.loc.line}:${candidate.loc.column} has no in-scope import; generate mode requires a top-level 'import { ZodForm }' statement`
101
+ });
102
+ continue;
103
+ }
104
+ if (zodFormBinding.source !== ZOD_FORM_PACKAGE) {
105
+ skipped.push({
106
+ candidate,
107
+ reason: `ZodForm import origin is '${zodFormBinding.source}', not '${ZOD_FORM_PACKAGE}'`
108
+ });
109
+ continue;
110
+ }
111
+ if (zodFormBinding.importedName !== 'ZodForm') {
112
+ skipped.push({
113
+ candidate,
114
+ reason: `ZodForm import is aliased ('${zodFormBinding.importedName}' as '${zodFormBinding.localName}'); only the unaliased named import is matched`
115
+ });
116
+ continue;
117
+ }
118
+ // 2. The schema identifier must resolve to a top-level import.
119
+ // CandidateSite.schemaIdentifier is non-null by scan-jsx's contract.
120
+ const schemaIdName = candidate.schemaIdentifier;
121
+ const schemaBinding = bindings.get(schemaIdName);
122
+ if (schemaBinding === undefined) {
123
+ skipped.push({
124
+ candidate,
125
+ reason: `schema identifier '${schemaIdName}' is not a top-level import (generate mode only handles imported schemas)`
126
+ });
127
+ continue;
128
+ }
129
+ if (schemaBinding.importedName === '*' || schemaBinding.importedName === 'default') {
130
+ skipped.push({
131
+ candidate,
132
+ reason: `schema identifier '${schemaIdName}' is a ${schemaBinding.importedName === '*' ? 'namespace' : 'default'} import; only named imports are handled`
133
+ });
134
+ continue;
135
+ }
136
+ // 3. The schema source must resolve to an absolute path inside the
137
+ // Vite root. Wrap the resolver call in try/catch — Vite's
138
+ // `this.resolve` can throw (rather than return null) if a downstream
139
+ // resolveId hook errors during the lookup. Treat that as a skip with
140
+ // the underlying error attached, not an uncaught reject.
141
+ let absoluteSchemaPath;
142
+ try {
143
+ absoluteSchemaPath = await resolveImport(schemaBinding.source, sourceFile);
144
+ }
145
+ catch (err) {
146
+ skipped.push({
147
+ candidate,
148
+ reason: `schema import '${schemaBinding.source}' threw during resolution: ${err instanceof Error ? err.message : String(err)}`
149
+ });
150
+ continue;
151
+ }
152
+ if (absoluteSchemaPath === null) {
153
+ skipped.push({
154
+ candidate,
155
+ reason: `schema import '${schemaBinding.source}' could not be resolved by Vite`
156
+ });
157
+ continue;
158
+ }
159
+ if (!isInsideRoot(absoluteSchemaPath, viteRoot)) {
160
+ skipped.push({
161
+ candidate,
162
+ reason: `schema identifier '${schemaIdName}' resolves to '${absoluteSchemaPath}', which is outside the Vite root`
163
+ });
164
+ continue;
165
+ }
166
+ counter += 1;
167
+ resolved.push({
168
+ candidate,
169
+ schemaFile: absoluteSchemaPath,
170
+ schemaExportName: schemaBinding.importedName,
171
+ generatedIdentifier: `_z2fGeneratedForm_${counter}`
172
+ });
173
+ }
174
+ return { resolved, skipped };
175
+ }
176
+ function isInsideRoot(child, root) {
177
+ const c = child.replace(/\\/g, '/');
178
+ const r = root.replace(/\\/g, '/');
179
+ const normalizedRoot = r.endsWith('/') ? r : r + '/';
180
+ return c === r || c.startsWith(normalizedRoot);
181
+ }
182
+ //# sourceMappingURL=resolve-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-schema.js","sourceRoot":"","sources":["../../src/generate-mode/resolve-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * One JSX attribute as it appears on a candidate `<ZodForm>` element.
3
+ *
4
+ * Discriminated on `kind`: a `'spread'` attribute (`{...rest}`) has no
5
+ * name; a `'named'` attribute has one. Encoding the distinction in the
6
+ * type prevents the "name is null when isSpread is true" coupling from
7
+ * silently drifting.
8
+ */
9
+ export type CandidateAttribute = {
10
+ kind: 'named';
11
+ /** Attribute identifier (e.g. `'schema'`, `'onSubmit'`). */
12
+ name: string;
13
+ /** Byte range of the entire attribute, inclusive of name + value. */
14
+ range: {
15
+ start: number;
16
+ end: number;
17
+ };
18
+ /** Raw source slice for this attribute (used to preserve formatting). */
19
+ source: string;
20
+ } | {
21
+ kind: 'spread';
22
+ range: {
23
+ start: number;
24
+ end: number;
25
+ };
26
+ source: string;
27
+ };
28
+ export interface CandidateSite {
29
+ /**
30
+ * Byte range of the *opening tag* (e.g. `<ZodForm schema={X} ... >` or
31
+ * `<ZodForm ... />` for self-closing). The closing tag (if any) is
32
+ * tracked separately.
33
+ */
34
+ openingRange: {
35
+ start: number;
36
+ end: number;
37
+ };
38
+ /** Byte range of the closing tag, or null for self-closing elements. */
39
+ closingRange: {
40
+ start: number;
41
+ end: number;
42
+ } | null;
43
+ /** Source location of the opening tag, for diagnostics (1-indexed line). */
44
+ loc: {
45
+ line: number;
46
+ column: number;
47
+ };
48
+ /** True iff the element is `<ZodForm ... />`. */
49
+ selfClosing: boolean;
50
+ /** All attributes in source order, including the `schema` attribute. */
51
+ attributes: CandidateAttribute[];
52
+ /** The identifier name from `schema={identifier}`. */
53
+ schemaIdentifier: string;
54
+ /** Children source slice (between opening and closing tags), or '' if self-closing. */
55
+ childrenSource: string;
56
+ }
57
+ export interface ScanResult {
58
+ /** Candidate sites that may be transformable. resolveSchema validates them. */
59
+ candidates: CandidateSite[];
60
+ /** Sites that matched `<ZodForm>` but failed an early structural check. */
61
+ skipped: SkippedSite[];
62
+ }
63
+ export interface SkippedSite {
64
+ loc: {
65
+ line: number;
66
+ column: number;
67
+ };
68
+ reason: string;
69
+ }
70
+ /**
71
+ * Scan a source string for `<ZodForm>` JSX elements. Returns candidates
72
+ * for further validation by `resolveSchema` plus an array of sites that
73
+ * structurally don't qualify (and thus need a DEBUG diagnostic).
74
+ *
75
+ * Returns `null` (a discriminator distinct from "scanned and found
76
+ * nothing") when the substring fast-path filtered the file out — the
77
+ * caller can short-circuit before allocating anything else.
78
+ *
79
+ * On a Babel parse failure, returns a `ScanResult` with zero candidates
80
+ * and a single skip diagnostic naming the parser error so it surfaces
81
+ * in the buildEnd summary. We deliberately don't propagate the parse
82
+ * error — Vite's main pipeline will report the user's syntax problem
83
+ * elsewhere with better context.
84
+ */
85
+ export declare function scanJsx(source: string): ScanResult | null;
86
+ //# sourceMappingURL=scan-jsx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-jsx.d.ts","sourceRoot":"","sources":["../../src/generate-mode/scan-jsx.ts"],"names":[],"mappings":"AAyBA;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IACE,IAAI,EAAE,OAAO,CAAC;IACd,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEN,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,wEAAwE;IACxE,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD,4EAA4E;IAC5E,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,iDAAiD;IACjD,WAAW,EAAE,OAAO,CAAC;IACrB,wEAAwE;IACxE,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,sDAAsD;IACtD,gBAAgB,EAAE,MAAM,CAAC;IACzB,uFAAuF;IACvF,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,+EAA+E;IAC/E,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,2EAA2E;IAC3E,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAgHzD"}