@prisma/orm-mongo 8.0.0-rc.18-dev.47 → 8.0.0-rc.19
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/dist/{mongo-static-C2JEnq37-on92QlFC.mjs → mongo-static-DNXbLhsJ-C9Jn5l2_.mjs} +3 -3
- package/dist/mongo-static-DNXbLhsJ-C9Jn5l2_.mjs.map +1 -0
- package/dist/runtime.mjs +1 -1
- package/dist/runtime.mjs.map +1 -1
- package/dist/static.mjs +1 -1
- package/package.json +8 -8
- package/skills/prisma-8/SKILL.md +1 -1
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/instructions.md +1826 -0
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/scripts/client-takes-contract-value/contract-from-json.ts +382 -0
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/scripts/data-type-values/data-type-values.ts +1117 -0
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/scripts/default-generators-to-on-create/rewrite-default-generators.mjs +86 -0
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/scripts/mongo-field-storage-names/mongo-field-storage-names.ts +250 -0
- package/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/scripts/remove-nocheck/remove-nocheck.ts +813 -0
- package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/instructions.md +2000 -0
- package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/scripts/client-takes-contract-value/contract-from-json.ts +382 -0
- package/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/scripts/remove-nocheck/remove-nocheck.ts +813 -0
- package/dist/mongo-static-C2JEnq37-on92QlFC.mjs.map +0 -1
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
// Moves every Prisma 8 client call that passes `contractJson` to a contract value:
|
|
2
|
+
// postgres<Contract>({ contractJson, url })
|
|
3
|
+
// becomes
|
|
4
|
+
// export const contract = contractFromJson<Contract>(contractJson);
|
|
5
|
+
// postgres({ contract, url })
|
|
6
|
+
//
|
|
7
|
+
// Usage: node contract-from-json.ts [project root] [--typescript <path to the typescript package>]
|
|
8
|
+
//
|
|
9
|
+
// The script reads source files with the TypeScript compiler, which it loads from the project.
|
|
10
|
+
// It rewrites each source file it can move, and prints it. In a module with a default export, such
|
|
11
|
+
// as a Worker entry, it declares `contract` without `export` and says so. It prints to stderr, with the reason,
|
|
12
|
+
// each file that passes `contractJson` to a client but that it did not move: a test file, a file
|
|
13
|
+
// that already has a binding named `contract`, a file whose clients use different contracts, or
|
|
14
|
+
// a call it cannot read. It exits 1 when it printed such a file, and changes nothing and exits 1
|
|
15
|
+
// when TypeScript is not installed.
|
|
16
|
+
|
|
17
|
+
import { readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { createRequire } from 'node:module';
|
|
19
|
+
import { join, relative, resolve } from 'node:path';
|
|
20
|
+
import type * as TS from 'typescript';
|
|
21
|
+
|
|
22
|
+
const SOURCE_FILE = /\.(?:ts|tsx|mts|cts)$/;
|
|
23
|
+
const TEST_FILE = /\.(?:test|spec)(?:-d)?\.[cm]?tsx?$/;
|
|
24
|
+
const TEST_DIRECTORIES = new Set(['test', 'tests', '__tests__']);
|
|
25
|
+
const SKIPPED_DIRECTORIES = new Set(['node_modules', 'dist', 'build', '.git', '.next', '.turbo']);
|
|
26
|
+
const FACADE_ENTRY =
|
|
27
|
+
/^@prisma\/orm-(postgres|sqlite|mongo)\/(?:runtime|serverless|static|query-builder)$/;
|
|
28
|
+
const SUPABASE_ENTRY = '@prisma/orm-extension-supabase/runtime';
|
|
29
|
+
const FACTORY_EXPORTS = new Set(['default', 'supabase', 'mongoQuery']);
|
|
30
|
+
const DETECTION =
|
|
31
|
+
/(?<![\w$.])(?:postgres|postgresServerless|sqlite|supabase|mongo|postgresStatic|sqliteStatic|mongoStatic|mongoQuery)(?:<[^>()]*(?:<[^>()]*>[^>()]*)*>)?\(\s*\{(?:(?:[^{}]|\{[^{}]*\})*?,)?\s*contractJson\s*[,}:]/;
|
|
32
|
+
|
|
33
|
+
interface Edit {
|
|
34
|
+
readonly start: number;
|
|
35
|
+
readonly end: number;
|
|
36
|
+
readonly text: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface MovedCall {
|
|
40
|
+
readonly edits: readonly Edit[];
|
|
41
|
+
readonly typeArguments: string;
|
|
42
|
+
readonly json: string;
|
|
43
|
+
readonly jsonNames: readonly string[];
|
|
44
|
+
readonly staticEntry: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type Outcome =
|
|
48
|
+
| { readonly kind: 'unchanged' }
|
|
49
|
+
| { readonly kind: 'rewritten'; readonly source: string; readonly exported: boolean }
|
|
50
|
+
| { readonly kind: 'refused'; readonly reason: string };
|
|
51
|
+
|
|
52
|
+
function staticEntryOf(specifier: string): string | undefined {
|
|
53
|
+
const facade = FACADE_ENTRY.exec(specifier);
|
|
54
|
+
if (facade !== null) return `@prisma/orm-${facade[1]}/static`;
|
|
55
|
+
return specifier === SUPABASE_ENTRY ? '@prisma/orm-postgres/static' : undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function specifierOf(ts: typeof TS, statement: TS.ImportDeclaration): string {
|
|
59
|
+
return ts.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : '';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function compareSpecifiers(left: string, right: string): number {
|
|
63
|
+
const rank = (specifier: string) =>
|
|
64
|
+
specifier.startsWith('node:') ? 0 : specifier.startsWith('.') ? 2 : 1;
|
|
65
|
+
return rank(left) - rank(right) || (left < right ? -1 : left > right ? 1 : 0);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function factoriesOf(ts: typeof TS, imports: readonly TS.ImportDeclaration[]) {
|
|
69
|
+
const factories = new Map<string, string>();
|
|
70
|
+
for (const statement of imports) {
|
|
71
|
+
const clause = statement.importClause;
|
|
72
|
+
const staticEntry = staticEntryOf(specifierOf(ts, statement));
|
|
73
|
+
if (clause === undefined || clause.isTypeOnly || staticEntry === undefined) continue;
|
|
74
|
+
if (clause.name !== undefined) factories.set(clause.name.text, staticEntry);
|
|
75
|
+
const bindings = clause.namedBindings;
|
|
76
|
+
if (bindings === undefined || !ts.isNamedImports(bindings)) continue;
|
|
77
|
+
for (const element of bindings.elements) {
|
|
78
|
+
const imported = (element.propertyName ?? element.name).text;
|
|
79
|
+
if (!element.isTypeOnly && FACTORY_EXPORTS.has(imported)) {
|
|
80
|
+
factories.set(element.name.text, staticEntry);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return factories;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function topLevelNames(ts: typeof TS, sourceFile: TS.SourceFile) {
|
|
88
|
+
const imported = new Set<string>();
|
|
89
|
+
const declared = new Set<string>();
|
|
90
|
+
for (const statement of sourceFile.statements) {
|
|
91
|
+
if (ts.isImportDeclaration(statement)) {
|
|
92
|
+
const clause = statement.importClause;
|
|
93
|
+
if (clause?.name !== undefined) imported.add(clause.name.text);
|
|
94
|
+
const bindings = clause?.namedBindings;
|
|
95
|
+
if (bindings !== undefined && ts.isNamespaceImport(bindings))
|
|
96
|
+
imported.add(bindings.name.text);
|
|
97
|
+
else for (const element of bindings?.elements ?? []) imported.add(element.name.text);
|
|
98
|
+
} else if (ts.isVariableStatement(statement)) {
|
|
99
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
100
|
+
if (ts.isIdentifier(declaration.name)) declared.add(declaration.name.text);
|
|
101
|
+
}
|
|
102
|
+
} else if (
|
|
103
|
+
(ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) &&
|
|
104
|
+
statement.name !== undefined
|
|
105
|
+
) {
|
|
106
|
+
declared.add(statement.name.text);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return { imported, declared };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function identifiersIn(ts: typeof TS, node: TS.Node): string[] {
|
|
113
|
+
const names: string[] = [];
|
|
114
|
+
const visit = (child: TS.Node): void => {
|
|
115
|
+
if (ts.isIdentifier(child)) names.push(child.text);
|
|
116
|
+
ts.forEachChild(child, visit);
|
|
117
|
+
};
|
|
118
|
+
visit(node);
|
|
119
|
+
return names;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function contractJsonProperty(ts: typeof TS, object: TS.ObjectLiteralExpression) {
|
|
123
|
+
return object.properties.find(
|
|
124
|
+
(property): property is TS.ShorthandPropertyAssignment | TS.PropertyAssignment =>
|
|
125
|
+
(ts.isShorthandPropertyAssignment(property) || ts.isPropertyAssignment(property)) &&
|
|
126
|
+
(ts.isIdentifier(property.name) || ts.isStringLiteral(property.name)) &&
|
|
127
|
+
property.name.text === 'contractJson',
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function movedCalls(
|
|
132
|
+
ts: typeof TS,
|
|
133
|
+
sourceFile: TS.SourceFile,
|
|
134
|
+
factories: ReadonlyMap<string, string>,
|
|
135
|
+
): MovedCall[] {
|
|
136
|
+
const source = sourceFile.text;
|
|
137
|
+
const calls: MovedCall[] = [];
|
|
138
|
+
const visit = (node: TS.Node): void => {
|
|
139
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
|
|
140
|
+
const staticEntry = factories.get(node.expression.text);
|
|
141
|
+
const [options] = node.arguments;
|
|
142
|
+
const property =
|
|
143
|
+
options !== undefined && ts.isObjectLiteralExpression(options)
|
|
144
|
+
? contractJsonProperty(ts, options)
|
|
145
|
+
: undefined;
|
|
146
|
+
if (staticEntry !== undefined && property !== undefined) {
|
|
147
|
+
const edits: Edit[] = [
|
|
148
|
+
{ start: property.getStart(sourceFile), end: property.end, text: 'contract' },
|
|
149
|
+
];
|
|
150
|
+
const typeArguments = node.typeArguments;
|
|
151
|
+
if (typeArguments !== undefined) {
|
|
152
|
+
edits.push({
|
|
153
|
+
start: node.expression.end,
|
|
154
|
+
end: source.indexOf('>', typeArguments.end) + 1,
|
|
155
|
+
text: '',
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
calls.push({
|
|
159
|
+
edits,
|
|
160
|
+
typeArguments:
|
|
161
|
+
typeArguments === undefined
|
|
162
|
+
? ''
|
|
163
|
+
: `<${typeArguments.map((type) => type.getText(sourceFile)).join(', ')}>`,
|
|
164
|
+
json: ts.isPropertyAssignment(property)
|
|
165
|
+
? property.initializer.getText(sourceFile)
|
|
166
|
+
: 'contractJson',
|
|
167
|
+
jsonNames: ts.isPropertyAssignment(property)
|
|
168
|
+
? identifiersIn(ts, property.initializer)
|
|
169
|
+
: ['contractJson'],
|
|
170
|
+
staticEntry,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
ts.forEachChild(node, visit);
|
|
175
|
+
};
|
|
176
|
+
visit(sourceFile);
|
|
177
|
+
return calls;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function importEdit(
|
|
181
|
+
ts: typeof TS,
|
|
182
|
+
sourceFile: TS.SourceFile,
|
|
183
|
+
imports: readonly TS.ImportDeclaration[],
|
|
184
|
+
staticEntry: string,
|
|
185
|
+
style: { readonly quote: string; readonly semicolon: string; readonly eol: string },
|
|
186
|
+
): Edit | { readonly after: string } {
|
|
187
|
+
const existing = imports.find(
|
|
188
|
+
(statement) =>
|
|
189
|
+
specifierOf(ts, statement) === staticEntry &&
|
|
190
|
+
statement.importClause !== undefined &&
|
|
191
|
+
!statement.importClause.isTypeOnly,
|
|
192
|
+
);
|
|
193
|
+
const clause = existing?.importClause;
|
|
194
|
+
const bindings = clause?.namedBindings;
|
|
195
|
+
if (bindings !== undefined && ts.isNamedImports(bindings)) {
|
|
196
|
+
const first = bindings.elements[0];
|
|
197
|
+
return first === undefined
|
|
198
|
+
? { start: bindings.getStart(sourceFile), end: bindings.end, text: '{ contractFromJson }' }
|
|
199
|
+
: {
|
|
200
|
+
start: first.getStart(sourceFile),
|
|
201
|
+
end: first.getStart(sourceFile),
|
|
202
|
+
text: 'contractFromJson, ',
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
if (clause?.name !== undefined && bindings === undefined) {
|
|
206
|
+
return { start: clause.name.end, end: clause.name.end, text: ', { contractFromJson }' };
|
|
207
|
+
}
|
|
208
|
+
const line = `import { contractFromJson } from ${style.quote}${staticEntry}${style.quote}${style.semicolon}`;
|
|
209
|
+
const before = imports.find(
|
|
210
|
+
(statement) =>
|
|
211
|
+
statement.importClause !== undefined &&
|
|
212
|
+
compareSpecifiers(specifierOf(ts, statement), staticEntry) > 0,
|
|
213
|
+
);
|
|
214
|
+
if (before === undefined) return { after: `${style.eol}${line}` };
|
|
215
|
+
const at = before.getStart(sourceFile);
|
|
216
|
+
return { start: at, end: at, text: `${line}${style.eol}` };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function moveFile(ts: typeof TS, fileName: string, source: string): Outcome {
|
|
220
|
+
const sourceFile = ts.createSourceFile(
|
|
221
|
+
fileName,
|
|
222
|
+
source,
|
|
223
|
+
ts.ScriptTarget.Latest,
|
|
224
|
+
true,
|
|
225
|
+
fileName.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS,
|
|
226
|
+
);
|
|
227
|
+
const imports = sourceFile.statements.filter(ts.isImportDeclaration);
|
|
228
|
+
const calls = movedCalls(ts, sourceFile, factoriesOf(ts, imports));
|
|
229
|
+
const first = calls[0];
|
|
230
|
+
if (first === undefined) {
|
|
231
|
+
return DETECTION.test(source)
|
|
232
|
+
? {
|
|
233
|
+
kind: 'refused',
|
|
234
|
+
reason: 'it passes contractJson to a client in a form the script cannot read',
|
|
235
|
+
}
|
|
236
|
+
: { kind: 'unchanged' };
|
|
237
|
+
}
|
|
238
|
+
if (
|
|
239
|
+
calls.some(
|
|
240
|
+
(call) =>
|
|
241
|
+
call.json !== first.json ||
|
|
242
|
+
call.typeArguments !== first.typeArguments ||
|
|
243
|
+
call.staticEntry !== first.staticEntry,
|
|
244
|
+
)
|
|
245
|
+
) {
|
|
246
|
+
return {
|
|
247
|
+
kind: 'refused',
|
|
248
|
+
reason: 'its clients use different contracts; give each its own contractFromJson value',
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
const names = topLevelNames(ts, sourceFile);
|
|
252
|
+
if (names.imported.has('contract') || names.declared.has('contract')) {
|
|
253
|
+
return {
|
|
254
|
+
kind: 'refused',
|
|
255
|
+
reason:
|
|
256
|
+
'it already has a binding named contract; rename that binding and run the script again',
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
const local = first.jsonNames.find((name) => names.declared.has(name));
|
|
260
|
+
if (local !== undefined) {
|
|
261
|
+
return {
|
|
262
|
+
kind: 'refused',
|
|
263
|
+
reason: `its contractJson value uses ${local}, which the file declares after its imports; declare the contract value after ${local} by hand`,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const lastImport = imports.at(-1);
|
|
268
|
+
if (lastImport === undefined) {
|
|
269
|
+
return { kind: 'refused', reason: 'it imports no client' };
|
|
270
|
+
}
|
|
271
|
+
const firstImport = imports[0];
|
|
272
|
+
const firstImportText = firstImport?.getText(sourceFile) ?? '';
|
|
273
|
+
const style = {
|
|
274
|
+
quote: firstImport?.moduleSpecifier.getText(sourceFile).startsWith('"') ? '"' : "'",
|
|
275
|
+
semicolon: firstImportText.endsWith(';') ? ';' : '',
|
|
276
|
+
eol: source.includes('\r\n') ? '\r\n' : '\n',
|
|
277
|
+
};
|
|
278
|
+
const edits: Edit[] = calls.flatMap((call) => call.edits);
|
|
279
|
+
const staticImport = importEdit(ts, sourceFile, imports, first.staticEntry, style);
|
|
280
|
+
const importedAfter = 'after' in staticImport ? staticImport.after : '';
|
|
281
|
+
if ('start' in staticImport) edits.push(staticImport);
|
|
282
|
+
|
|
283
|
+
let afterImports = lastImport.end;
|
|
284
|
+
while (source[afterImports] === '\r' || source[afterImports] === '\n') afterImports++;
|
|
285
|
+
const exported = !hasDefaultExport(ts, sourceFile);
|
|
286
|
+
const declaration = `${exported ? 'export ' : ''}const contract = contractFromJson${first.typeArguments}(${first.json})${style.semicolon}`;
|
|
287
|
+
edits.push({
|
|
288
|
+
start: lastImport.end,
|
|
289
|
+
end: afterImports,
|
|
290
|
+
text: `${importedAfter}${style.eol}${style.eol}${declaration}${style.eol}${afterImports < source.length ? style.eol : ''}`,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
let moved = source;
|
|
294
|
+
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
295
|
+
moved = moved.slice(0, edit.start) + edit.text + moved.slice(edit.end);
|
|
296
|
+
}
|
|
297
|
+
return { kind: 'rewritten', source: moved, exported };
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function hasDefaultExport(ts: typeof TS, sourceFile: TS.SourceFile): boolean {
|
|
301
|
+
return sourceFile.statements.some(
|
|
302
|
+
(statement) =>
|
|
303
|
+
(ts.isExportAssignment(statement) && !statement.isExportEquals) ||
|
|
304
|
+
(ts.isExportDeclaration(statement) &&
|
|
305
|
+
statement.exportClause !== undefined &&
|
|
306
|
+
ts.isNamedExports(statement.exportClause) &&
|
|
307
|
+
statement.exportClause.elements.some((element) => element.name.text === 'default')) ||
|
|
308
|
+
(ts.canHaveModifiers(statement) &&
|
|
309
|
+
(ts.getModifiers(statement)?.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword) ??
|
|
310
|
+
false)),
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function isTestPath(path: string): boolean {
|
|
315
|
+
return TEST_FILE.test(path) || path.split(/[\\/]/).some((part) => TEST_DIRECTORIES.has(part));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function sourceFiles(directory: string): string[] {
|
|
319
|
+
const files: string[] = [];
|
|
320
|
+
for (const entry of readdirSync(directory)) {
|
|
321
|
+
if (SKIPPED_DIRECTORIES.has(entry)) continue;
|
|
322
|
+
const path = join(directory, entry);
|
|
323
|
+
if (statSync(path).isDirectory()) files.push(...sourceFiles(path));
|
|
324
|
+
else if (SOURCE_FILE.test(entry) && !entry.endsWith('.d.ts')) files.push(path);
|
|
325
|
+
}
|
|
326
|
+
return files;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function loadTypeScript(root: string, explicit: string | undefined): typeof TS | undefined {
|
|
330
|
+
const require = createRequire(join(root, 'package.json'));
|
|
331
|
+
try {
|
|
332
|
+
return require(explicit ?? 'typescript');
|
|
333
|
+
} catch {
|
|
334
|
+
return undefined;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function main(): number {
|
|
339
|
+
const args = process.argv.slice(2);
|
|
340
|
+
const flag = args.indexOf('--typescript');
|
|
341
|
+
const explicit = flag === -1 ? undefined : resolve(args[flag + 1] ?? '');
|
|
342
|
+
const positional = args.filter(
|
|
343
|
+
(_, index) => flag === -1 || (index !== flag && index !== flag + 1),
|
|
344
|
+
);
|
|
345
|
+
const root = resolve(positional[0] ?? process.cwd());
|
|
346
|
+
const ts = loadTypeScript(root, explicit);
|
|
347
|
+
if (ts === undefined) {
|
|
348
|
+
process.stderr.write(
|
|
349
|
+
`TypeScript is not installed in ${root}. Install it (for example pnpm add -D typescript) and run the script again, or move each client by hand as the guide describes. No file was changed.\n`,
|
|
350
|
+
);
|
|
351
|
+
return 1;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
let refused = 0;
|
|
355
|
+
for (const path of sourceFiles(root).sort()) {
|
|
356
|
+
const name = relative(root, path).split('\\').join('/');
|
|
357
|
+
const source = readFileSync(path, 'utf8');
|
|
358
|
+
const outcome: Outcome = isTestPath(name)
|
|
359
|
+
? DETECTION.test(source)
|
|
360
|
+
? {
|
|
361
|
+
kind: 'refused',
|
|
362
|
+
reason:
|
|
363
|
+
'it is a test file; import the contract value from the module that creates the client',
|
|
364
|
+
}
|
|
365
|
+
: { kind: 'unchanged' }
|
|
366
|
+
: moveFile(ts, path, source);
|
|
367
|
+
if (outcome.kind === 'rewritten') {
|
|
368
|
+
writeFileSync(path, outcome.source);
|
|
369
|
+
process.stdout.write(
|
|
370
|
+
outcome.exported
|
|
371
|
+
? `${name}: moved to contractFromJson\n`
|
|
372
|
+
: `${name}: moved to contractFromJson; contract is not exported, because the module has a default export (a Worker treats every named export of its entry module as an entrypoint); a module that needs the value gets it from a separate module\n`,
|
|
373
|
+
);
|
|
374
|
+
} else if (outcome.kind === 'refused') {
|
|
375
|
+
refused++;
|
|
376
|
+
process.stderr.write(`${name}: not moved, because ${outcome.reason}\n`);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return refused === 0 ? 0 : 1;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
process.exitCode = main();
|