@standards/cli 1.0.0-alpha.404 → 1.0.0-alpha.406
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 +4 -17
- package/dist/bin.mjs +0 -90
- package/package.json +5 -5
- package/dist/builder-shorthand-CPJ9hFiW.mjs +0 -204
- package/dist/engine-imports-K-yySYo3.mjs +0 -173
- package/dist/image-Ca-XlG3r.mjs +0 -99
- package/dist/locale-CfZalwmA.mjs +0 -228
- package/dist/palette-D63ag-eX.mjs +0 -148
- package/dist/scopes-Bqw1v3wB.mjs +0 -122
- package/dist/source-files-D2Bdfvhx.mjs +0 -76
package/README.md
CHANGED
|
@@ -40,29 +40,16 @@ the adapters and the rest of the restricted set) left `@stndrds/*` on npmjs for
|
|
|
40
40
|
registry `https://registry.standards.run/` at `1.0.0-alpha.381`; the public ones (`cli`,
|
|
41
41
|
`client`, `constants`, `schema`) followed at `1.0.0-alpha.382`, published both on npmjs and on
|
|
42
42
|
the licensed registry at the same version, so a project that maps the whole `@standards` scope to
|
|
43
|
-
the licensed registry finds them there too. The old `@stndrds/*` names are deprecated
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
npx @standards/cli codemod scopes --dry-run
|
|
48
|
-
npx @standards/cli codemod scopes
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
It renames every `@stndrds/<package>` reference to `@standards/<package>` in code, styles,
|
|
52
|
-
`package.json`, YAML (`pnpm-workspace.yaml`) and Markdown (`AGENTS.md`, `CLAUDE.md`) under the
|
|
53
|
-
paths you give (default `.`); `@stndrds/ui-kit`-style names that only start like one of ours are
|
|
54
|
-
left alone, and lockfiles are never edited. Run it again if you ran it before `1.0.0-alpha.382`:
|
|
55
|
-
that version only moved the licensed packages. It then points
|
|
56
|
-
`@standards` at the licensed registry in the `.npmrc` in `--root` (default `.`):
|
|
43
|
+
the licensed registry finds them there too. The old `@stndrds/*` names are deprecated: rename each `@stndrds/<package>` reference to
|
|
44
|
+
`@standards/<package>` and point `@standards` at the licensed registry in the project `.npmrc`:
|
|
57
45
|
|
|
58
46
|
```ini
|
|
59
47
|
@standards:registry=https://registry.standards.run/
|
|
60
48
|
```
|
|
61
49
|
|
|
62
|
-
|
|
50
|
+
The licence key never goes in the project
|
|
63
51
|
`.npmrc`: pnpm does not expand environment variables in registry credentials it reads there, so
|
|
64
|
-
`${STANDARDS_TOKEN}` in that file reaches the registry as no key at all (401).
|
|
65
|
-
removes such a line if an earlier run wrote it. Put the key in your user-level `~/.npmrc`, which
|
|
52
|
+
`${STANDARDS_TOKEN}` in that file reaches the registry as no key at all (401). Put the key in your user-level `~/.npmrc`, which
|
|
66
53
|
npm and pnpm both read:
|
|
67
54
|
|
|
68
55
|
```bash
|
package/dist/bin.mjs
CHANGED
|
@@ -315,95 +315,6 @@ function registerBundlesCommand(program) {
|
|
|
315
315
|
}));
|
|
316
316
|
}
|
|
317
317
|
//#endregion
|
|
318
|
-
//#region src/commands/codemod.ts
|
|
319
|
-
/** Rewrites consumer code for a breaking SDK change. */
|
|
320
|
-
function registerCodemodCommand(program) {
|
|
321
|
-
const codemod = program.command("codemod").description("Rewrite code for a breaking SDK change");
|
|
322
|
-
codemod.command("builder-shorthand").description("Rewrite text({ name, label }) builders to text(name, label)").argument("[paths...]", "files or directories to rewrite", ["."]).option("--dry-run", "report without writing").option("--relative-imports", "also treat relative imports as Standards builders — for the Standards monorepo itself").action(async (paths, opts) => {
|
|
323
|
-
const { runBuilderShorthand } = await import("./builder-shorthand-CPJ9hFiW.mjs");
|
|
324
|
-
const report = await runBuilderShorthand(paths, {
|
|
325
|
-
write: !opts.dryRun,
|
|
326
|
-
relativeImports: opts.relativeImports === true
|
|
327
|
-
});
|
|
328
|
-
const verb = opts.dryRun ? "Would rewrite" : "Rewrote";
|
|
329
|
-
process.stdout.write(`${verb} ${report.changed} calls in ${report.files} files.\n`);
|
|
330
|
-
for (const call of report.skipped) process.stdout.write(`${call.file}:${call.line}:${call.column} ${call.callee} ${call.reason}\n`);
|
|
331
|
-
if (report.skipped.length > 0) {
|
|
332
|
-
process.stdout.write(`${report.skipped.length} calls need a manual rewrite to fn(name, label), then re-run "standards codemod builder-shorthand".\n`);
|
|
333
|
-
process.exitCode = 1;
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
codemod.command("palette").description("Rewrite old colour ids (blue, green, ...) to the Standards palette").argument("[paths...]", "files or directories to rewrite", ["."]).option("--dry-run", "report without writing").action(async (paths, opts) => {
|
|
337
|
-
const { runPalette } = await import("./palette-D63ag-eX.mjs");
|
|
338
|
-
const report = await runPalette(paths, { write: !opts.dryRun });
|
|
339
|
-
const verb = opts.dryRun ? "Would rewrite" : "Rewrote";
|
|
340
|
-
process.stdout.write(`${verb} ${report.changed} colours in ${report.files} files.\n`);
|
|
341
|
-
if (opts.dryRun) for (const entry of report.rewritten) process.stdout.write(` ${entry.file}: ${entry.changed}\n`);
|
|
342
|
-
for (const failure of report.failures) process.stderr.write(`${failure.message}\n`);
|
|
343
|
-
if (report.failures.length > 0) process.exitCode = 1;
|
|
344
|
-
});
|
|
345
|
-
codemod.command("image").description("Rewrite .imageShape(x) to .image({ shape: x }) and appearance.imageFileId to appearance.image?.fileId").argument("[paths...]", "files or directories to rewrite", ["."]).option("--dry-run", "report without writing").action(async (paths, opts) => {
|
|
346
|
-
const { runImage } = await import("./image-Ca-XlG3r.mjs");
|
|
347
|
-
const report = await runImage(paths, { write: !opts.dryRun });
|
|
348
|
-
const verb = opts.dryRun ? "Would rewrite" : "Rewrote";
|
|
349
|
-
process.stdout.write(`${verb} ${report.changed} references in ${report.files} files.\n`);
|
|
350
|
-
for (const { file, line, column } of report.skipped) process.stdout.write(`${file}:${line}:${column} appearance.imageFileId a write, rewrite by hand\n`);
|
|
351
|
-
for (const failure of report.failures) process.stderr.write(`${failure.message}\n`);
|
|
352
|
-
if (report.skipped.length > 0 || report.failures.length > 0) process.exitCode = 1;
|
|
353
|
-
});
|
|
354
|
-
codemod.command("locale").description("Rewrite a whole dictionary passed as translations to locale, and DEFAULT_*_TRANSLATIONS to EN_*").argument("[paths...]", "files or directories to rewrite", ["."]).option("--dry-run", "report without writing").action(async (paths, opts) => {
|
|
355
|
-
const { runLocale } = await import("./locale-CfZalwmA.mjs");
|
|
356
|
-
const report = await runLocale(paths, { write: !opts.dryRun });
|
|
357
|
-
const verb = opts.dryRun ? "Would rewrite" : "Rewrote";
|
|
358
|
-
process.stdout.write(`${verb} ${report.changed} references in ${report.files} files.\n`);
|
|
359
|
-
for (const { file, line, column } of report.skipped) process.stdout.write(`${file}:${line}:${column} translations pass locale, keep only your overrides\n`);
|
|
360
|
-
for (const failure of report.failures) process.stderr.write(`${failure.message}\n`);
|
|
361
|
-
if (report.skipped.length > 0 || report.failures.length > 0) process.exitCode = 1;
|
|
362
|
-
});
|
|
363
|
-
codemod.command("engine-imports").description("Move imports of names that left @standards/schema to @standards/engine").argument("[paths...]", "files or directories to rewrite", ["."]).option("--dry-run", "report without writing").option("--root <dir>", "where @standards/schema and @standards/engine are installed", ".").action(async (paths, opts) => {
|
|
364
|
-
const { runEngineImports } = await import("./engine-imports-K-yySYo3.mjs");
|
|
365
|
-
const report = await runEngineImports(paths, {
|
|
366
|
-
write: !opts.dryRun,
|
|
367
|
-
root: opts.root
|
|
368
|
-
});
|
|
369
|
-
if (typeof report === "string") {
|
|
370
|
-
process.stderr.write(`${report}\n`);
|
|
371
|
-
process.exitCode = 1;
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
const verb = opts.dryRun ? "Would move" : "Moved";
|
|
375
|
-
process.stdout.write(`${verb} ${report.moved} imports in ${report.files} files.\n`);
|
|
376
|
-
for (const { file, name } of report.unresolved) process.stdout.write(`${file} ${name} not moved, check by hand\n`);
|
|
377
|
-
for (const failure of report.failures) process.stderr.write(`${failure.message}\n`);
|
|
378
|
-
if (report.failures.length > 0) process.exitCode = 1;
|
|
379
|
-
});
|
|
380
|
-
codemod.command("scopes").description("Move every @stndrds/* package to @standards/* and point @standards at the licensed registry").argument("[paths...]", "files or directories to rewrite", ["."]).option("--dry-run", "report without writing").option("--root <dir>", "where the project's .npmrc lives", ".").action(async (paths, opts) => {
|
|
381
|
-
const { runScopes } = await import("./scopes-Bqw1v3wB.mjs");
|
|
382
|
-
const report = await runScopes(paths, {
|
|
383
|
-
write: !opts.dryRun,
|
|
384
|
-
root: opts.root
|
|
385
|
-
});
|
|
386
|
-
const verb = opts.dryRun ? "Would rewrite" : "Rewrote";
|
|
387
|
-
process.stdout.write(`${verb} ${report.changed} references in ${report.files} files.\n`);
|
|
388
|
-
if (report.npmrc !== void 0) {
|
|
389
|
-
const action = opts.dryRun ? "Would point" : "Pointed";
|
|
390
|
-
process.stdout.write(`${action} @standards at the licensed registry in ${report.npmrc}.\n`);
|
|
391
|
-
}
|
|
392
|
-
if (!report.licensed) {
|
|
393
|
-
process.stdout.write("Then reinstall to refresh the lockfile.\n");
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
process.stdout.write([
|
|
397
|
-
"Your licence key goes in your user ~/.npmrc, never the project one (pnpm ignores it there):",
|
|
398
|
-
" npm config set \"//registry.standards.run/:_authToken\" \"$STANDARDS_TOKEN\"",
|
|
399
|
-
"In CI, add it to $HOME/.npmrc before installing, with STANDARDS_TOKEN set from a secret:",
|
|
400
|
-
` echo '//registry.standards.run/:_authToken=\${STANDARDS_TOKEN}' >> "$HOME/.npmrc"`,
|
|
401
|
-
"Then reinstall to refresh the lockfile.",
|
|
402
|
-
""
|
|
403
|
-
].join("\n"));
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
//#endregion
|
|
407
318
|
//#region src/commands/connectors.ts
|
|
408
319
|
const PROVIDERS = Object.keys({
|
|
409
320
|
github: true,
|
|
@@ -2115,7 +2026,6 @@ function createProgram() {
|
|
|
2115
2026
|
registerInvitationsCommand(program);
|
|
2116
2027
|
registerAuthCommand(program);
|
|
2117
2028
|
registerBundlesCommand(program);
|
|
2118
|
-
registerCodemodCommand(program);
|
|
2119
2029
|
registerConnectorsCommand(program);
|
|
2120
2030
|
registerMcpCommand(program);
|
|
2121
2031
|
registerMeetingsCommand(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@standards/cli",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.406",
|
|
4
4
|
"description": "CLI tool to interact with Standards API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,17 +26,17 @@
|
|
|
26
26
|
"cli-table3": "^0.6.5",
|
|
27
27
|
"commander": "^13.1.0",
|
|
28
28
|
"jiti": "2.7.0",
|
|
29
|
-
"typescript": "^5.6.3",
|
|
30
29
|
"ws": "8.21.1",
|
|
31
|
-
"@standards/client": "1.0.0-alpha.
|
|
32
|
-
"@standards/constants": "1.0.0-alpha.
|
|
33
|
-
"@standards/schema": "1.0.0-alpha.
|
|
30
|
+
"@standards/client": "1.0.0-alpha.406",
|
|
31
|
+
"@standards/constants": "1.0.0-alpha.406",
|
|
32
|
+
"@standards/schema": "1.0.0-alpha.406"
|
|
34
33
|
},
|
|
35
34
|
"devDependencies": {
|
|
36
35
|
"@types/node": "^25.6.0",
|
|
37
36
|
"@types/ws": "8.18.1",
|
|
38
37
|
"jsdom": "^25.0.1",
|
|
39
38
|
"tsdown": "^0.23.0",
|
|
39
|
+
"typescript": "^5.6.3",
|
|
40
40
|
"typescript7": "npm:typescript@^7.0.2",
|
|
41
41
|
"vitest": "^5.0.5"
|
|
42
42
|
},
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*! © 2025-2026 AND YOU CREATE SAS (RCS Paris 940 190 614). Proprietary — see LICENSE (Standards SDK License 1.0). */
|
|
3
|
-
import { i as rewriteSourceFiles, n as parseSourceFile, t as applyEdits } from "./source-files-D2Bdfvhx.mjs";
|
|
4
|
-
import ts from "typescript";
|
|
5
|
-
//#region src/codemod/builder-shorthand.ts
|
|
6
|
-
const BUILDERS = /* @__PURE__ */ new Set([
|
|
7
|
-
"text",
|
|
8
|
-
"richtext",
|
|
9
|
-
"number",
|
|
10
|
-
"checkbox",
|
|
11
|
-
"date",
|
|
12
|
-
"phone",
|
|
13
|
-
"currency",
|
|
14
|
-
"status",
|
|
15
|
-
"select",
|
|
16
|
-
"multiselect",
|
|
17
|
-
"location",
|
|
18
|
-
"user",
|
|
19
|
-
"relation",
|
|
20
|
-
"formula",
|
|
21
|
-
"rollup",
|
|
22
|
-
"document",
|
|
23
|
-
"object",
|
|
24
|
-
"nativeObject"
|
|
25
|
-
]);
|
|
26
|
-
const WITH_ID = /* @__PURE__ */ new Set(["object", "nativeObject"]);
|
|
27
|
-
const STANDARDS_PACKAGE = /^@standards\/(schema|client)$/;
|
|
28
|
-
const RELATIVE_MODULE = /^\.{1,2}\//;
|
|
29
|
-
const COMMENT_IN_CONFIG = "comment in config, rewrite by hand";
|
|
30
|
-
/** Import clauses whose module counts as Standards: the packages, plus relative paths on opt-in. */
|
|
31
|
-
function standardsImports(file, options) {
|
|
32
|
-
const clauses = [];
|
|
33
|
-
for (const statement of file.statements) {
|
|
34
|
-
if (!(ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier))) continue;
|
|
35
|
-
const specifier = statement.moduleSpecifier.text;
|
|
36
|
-
if ((STANDARDS_PACKAGE.test(specifier) || options.relativeImports === true && RELATIVE_MODULE.test(specifier)) && statement.importClause) clauses.push(statement.importClause);
|
|
37
|
-
}
|
|
38
|
-
return clauses;
|
|
39
|
-
}
|
|
40
|
-
/** Local identifier → exported builder name, for named imports from Standards. */
|
|
41
|
-
function importedBuilders(clauses) {
|
|
42
|
-
const found = /* @__PURE__ */ new Map();
|
|
43
|
-
for (const clause of clauses) {
|
|
44
|
-
const bindings = clause.namedBindings;
|
|
45
|
-
if (!(bindings && ts.isNamedImports(bindings))) continue;
|
|
46
|
-
for (const element of bindings.elements) {
|
|
47
|
-
const exported = element.propertyName?.text ?? element.name.text;
|
|
48
|
-
if (BUILDERS.has(exported)) found.set(element.name.text, exported);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return found;
|
|
52
|
-
}
|
|
53
|
-
/** True when `[start, end)` of the file holds a comment, which a rewrite would drop. */
|
|
54
|
-
function hasComment(file, start, end) {
|
|
55
|
-
const scanner = ts.createScanner(ts.ScriptTarget.Latest, false, file.languageVariant, file.text.slice(start, end));
|
|
56
|
-
for (let token = scanner.scan(); token !== ts.SyntaxKind.EndOfFileToken; token = scanner.scan()) if (token === ts.SyntaxKind.SingleLineCommentTrivia || token === ts.SyntaxKind.MultiLineCommentTrivia) return true;
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
function readConfig(literal, file, allowed) {
|
|
60
|
-
const values = /* @__PURE__ */ new Map();
|
|
61
|
-
for (const property of literal.properties) {
|
|
62
|
-
if (ts.isSpreadAssignment(property)) return "spread in config";
|
|
63
|
-
if (ts.isShorthandPropertyAssignment(property)) {
|
|
64
|
-
values.set(property.name.text, property.name.text);
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
if (!(ts.isPropertyAssignment(property) && ts.isIdentifier(property.name))) return "unsupported property in config";
|
|
68
|
-
const key = property.name.text;
|
|
69
|
-
if (!allowed.has(key)) return `unsupported key "${key}"`;
|
|
70
|
-
values.set(key, property.initializer.getText(file));
|
|
71
|
-
}
|
|
72
|
-
if (!(values.has("name") && values.has("label"))) return "missing name or label";
|
|
73
|
-
return values;
|
|
74
|
-
}
|
|
75
|
-
function rewriteBuilder(call, exported, file) {
|
|
76
|
-
const [config] = call.arguments;
|
|
77
|
-
if (call.arguments.length !== 1 || config === void 0) return { kind: "none" };
|
|
78
|
-
if (!ts.isObjectLiteralExpression(config)) return {
|
|
79
|
-
kind: "skip",
|
|
80
|
-
reason: "config is not an object literal"
|
|
81
|
-
};
|
|
82
|
-
const values = readConfig(config, file, new Set(WITH_ID.has(exported) ? [
|
|
83
|
-
"name",
|
|
84
|
-
"label",
|
|
85
|
-
"id"
|
|
86
|
-
] : ["name", "label"]));
|
|
87
|
-
if (typeof values === "string") return {
|
|
88
|
-
kind: "skip",
|
|
89
|
-
reason: values
|
|
90
|
-
};
|
|
91
|
-
if (hasComment(file, config.getStart(file), config.getEnd())) return {
|
|
92
|
-
kind: "skip",
|
|
93
|
-
reason: COMMENT_IN_CONFIG
|
|
94
|
-
};
|
|
95
|
-
const edits = [{
|
|
96
|
-
start: config.getStart(file),
|
|
97
|
-
end: config.getEnd(),
|
|
98
|
-
text: `${values.get("name")}, ${values.get("label")}`
|
|
99
|
-
}];
|
|
100
|
-
const id = values.get("id");
|
|
101
|
-
if (id !== void 0) edits.push({
|
|
102
|
-
start: call.getEnd(),
|
|
103
|
-
end: call.getEnd(),
|
|
104
|
-
text: `.id(${id})`
|
|
105
|
-
});
|
|
106
|
-
return {
|
|
107
|
-
kind: "edit",
|
|
108
|
-
edits
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
function overlaps(x, y) {
|
|
112
|
-
if (x.start === x.end && y.start === y.end) return x.start === y.start;
|
|
113
|
-
return x.start < y.end && y.start < x.end;
|
|
114
|
-
}
|
|
115
|
-
/** The widest call among those whose edits collide with another call's edits. */
|
|
116
|
-
function findOverlapVictim(calls) {
|
|
117
|
-
let victim;
|
|
118
|
-
for (const [i, first] of calls.entries()) for (const second of calls.slice(i + 1)) {
|
|
119
|
-
if (!first.edits.some((x) => second.edits.some((y) => overlaps(x, y)))) continue;
|
|
120
|
-
const wider = first.node.getWidth() >= second.node.getWidth() ? first : second;
|
|
121
|
-
if (victim === void 0 || wider.node.getWidth() > victim.node.getWidth()) victim = wider;
|
|
122
|
-
}
|
|
123
|
-
return victim;
|
|
124
|
-
}
|
|
125
|
-
/** Local names of `import * as x` from Standards. */
|
|
126
|
-
function importedNamespaces(clauses) {
|
|
127
|
-
const found = /* @__PURE__ */ new Set();
|
|
128
|
-
for (const clause of clauses) {
|
|
129
|
-
const bindings = clause.namedBindings;
|
|
130
|
-
if (bindings && ts.isNamespaceImport(bindings)) found.add(bindings.name.text);
|
|
131
|
-
}
|
|
132
|
-
return found;
|
|
133
|
-
}
|
|
134
|
-
/** True when a call to `exported` still has the pre-shorthand argument shape. */
|
|
135
|
-
function isLegacyShape(call, exported) {
|
|
136
|
-
return BUILDERS.has(exported) && call.arguments.length === 1;
|
|
137
|
-
}
|
|
138
|
-
/** Every TS and JS module a schema can live in; declaration files carry no calls. */
|
|
139
|
-
/** Rewrites `fn({ name, label })` builders of one file to `fn(name, label)`. */
|
|
140
|
-
function rewriteBuilderShorthand(text, fileName, options = {}) {
|
|
141
|
-
const { file } = parseSourceFile(text, fileName);
|
|
142
|
-
const clauses = standardsImports(file, options);
|
|
143
|
-
const builders = importedBuilders(clauses);
|
|
144
|
-
const namespaces = importedNamespaces(clauses);
|
|
145
|
-
const calls = [];
|
|
146
|
-
const skipped = [];
|
|
147
|
-
function skip(node, callee, reason) {
|
|
148
|
-
const { line, character } = file.getLineAndCharacterOfPosition(node.getStart(file));
|
|
149
|
-
skipped.push({
|
|
150
|
-
file: fileName,
|
|
151
|
-
line: line + 1,
|
|
152
|
-
column: character + 1,
|
|
153
|
-
callee,
|
|
154
|
-
reason
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
function visit(node) {
|
|
158
|
-
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
|
|
159
|
-
const exported = builders.get(node.expression.text);
|
|
160
|
-
if (exported !== void 0) {
|
|
161
|
-
const outcome = rewriteBuilder(node, exported, file);
|
|
162
|
-
if (outcome.kind === "edit") calls.push({
|
|
163
|
-
node,
|
|
164
|
-
edits: outcome.edits
|
|
165
|
-
});
|
|
166
|
-
else if (outcome.kind === "skip") skip(node, node.expression.text, outcome.reason);
|
|
167
|
-
}
|
|
168
|
-
} else if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.expression) && namespaces.has(node.expression.expression.text) && isLegacyShape(node, node.expression.name.text)) skip(node, node.expression.getText(file), "namespace import, rewrite by hand");
|
|
169
|
-
ts.forEachChild(node, visit);
|
|
170
|
-
}
|
|
171
|
-
visit(file);
|
|
172
|
-
let kept = calls;
|
|
173
|
-
for (;;) {
|
|
174
|
-
const victim = findOverlapVictim(kept);
|
|
175
|
-
if (victim === void 0) break;
|
|
176
|
-
skip(victim.node, victim.node.expression.text, "overlapping rewrite");
|
|
177
|
-
kept = kept.filter((call) => call !== victim);
|
|
178
|
-
}
|
|
179
|
-
skipped.sort((x, y) => x.line - y.line || x.column - y.column);
|
|
180
|
-
const changed = kept.length;
|
|
181
|
-
return {
|
|
182
|
-
output: applyEdits(text, kept.flatMap((call) => call.edits)),
|
|
183
|
-
changed,
|
|
184
|
-
skipped
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
/** Walks `paths`, rewrites every TS file, writes back when `write` is set. */
|
|
188
|
-
async function runBuilderShorthand(paths, options) {
|
|
189
|
-
const report = {
|
|
190
|
-
files: 0,
|
|
191
|
-
changed: 0,
|
|
192
|
-
skipped: []
|
|
193
|
-
};
|
|
194
|
-
const results = await rewriteSourceFiles(paths, options.write, (text, path) => rewriteBuilderShorthand(text, path, options));
|
|
195
|
-
for (const { result } of results) {
|
|
196
|
-
report.skipped.push(...result.skipped);
|
|
197
|
-
if (result.changed === 0) continue;
|
|
198
|
-
report.files += 1;
|
|
199
|
-
report.changed += result.changed;
|
|
200
|
-
}
|
|
201
|
-
return report;
|
|
202
|
-
}
|
|
203
|
-
//#endregion
|
|
204
|
-
export { runBuilderShorthand };
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*! © 2025-2026 AND YOU CREATE SAS (RCS Paris 940 190 614). Proprietary — see LICENSE (Standards SDK License 1.0). */
|
|
3
|
-
import { i as rewriteSourceFiles, n as parseSourceFile, t as applyEdits } from "./source-files-D2Bdfvhx.mjs";
|
|
4
|
-
import { join, resolve } from "node:path";
|
|
5
|
-
import ts from "typescript";
|
|
6
|
-
//#region src/codemod/engine-imports.ts
|
|
7
|
-
const SCHEMA = "@standards/schema";
|
|
8
|
-
const ENGINE = "@standards/engine";
|
|
9
|
-
/** Subpath entries that moved whole: their specifier is renamed, nothing else. */
|
|
10
|
-
const MOVED_SUBPATHS = /* @__PURE__ */ new Set(["capabilities", "webhooks"]);
|
|
11
|
-
function isSchemaSpecifier(specifier) {
|
|
12
|
-
return specifier === SCHEMA || specifier.startsWith(`${SCHEMA}/`);
|
|
13
|
-
}
|
|
14
|
-
function schemaLiteralOf(node) {
|
|
15
|
-
const literal = node.moduleSpecifier;
|
|
16
|
-
return literal !== void 0 && ts.isStringLiteral(literal) && isSchemaSpecifier(literal.text) ? literal : void 0;
|
|
17
|
-
}
|
|
18
|
-
function namedElements(node) {
|
|
19
|
-
if (ts.isImportDeclaration(node)) {
|
|
20
|
-
const bindings = node.importClause?.namedBindings;
|
|
21
|
-
if (node.importClause?.name !== void 0) return void 0;
|
|
22
|
-
return bindings !== void 0 && ts.isNamedImports(bindings) ? bindings.elements : void 0;
|
|
23
|
-
}
|
|
24
|
-
return node.exportClause !== void 0 && ts.isNamedExports(node.exportClause) ? node.exportClause.elements : void 0;
|
|
25
|
-
}
|
|
26
|
-
function declaration(node, elements, specifier) {
|
|
27
|
-
return `${ts.isImportDeclaration(node) ? "import" : "export"}${(ts.isImportDeclaration(node) ? node.importClause?.isTypeOnly : node.isTypeOnly) ? " type" : ""} { ${elements.join(", ")} } from "${specifier}";`;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Moves every name `@standards/schema` no longer exports, and `@standards/engine`
|
|
31
|
-
* does, out of a schema import into an engine import beside it.
|
|
32
|
-
*/
|
|
33
|
-
function rewriteEngineImports(source, fileName, exports) {
|
|
34
|
-
const parsed = parseSourceFile(source, fileName);
|
|
35
|
-
if (parsed.error !== void 0) return {
|
|
36
|
-
output: source,
|
|
37
|
-
changed: 0,
|
|
38
|
-
unresolved: [],
|
|
39
|
-
error: parsed.error
|
|
40
|
-
};
|
|
41
|
-
const edits = [];
|
|
42
|
-
const unresolved = [];
|
|
43
|
-
let moved = 0;
|
|
44
|
-
for (const node of parsed.file.statements) {
|
|
45
|
-
if (!(ts.isImportDeclaration(node) || ts.isExportDeclaration(node))) continue;
|
|
46
|
-
const literal = schemaLiteralOf(node);
|
|
47
|
-
if (literal === void 0) continue;
|
|
48
|
-
const specifier = literal.text;
|
|
49
|
-
const subpath = specifier.slice(18);
|
|
50
|
-
if (MOVED_SUBPATHS.has(subpath)) {
|
|
51
|
-
const quote = literal.getText().charAt(0);
|
|
52
|
-
edits.push({
|
|
53
|
-
start: literal.getStart(),
|
|
54
|
-
end: literal.getEnd(),
|
|
55
|
-
text: `${quote}${ENGINE}/${subpath}${quote}`
|
|
56
|
-
});
|
|
57
|
-
moved += 1;
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
const elements = namedElements(node);
|
|
61
|
-
if (elements === void 0) {
|
|
62
|
-
if (ts.isExportDeclaration(node) || node.importClause !== void 0) unresolved.push(node.getText());
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
const stay = [];
|
|
66
|
-
const go = [];
|
|
67
|
-
for (const element of elements) {
|
|
68
|
-
const name = (element.propertyName ?? element.name).text;
|
|
69
|
-
if (exports.schema(specifier).has(name)) stay.push(element.getText());
|
|
70
|
-
else if (exports.engine.has(name)) go.push(element.getText());
|
|
71
|
-
else {
|
|
72
|
-
unresolved.push(name);
|
|
73
|
-
stay.push(element.getText());
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
if (go.length === 0) continue;
|
|
77
|
-
moved += go.length;
|
|
78
|
-
const text = stay.length === 0 ? declaration(node, go, ENGINE) : `${declaration(node, stay, specifier)}\n${declaration(node, go, ENGINE)}`;
|
|
79
|
-
edits.push({
|
|
80
|
-
start: node.getStart(),
|
|
81
|
-
end: node.getEnd(),
|
|
82
|
-
text
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
function visit(node) {
|
|
86
|
-
if (ts.isImportTypeNode(node) && ts.isLiteralTypeNode(node.argument) && ts.isStringLiteral(node.argument.literal) && isSchemaSpecifier(node.argument.literal.text) && node.qualifier !== void 0) {
|
|
87
|
-
const literal = node.argument.literal;
|
|
88
|
-
const first = ts.isIdentifier(node.qualifier) ? node.qualifier : node.qualifier.left;
|
|
89
|
-
const name = ts.isIdentifier(first) ? first.text : void 0;
|
|
90
|
-
if (name !== void 0 && !exports.schema(literal.text).has(name) && exports.engine.has(name)) {
|
|
91
|
-
const quote = literal.getText().charAt(0);
|
|
92
|
-
edits.push({
|
|
93
|
-
start: literal.getStart(),
|
|
94
|
-
end: literal.getEnd(),
|
|
95
|
-
text: `${quote}${ENGINE}${quote}`
|
|
96
|
-
});
|
|
97
|
-
moved += 1;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
ts.forEachChild(node, visit);
|
|
101
|
-
}
|
|
102
|
-
visit(parsed.file);
|
|
103
|
-
return {
|
|
104
|
-
output: applyEdits(source, edits),
|
|
105
|
-
changed: moved,
|
|
106
|
-
unresolved
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
/** The names a package's installed type declarations export, resolved from `root`. */
|
|
110
|
-
function exportedNames(packageName, root) {
|
|
111
|
-
const options = {
|
|
112
|
-
module: ts.ModuleKind.NodeNext,
|
|
113
|
-
moduleResolution: ts.ModuleResolutionKind.NodeNext,
|
|
114
|
-
skipLibCheck: true,
|
|
115
|
-
noEmit: true
|
|
116
|
-
};
|
|
117
|
-
const resolved = ts.resolveModuleName(packageName, join(root, "index.ts"), options, ts.sys).resolvedModule?.resolvedFileName;
|
|
118
|
-
if (resolved === void 0) return /* @__PURE__ */ new Set();
|
|
119
|
-
const program = ts.createProgram([resolved], options);
|
|
120
|
-
const file = program.getSourceFile(resolved);
|
|
121
|
-
const symbol = file && program.getTypeChecker().getSymbolAtLocation(file);
|
|
122
|
-
if (symbol === void 0) return /* @__PURE__ */ new Set();
|
|
123
|
-
return new Set(program.getTypeChecker().getExportsOfModule(symbol).map((exported) => exported.name));
|
|
124
|
-
}
|
|
125
|
-
/** Reads both packages as installed under `root`; fails when engine is not installed there. */
|
|
126
|
-
function installedExports(root) {
|
|
127
|
-
const bySpecifier = /* @__PURE__ */ new Map();
|
|
128
|
-
function schema(specifier) {
|
|
129
|
-
let names = bySpecifier.get(specifier);
|
|
130
|
-
if (names === void 0) {
|
|
131
|
-
names = exportedNames(specifier, root);
|
|
132
|
-
bySpecifier.set(specifier, names);
|
|
133
|
-
}
|
|
134
|
-
return names;
|
|
135
|
-
}
|
|
136
|
-
if (schema(SCHEMA).size === 0) return `${SCHEMA} is not installed under ${root}.`;
|
|
137
|
-
const engine = exportedNames(ENGINE, root);
|
|
138
|
-
if (engine.size === 0) return `Add ${ENGINE} to your dependencies and install it, then re-run.`;
|
|
139
|
-
return {
|
|
140
|
-
schema,
|
|
141
|
-
engine
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
async function runEngineImports(paths, options) {
|
|
145
|
-
const exports = installedExports(resolve(options.root));
|
|
146
|
-
if (typeof exports === "string") return exports;
|
|
147
|
-
const report = {
|
|
148
|
-
files: 0,
|
|
149
|
-
moved: 0,
|
|
150
|
-
unresolved: [],
|
|
151
|
-
failures: []
|
|
152
|
-
};
|
|
153
|
-
const results = await rewriteSourceFiles(paths, options.write, (text, path) => rewriteEngineImports(text, path, exports));
|
|
154
|
-
for (const { path, result } of results) {
|
|
155
|
-
if (result.error !== void 0) {
|
|
156
|
-
report.failures.push({
|
|
157
|
-
file: path,
|
|
158
|
-
message: result.error
|
|
159
|
-
});
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
for (const name of result.unresolved) report.unresolved.push({
|
|
163
|
-
file: path,
|
|
164
|
-
name
|
|
165
|
-
});
|
|
166
|
-
if (result.changed === 0) continue;
|
|
167
|
-
report.files += 1;
|
|
168
|
-
report.moved += result.changed;
|
|
169
|
-
}
|
|
170
|
-
return report;
|
|
171
|
-
}
|
|
172
|
-
//#endregion
|
|
173
|
-
export { runEngineImports };
|
package/dist/image-Ca-XlG3r.mjs
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*! © 2025-2026 AND YOU CREATE SAS (RCS Paris 940 190 614). Proprietary — see LICENSE (Standards SDK License 1.0). */
|
|
3
|
-
import { i as rewriteSourceFiles, n as parseSourceFile, t as applyEdits } from "./source-files-D2Bdfvhx.mjs";
|
|
4
|
-
import ts from "typescript";
|
|
5
|
-
//#region src/codemod/image.ts
|
|
6
|
-
function isAssignmentTarget(node) {
|
|
7
|
-
const { parent } = node;
|
|
8
|
-
if (ts.isBinaryExpression(parent)) {
|
|
9
|
-
const operator = parent.operatorToken.kind;
|
|
10
|
-
return parent.left === node && operator >= ts.SyntaxKind.FirstAssignment && operator <= ts.SyntaxKind.LastAssignment;
|
|
11
|
-
}
|
|
12
|
-
return (ts.isPrefixUnaryExpression(parent) || ts.isPostfixUnaryExpression(parent)) && (parent.operator === ts.SyntaxKind.PlusPlusToken || parent.operator === ts.SyntaxKind.MinusMinusToken);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Rewrites `.imageShape(x)` to `.image({ shape: x })` and `.appearance.imageFileId`
|
|
16
|
-
* to `.appearance.image?.fileId` in one source file.
|
|
17
|
-
*/
|
|
18
|
-
function rewriteImage(text, fileName) {
|
|
19
|
-
const { file, error } = parseSourceFile(text, fileName);
|
|
20
|
-
if (error !== void 0) return {
|
|
21
|
-
output: text,
|
|
22
|
-
changed: 0,
|
|
23
|
-
skipped: [],
|
|
24
|
-
error
|
|
25
|
-
};
|
|
26
|
-
const edits = [];
|
|
27
|
-
const skipped = [];
|
|
28
|
-
let changed = 0;
|
|
29
|
-
function visit(node) {
|
|
30
|
-
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "imageShape" && node.arguments.length === 1) {
|
|
31
|
-
const argument = node.arguments[0];
|
|
32
|
-
const open = node.arguments.pos;
|
|
33
|
-
const close = node.getEnd() - 1;
|
|
34
|
-
const before = text.slice(open, argument.getStart(file));
|
|
35
|
-
const after = text.slice(argument.getEnd(), close);
|
|
36
|
-
edits.push({
|
|
37
|
-
start: node.expression.name.getStart(file),
|
|
38
|
-
end: /^\s*$/.test(before) ? argument.getStart(file) : open,
|
|
39
|
-
text: "image({ shape: "
|
|
40
|
-
});
|
|
41
|
-
edits.push({
|
|
42
|
-
start: /^[\s,]*$/.test(after) ? argument.getEnd() : close,
|
|
43
|
-
end: node.getEnd(),
|
|
44
|
-
text: " })"
|
|
45
|
-
});
|
|
46
|
-
changed += 1;
|
|
47
|
-
} else if (ts.isPropertyAccessExpression(node) && node.name.text === "imageFileId" && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "appearance") {
|
|
48
|
-
if (isAssignmentTarget(node)) {
|
|
49
|
-
const { line, character } = file.getLineAndCharacterOfPosition(node.getStart(file));
|
|
50
|
-
skipped.push({
|
|
51
|
-
line: line + 1,
|
|
52
|
-
column: character + 1
|
|
53
|
-
});
|
|
54
|
-
} else {
|
|
55
|
-
edits.push({
|
|
56
|
-
start: node.name.getStart(file),
|
|
57
|
-
end: node.name.getEnd(),
|
|
58
|
-
text: "image?.fileId"
|
|
59
|
-
});
|
|
60
|
-
changed += 1;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
ts.forEachChild(node, visit);
|
|
64
|
-
}
|
|
65
|
-
visit(file);
|
|
66
|
-
return {
|
|
67
|
-
output: applyEdits(text, edits),
|
|
68
|
-
changed,
|
|
69
|
-
skipped
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
/** Walks `paths`, rewrites every TS or JS file, writes back when `write` is set. */
|
|
73
|
-
async function runImage(paths, options) {
|
|
74
|
-
const report = {
|
|
75
|
-
files: 0,
|
|
76
|
-
changed: 0,
|
|
77
|
-
skipped: [],
|
|
78
|
-
failures: []
|
|
79
|
-
};
|
|
80
|
-
for (const { path, result } of await rewriteSourceFiles(paths, options.write, rewriteImage)) {
|
|
81
|
-
if (result.error !== void 0) {
|
|
82
|
-
report.failures.push({
|
|
83
|
-
file: path,
|
|
84
|
-
message: result.error
|
|
85
|
-
});
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
for (const at of result.skipped) report.skipped.push({
|
|
89
|
-
file: path,
|
|
90
|
-
...at
|
|
91
|
-
});
|
|
92
|
-
if (result.changed === 0) continue;
|
|
93
|
-
report.files += 1;
|
|
94
|
-
report.changed += result.changed;
|
|
95
|
-
}
|
|
96
|
-
return report;
|
|
97
|
-
}
|
|
98
|
-
//#endregion
|
|
99
|
-
export { runImage };
|
package/dist/locale-CfZalwmA.mjs
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*! © 2025-2026 AND YOU CREATE SAS (RCS Paris 940 190 614). Proprietary — see LICENSE (Standards SDK License 1.0). */
|
|
3
|
-
import { i as rewriteSourceFiles, n as parseSourceFile, t as applyEdits } from "./source-files-D2Bdfvhx.mjs";
|
|
4
|
-
import ts from "typescript";
|
|
5
|
-
//#region src/codemod/locale.ts
|
|
6
|
-
/** Where the English values went once `DEFAULT_*_TRANSLATIONS` left the package roots. */
|
|
7
|
-
const EN_ENTRY = "@standards/react/locales/en";
|
|
8
|
-
const FORMER_HOMES = /* @__PURE__ */ new Set([
|
|
9
|
-
"@standards/react",
|
|
10
|
-
"@standards/ui",
|
|
11
|
-
EN_ENTRY
|
|
12
|
-
]);
|
|
13
|
-
const LOCALE_ENTRY = /^@standards\/react\/locales\/(en|fr)$/;
|
|
14
|
-
const RENAMED = { EN_SETTINGS_DIALOG_TRANSLATIONS: "EN_ROLES_SETTINGS_TRANSLATIONS" };
|
|
15
|
-
/** A whole dictionary, by its exported name, and the locale it stands for. */
|
|
16
|
-
const DICTIONARIES = {
|
|
17
|
-
EN_TRANSLATIONS: "en",
|
|
18
|
-
FR_TRANSLATIONS: "fr"
|
|
19
|
-
};
|
|
20
|
-
/** The `@standards/react/locales/en` name of a removed or renamed export. */
|
|
21
|
-
function englishName(name) {
|
|
22
|
-
const match = /^DEFAULT_([A-Z_]*)TRANSLATIONS$/.exec(name);
|
|
23
|
-
return match ? `EN_${match[1]}TRANSLATIONS` : RENAMED[name];
|
|
24
|
-
}
|
|
25
|
-
/** `translations: X` or `translations={X}`, with the expression it passes. */
|
|
26
|
-
function translationsValue(node) {
|
|
27
|
-
if (ts.isPropertyAssignment(node) && node.name.getText() === "translations") return {
|
|
28
|
-
value: node.initializer,
|
|
29
|
-
jsx: false
|
|
30
|
-
};
|
|
31
|
-
if (ts.isJsxAttribute(node) && node.name.getText() === "translations" && node.initializer !== void 0 && ts.isJsxExpression(node.initializer) && node.initializer.expression !== void 0) return {
|
|
32
|
-
value: node.initializer.expression,
|
|
33
|
-
jsx: true
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
/** An identifier that reads a binding: not a property name, not an import specifier. */
|
|
37
|
-
function isReference(node) {
|
|
38
|
-
const { parent } = node;
|
|
39
|
-
if (ts.isPropertyAccessExpression(parent)) return parent.expression === node;
|
|
40
|
-
if (ts.isPropertyAssignment(parent) || ts.isPropertySignature(parent)) return parent.name !== node;
|
|
41
|
-
if (ts.isExportSpecifier(parent)) {
|
|
42
|
-
if (parent.parent.parent.moduleSpecifier !== void 0) return false;
|
|
43
|
-
return (parent.propertyName ?? parent.name) === node;
|
|
44
|
-
}
|
|
45
|
-
return !ts.isImportSpecifier(parent);
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* The text that reads `renamed` where `node` stood, keeping what the old name
|
|
49
|
-
* also spelled: a shorthand property's key, a re-export's exported name.
|
|
50
|
-
*/
|
|
51
|
-
function renamedReference(node, renamed) {
|
|
52
|
-
const { parent } = node;
|
|
53
|
-
if (ts.isShorthandPropertyAssignment(parent)) return `${node.text}: ${renamed}`;
|
|
54
|
-
if (ts.isExportSpecifier(parent) && parent.propertyName === void 0) return `${renamed} as ${node.text}`;
|
|
55
|
-
return renamed;
|
|
56
|
-
}
|
|
57
|
-
/** One import declaration, written back with the bindings that stay in each module. */
|
|
58
|
-
function importDeclaration(node, specifier, stay, go) {
|
|
59
|
-
const clause = node.importClause;
|
|
60
|
-
const typeOnly = clause?.isTypeOnly ? " type" : "";
|
|
61
|
-
const defaultName = clause?.name?.text;
|
|
62
|
-
const line = (names, from, withDefault) => {
|
|
63
|
-
const head = [withDefault ? defaultName : void 0, names.length > 0 ? `{ ${names.join(", ")} }` : void 0].filter((part) => part !== void 0).join(", ");
|
|
64
|
-
return head === "" ? "" : `import${typeOnly} ${head} from "${from}";`;
|
|
65
|
-
};
|
|
66
|
-
if (specifier === EN_ENTRY) return line([...stay, ...go], EN_ENTRY, true);
|
|
67
|
-
if (stay.length === 0 && defaultName === void 0) return line(go, EN_ENTRY, false);
|
|
68
|
-
return [line(stay, specifier, true), line(go, EN_ENTRY, false)].filter(Boolean).join("\n");
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Moves `DEFAULT_*_TRANSLATIONS` imports to `EN_*` from `@standards/react/locales/en`,
|
|
72
|
-
* and turns a whole dictionary passed as `translations` into `locale`.
|
|
73
|
-
*/
|
|
74
|
-
function rewriteLocale(text, fileName) {
|
|
75
|
-
const { file, error } = parseSourceFile(text, fileName);
|
|
76
|
-
if (error !== void 0) return {
|
|
77
|
-
output: text,
|
|
78
|
-
changed: 0,
|
|
79
|
-
skipped: [],
|
|
80
|
-
error
|
|
81
|
-
};
|
|
82
|
-
const edits = [];
|
|
83
|
-
const skipped = [];
|
|
84
|
-
let changed = 0;
|
|
85
|
-
/** Local name → the `EN_*` name its references take. */
|
|
86
|
-
const renames = /* @__PURE__ */ new Map();
|
|
87
|
-
/** Local name of a whole dictionary → its locale. */
|
|
88
|
-
const dictionaries = /* @__PURE__ */ new Map();
|
|
89
|
-
/** Each import naming one of these exports, rewritten once its references are counted. */
|
|
90
|
-
const imports = [];
|
|
91
|
-
const references = /* @__PURE__ */ new Map();
|
|
92
|
-
const replaced = /* @__PURE__ */ new Map();
|
|
93
|
-
for (const node of file.statements) {
|
|
94
|
-
if (!(ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier))) continue;
|
|
95
|
-
const specifier = node.moduleSpecifier.text;
|
|
96
|
-
const bindings = node.importClause?.namedBindings;
|
|
97
|
-
if (bindings === void 0 || !ts.isNamedImports(bindings)) continue;
|
|
98
|
-
const entry = {
|
|
99
|
-
node,
|
|
100
|
-
specifier,
|
|
101
|
-
stay: [],
|
|
102
|
-
go: []
|
|
103
|
-
};
|
|
104
|
-
let relevant = false;
|
|
105
|
-
for (const element of bindings.elements) {
|
|
106
|
-
const imported = (element.propertyName ?? element.name).text;
|
|
107
|
-
const local = element.name.text;
|
|
108
|
-
const english = FORMER_HOMES.has(specifier) ? englishName(imported) : void 0;
|
|
109
|
-
if (english === void 0) entry.stay.push({
|
|
110
|
-
local,
|
|
111
|
-
text: element.getText(file)
|
|
112
|
-
});
|
|
113
|
-
else if (element.propertyName !== void 0) entry.go.push({
|
|
114
|
-
local,
|
|
115
|
-
text: `${element.isTypeOnly ? "type " : ""}${english} as ${local}`
|
|
116
|
-
});
|
|
117
|
-
else {
|
|
118
|
-
renames.set(local, english);
|
|
119
|
-
entry.go.push({
|
|
120
|
-
local,
|
|
121
|
-
text: `${element.isTypeOnly ? "type " : ""}${english}`
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
const exported = english ?? imported;
|
|
125
|
-
if (exported in DICTIONARIES && (english !== void 0 || LOCALE_ENTRY.test(specifier))) {
|
|
126
|
-
dictionaries.set(local, DICTIONARIES[exported]);
|
|
127
|
-
relevant = true;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
changed += entry.go.length;
|
|
131
|
-
if (entry.go.length > 0 || relevant) imports.push(entry);
|
|
132
|
-
}
|
|
133
|
-
function visit(node) {
|
|
134
|
-
if (ts.isImportDeclaration(node)) return;
|
|
135
|
-
const site = translationsValue(node);
|
|
136
|
-
if (site !== void 0) {
|
|
137
|
-
const name = ts.isIdentifier(site.value) ? site.value.text : void 0;
|
|
138
|
-
const locale = name === void 0 ? void 0 : dictionaries.get(name);
|
|
139
|
-
if (name !== void 0 && locale !== void 0) {
|
|
140
|
-
const text = site.jsx ? `locale="${locale}"` : `locale: "${locale}"`;
|
|
141
|
-
edits.push({
|
|
142
|
-
start: node.getStart(file),
|
|
143
|
-
end: node.getEnd(),
|
|
144
|
-
text
|
|
145
|
-
});
|
|
146
|
-
replaced.set(name, (replaced.get(name) ?? 0) + 1);
|
|
147
|
-
references.set(name, (references.get(name) ?? 0) + 1);
|
|
148
|
-
changed += 1;
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
if (mentions(site.value, dictionaries)) {
|
|
152
|
-
const { line, character } = file.getLineAndCharacterOfPosition(node.getStart(file));
|
|
153
|
-
skipped.push({
|
|
154
|
-
line: line + 1,
|
|
155
|
-
column: character + 1
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
if (ts.isIdentifier(node) && isReference(node)) {
|
|
160
|
-
if (dictionaries.has(node.text)) references.set(node.text, (references.get(node.text) ?? 0) + 1);
|
|
161
|
-
const renamed = renames.get(node.text);
|
|
162
|
-
if (renamed !== void 0) {
|
|
163
|
-
edits.push({
|
|
164
|
-
start: node.getStart(file),
|
|
165
|
-
end: node.getEnd(),
|
|
166
|
-
text: renamedReference(node, renamed)
|
|
167
|
-
});
|
|
168
|
-
changed += 1;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
ts.forEachChild(node, visit);
|
|
172
|
-
}
|
|
173
|
-
visit(file);
|
|
174
|
-
const unused = new Set([...dictionaries.keys()].filter((name) => {
|
|
175
|
-
const uses = replaced.get(name) ?? 0;
|
|
176
|
-
return uses > 0 && uses === references.get(name);
|
|
177
|
-
}));
|
|
178
|
-
for (const { node, specifier, stay, go } of imports) {
|
|
179
|
-
const kept = (bindings) => bindings.filter(({ local }) => !unused.has(local)).map(({ text }) => text);
|
|
180
|
-
const keptStay = kept(stay);
|
|
181
|
-
const keptGo = kept(go);
|
|
182
|
-
if (keptGo.length === 0 && go.length === 0 && keptStay.length === stay.length) continue;
|
|
183
|
-
const text = importDeclaration(node, specifier, keptStay, keptGo);
|
|
184
|
-
const end = node.getEnd();
|
|
185
|
-
edits.push({
|
|
186
|
-
start: node.getStart(file),
|
|
187
|
-
end: text === "" && file.text.charAt(end) === "\n" ? end + 1 : end,
|
|
188
|
-
text
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
return {
|
|
192
|
-
output: applyEdits(text, edits),
|
|
193
|
-
changed,
|
|
194
|
-
skipped
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
function mentions(node, names) {
|
|
198
|
-
if (ts.isIdentifier(node) && names.has(node.text)) return true;
|
|
199
|
-
return ts.forEachChild(node, (child) => mentions(child, names) || void 0) === true;
|
|
200
|
-
}
|
|
201
|
-
/** Walks `paths`, rewrites every TS or JS file, writes back when `write` is set. */
|
|
202
|
-
async function runLocale(paths, options) {
|
|
203
|
-
const report = {
|
|
204
|
-
files: 0,
|
|
205
|
-
changed: 0,
|
|
206
|
-
skipped: [],
|
|
207
|
-
failures: []
|
|
208
|
-
};
|
|
209
|
-
for (const { path, result } of await rewriteSourceFiles(paths, options.write, rewriteLocale)) {
|
|
210
|
-
if (result.error !== void 0) {
|
|
211
|
-
report.failures.push({
|
|
212
|
-
file: path,
|
|
213
|
-
message: result.error
|
|
214
|
-
});
|
|
215
|
-
continue;
|
|
216
|
-
}
|
|
217
|
-
for (const at of result.skipped) report.skipped.push({
|
|
218
|
-
file: path,
|
|
219
|
-
...at
|
|
220
|
-
});
|
|
221
|
-
if (result.changed === 0) continue;
|
|
222
|
-
report.files += 1;
|
|
223
|
-
report.changed += result.changed;
|
|
224
|
-
}
|
|
225
|
-
return report;
|
|
226
|
-
}
|
|
227
|
-
//#endregion
|
|
228
|
-
export { runLocale };
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*! © 2025-2026 AND YOU CREATE SAS (RCS Paris 940 190 614). Proprietary — see LICENSE (Standards SDK License 1.0). */
|
|
3
|
-
import { i as rewriteSourceFiles, n as parseSourceFile, t as applyEdits } from "./source-files-D2Bdfvhx.mjs";
|
|
4
|
-
import ts from "typescript";
|
|
5
|
-
import { PALETTE_HUES } from "@standards/constants";
|
|
6
|
-
//#region src/codemod/palette.ts
|
|
7
|
-
/** Previous Tailwind colour id → nearest Standards palette id (same table as the SQL migration). */
|
|
8
|
-
const OLD_TO_NEW = {
|
|
9
|
-
gray: "stone",
|
|
10
|
-
slate: "stone",
|
|
11
|
-
red: "brick",
|
|
12
|
-
rose: "brick",
|
|
13
|
-
orange: "terra",
|
|
14
|
-
amber: "ochre",
|
|
15
|
-
yellow: "ochre",
|
|
16
|
-
lime: "moss",
|
|
17
|
-
green: "sage",
|
|
18
|
-
emerald: "sage",
|
|
19
|
-
teal: "lagoon",
|
|
20
|
-
cyan: "lagoon",
|
|
21
|
-
blue: "ink",
|
|
22
|
-
sky: "ink",
|
|
23
|
-
indigo: "iris",
|
|
24
|
-
violet: "iris",
|
|
25
|
-
purple: "iris",
|
|
26
|
-
pink: "peony",
|
|
27
|
-
fuchsia: "peony"
|
|
28
|
-
};
|
|
29
|
-
const NEUTRAL = "stone";
|
|
30
|
-
/** Fallback order doubles as the tie-break: earlier wins. */
|
|
31
|
-
const HUE_IDS = Object.keys(PALETTE_HUES);
|
|
32
|
-
const PALETTE_IDS = /* @__PURE__ */ new Set([NEUTRAL, ...HUE_IDS]);
|
|
33
|
-
function isStringLike(node) {
|
|
34
|
-
return node !== void 0 && (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node));
|
|
35
|
-
}
|
|
36
|
-
function hueDistance(x, y) {
|
|
37
|
-
const delta = Math.abs(x - y) % 360;
|
|
38
|
-
return Math.min(delta, 360 - delta);
|
|
39
|
-
}
|
|
40
|
-
/** Smallest circular hue distance wins; a tie goes to the earlier id of the palette. */
|
|
41
|
-
function nearestFree(target, taken) {
|
|
42
|
-
const hue = PALETTE_HUES[target];
|
|
43
|
-
if (hue === void 0) return void 0;
|
|
44
|
-
let best;
|
|
45
|
-
let bestDistance = Number.POSITIVE_INFINITY;
|
|
46
|
-
for (const id of HUE_IDS) {
|
|
47
|
-
if (taken.has(id)) continue;
|
|
48
|
-
const distance = hueDistance(hue, PALETTE_HUES[id]);
|
|
49
|
-
if (distance < bestDistance) {
|
|
50
|
-
best = id;
|
|
51
|
-
bestDistance = distance;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return best;
|
|
55
|
-
}
|
|
56
|
-
function propertyName(property) {
|
|
57
|
-
if (!(ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property))) return void 0;
|
|
58
|
-
const { name } = property;
|
|
59
|
-
return ts.isIdentifier(name) || ts.isStringLiteral(name) ? name.text : void 0;
|
|
60
|
-
}
|
|
61
|
-
/** The string literal holding the `color` of an object literal, if it has one. */
|
|
62
|
-
function colorLiteral(object) {
|
|
63
|
-
if (!ts.isObjectLiteralExpression(object)) return void 0;
|
|
64
|
-
for (const property of object.properties) if (ts.isPropertyAssignment(property) && propertyName(property) === "color") return isStringLike(property.initializer) ? property.initializer : void 0;
|
|
65
|
-
}
|
|
66
|
-
/** Every string literal that carries a colour id: `color` values, `variant` attributes, `.color()` arguments. */
|
|
67
|
-
function colourLiterals(file) {
|
|
68
|
-
const found = [];
|
|
69
|
-
function visit(node) {
|
|
70
|
-
if (ts.isPropertyAssignment(node) && propertyName(node) === "color") {
|
|
71
|
-
if (isStringLike(node.initializer)) found.push(node.initializer);
|
|
72
|
-
} else if (ts.isJsxAttribute(node) && node.name.getText(file) === "variant") {
|
|
73
|
-
const value = node.initializer;
|
|
74
|
-
if (value && ts.isStringLiteral(value)) found.push(value);
|
|
75
|
-
else if (value && ts.isJsxExpression(value) && isStringLike(value.expression)) found.push(value.expression);
|
|
76
|
-
} else if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "color" && isStringLike(node.arguments[0])) found.push(node.arguments[0]);
|
|
77
|
-
ts.forEachChild(node, visit);
|
|
78
|
-
}
|
|
79
|
-
visit(file);
|
|
80
|
-
return found;
|
|
81
|
-
}
|
|
82
|
-
/** Rewrites the colour ids of one source file to the Standards palette. */
|
|
83
|
-
function rewritePalette(text, fileName) {
|
|
84
|
-
const { file, error } = parseSourceFile(text, fileName);
|
|
85
|
-
if (error !== void 0) return {
|
|
86
|
-
output: text,
|
|
87
|
-
changed: 0,
|
|
88
|
-
error
|
|
89
|
-
};
|
|
90
|
-
const replacements = /* @__PURE__ */ new Map();
|
|
91
|
-
for (const literal of colourLiterals(file)) {
|
|
92
|
-
const mapped = OLD_TO_NEW[literal.text];
|
|
93
|
-
if (mapped !== void 0) replacements.set(literal, mapped);
|
|
94
|
-
}
|
|
95
|
-
function resolveArray(array) {
|
|
96
|
-
const options = array.elements.map(colorLiteral).filter((literal) => literal !== void 0);
|
|
97
|
-
const taken = new Set(options.map((o) => o.text).filter((id) => PALETTE_IDS.has(id)));
|
|
98
|
-
for (const option of options) {
|
|
99
|
-
const mapped = replacements.get(option);
|
|
100
|
-
if (mapped === void 0) continue;
|
|
101
|
-
const id = taken.has(mapped) ? nearestFree(mapped, taken) ?? mapped : mapped;
|
|
102
|
-
replacements.set(option, id);
|
|
103
|
-
taken.add(id);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
function visitArrays(node) {
|
|
107
|
-
if (ts.isArrayLiteralExpression(node)) resolveArray(node);
|
|
108
|
-
ts.forEachChild(node, visitArrays);
|
|
109
|
-
}
|
|
110
|
-
visitArrays(file);
|
|
111
|
-
const edits = [...replacements.entries()].filter(([literal, id]) => literal.text !== id).map(([literal, id]) => ({
|
|
112
|
-
start: literal.getStart(file) + 1,
|
|
113
|
-
end: literal.getEnd() - 1,
|
|
114
|
-
text: id
|
|
115
|
-
}));
|
|
116
|
-
return {
|
|
117
|
-
output: applyEdits(text, edits),
|
|
118
|
-
changed: edits.length
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
/** Walks `paths`, rewrites every TS or JS file, writes back when `write` is set. */
|
|
122
|
-
async function runPalette(paths, options) {
|
|
123
|
-
const report = {
|
|
124
|
-
files: 0,
|
|
125
|
-
changed: 0,
|
|
126
|
-
rewritten: [],
|
|
127
|
-
failures: []
|
|
128
|
-
};
|
|
129
|
-
for (const { path, result } of await rewriteSourceFiles(paths, options.write, rewritePalette)) {
|
|
130
|
-
if (result.error !== void 0) {
|
|
131
|
-
report.failures.push({
|
|
132
|
-
file: path,
|
|
133
|
-
message: result.error
|
|
134
|
-
});
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
if (result.changed === 0) continue;
|
|
138
|
-
report.files += 1;
|
|
139
|
-
report.changed += result.changed;
|
|
140
|
-
report.rewritten.push({
|
|
141
|
-
file: path,
|
|
142
|
-
changed: result.changed
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
return report;
|
|
146
|
-
}
|
|
147
|
-
//#endregion
|
|
148
|
-
export { runPalette };
|
package/dist/scopes-Bqw1v3wB.mjs
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*! © 2025-2026 AND YOU CREATE SAS (RCS Paris 940 190 614). Proprietary — see LICENSE (Standards SDK License 1.0). */
|
|
3
|
-
import { r as rewriteFiles } from "./source-files-D2Bdfvhx.mjs";
|
|
4
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
5
|
-
import { basename, join } from "node:path";
|
|
6
|
-
//#region src/codemod/scopes.ts
|
|
7
|
-
/**
|
|
8
|
-
* Every package that left `@stndrds` for `@standards`: the restricted ones
|
|
9
|
-
* (now on the licensed registry only) and the public ones (now on npmjs and
|
|
10
|
-
* the licensed registry). A historical list: packages created later never had
|
|
11
|
-
* an `@stndrds` name.
|
|
12
|
-
*/
|
|
13
|
-
const RENAMED_PACKAGES = [
|
|
14
|
-
"adapter-cache",
|
|
15
|
-
"adapter-kernel",
|
|
16
|
-
"adapter-meilisearch",
|
|
17
|
-
"adapter-nestjs",
|
|
18
|
-
"adapter-oidc-provider",
|
|
19
|
-
"adapter-postgres",
|
|
20
|
-
"adapter-posthog",
|
|
21
|
-
"adapter-redis",
|
|
22
|
-
"adapter-supabase",
|
|
23
|
-
"adapter-vercel-sandbox",
|
|
24
|
-
"auth",
|
|
25
|
-
"blocks",
|
|
26
|
-
"cli",
|
|
27
|
-
"client",
|
|
28
|
-
"constants",
|
|
29
|
-
"ds",
|
|
30
|
-
"engine",
|
|
31
|
-
"fonts",
|
|
32
|
-
"react",
|
|
33
|
-
"runtime",
|
|
34
|
-
"schema",
|
|
35
|
-
"ui"
|
|
36
|
-
];
|
|
37
|
-
const SCOPE_REGISTRY_LINE = `@standards:registry=https://registry.standards.run/`;
|
|
38
|
-
/**
|
|
39
|
-
* The key line belongs in the user-level `~/.npmrc`, never the project one:
|
|
40
|
-
* pnpm does not expand environment variables in registry credentials read
|
|
41
|
-
* from a project `.npmrc`, so `${STANDARDS_TOKEN}` there reaches the
|
|
42
|
-
* registry as no key at all (401). Earlier runs of this codemod wrote it.
|
|
43
|
-
*/
|
|
44
|
-
const PROJECT_AUTH_LINE = /^\s*\/\/registry\.standards\.run\/:_authToken=\$\{[^}]+\}\s*$/;
|
|
45
|
-
/** Public on npmjs too: a project using only these needs no licence and no registry line. */
|
|
46
|
-
const PUBLIC_PACKAGES = /* @__PURE__ */ new Set([
|
|
47
|
-
"cli",
|
|
48
|
-
"client",
|
|
49
|
-
"constants",
|
|
50
|
-
"schema"
|
|
51
|
-
]);
|
|
52
|
-
const LICENSED_NAME = new RegExp(`@standards/(${RENAMED_PACKAGES.filter((name) => !PUBLIC_PACKAGES.has(name)).join("|")})(?![a-z0-9-])`);
|
|
53
|
-
const OLD_NAME = new RegExp(`@stndrds/(${RENAMED_PACKAGES.join("|")})(?![a-z0-9-])`, "g");
|
|
54
|
-
/** Code, styles, manifests, workspace config and agent guidance (AGENTS.md, CLAUDE.md). */
|
|
55
|
-
const REWRITTEN_FILE = /\.(?:[cm]?tsx?|[cm]?jsx?|css|scss|sass|less|json|jsonc|ya?ml|mdx?)$/;
|
|
56
|
-
/** Lockfiles are regenerated by the install that follows, never edited. */
|
|
57
|
-
const LOCKFILES = /* @__PURE__ */ new Set([
|
|
58
|
-
"pnpm-lock.yaml",
|
|
59
|
-
"package-lock.json",
|
|
60
|
-
"yarn.lock",
|
|
61
|
-
"bun.lock"
|
|
62
|
-
]);
|
|
63
|
-
/** Renames every reference to one of our packages from `@stndrds/<name>` to `@standards/<name>`. */
|
|
64
|
-
function rewriteScopes(source) {
|
|
65
|
-
let changed = 0;
|
|
66
|
-
const output = source.replace(OLD_NAME, (_match, name) => {
|
|
67
|
-
changed += 1;
|
|
68
|
-
return `@standards/${name}`;
|
|
69
|
-
});
|
|
70
|
-
return {
|
|
71
|
-
output,
|
|
72
|
-
changed,
|
|
73
|
-
licensed: LICENSED_NAME.test(output)
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Project `.npmrc` pointing `@standards` at the licensed registry: a different
|
|
78
|
-
* `@standards:registry` is replaced in place, an env-variable key line for the
|
|
79
|
-
* registry is removed (it never worked there), every other line is kept.
|
|
80
|
-
*/
|
|
81
|
-
function ensureScopesNpmrc(text) {
|
|
82
|
-
const lines = text.split("\n");
|
|
83
|
-
if (lines.at(-1) === "") lines.pop();
|
|
84
|
-
const output = lines.filter((line) => !PROJECT_AUTH_LINE.test(line)).map((line) => line.trim().startsWith("@standards:registry=") ? SCOPE_REGISTRY_LINE : line);
|
|
85
|
-
if (!output.includes(SCOPE_REGISTRY_LINE)) output.push(SCOPE_REGISTRY_LINE);
|
|
86
|
-
return `${output.join("\n")}\n`;
|
|
87
|
-
}
|
|
88
|
-
function isRewritten(path) {
|
|
89
|
-
return REWRITTEN_FILE.test(path) && !LOCKFILES.has(basename(path));
|
|
90
|
-
}
|
|
91
|
-
async function readOptional(path) {
|
|
92
|
-
try {
|
|
93
|
-
return await readFile(path, "utf8");
|
|
94
|
-
} catch {
|
|
95
|
-
return "";
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
async function runScopes(paths, options) {
|
|
99
|
-
const report = {
|
|
100
|
-
files: 0,
|
|
101
|
-
changed: 0,
|
|
102
|
-
licensed: false
|
|
103
|
-
};
|
|
104
|
-
const results = await rewriteFiles(paths, isRewritten, options.write, rewriteScopes);
|
|
105
|
-
for (const { result } of results) {
|
|
106
|
-
if (result.licensed) report.licensed = true;
|
|
107
|
-
if (result.changed === 0) continue;
|
|
108
|
-
report.files += 1;
|
|
109
|
-
report.changed += result.changed;
|
|
110
|
-
}
|
|
111
|
-
if (!report.licensed) return report;
|
|
112
|
-
const npmrcPath = join(options.root, ".npmrc");
|
|
113
|
-
const current = await readOptional(npmrcPath);
|
|
114
|
-
const next = ensureScopesNpmrc(current);
|
|
115
|
-
if (next !== current) {
|
|
116
|
-
report.npmrc = npmrcPath;
|
|
117
|
-
if (options.write) await writeFile(npmrcPath, next);
|
|
118
|
-
}
|
|
119
|
-
return report;
|
|
120
|
-
}
|
|
121
|
-
//#endregion
|
|
122
|
-
export { runScopes };
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*! © 2025-2026 AND YOU CREATE SAS (RCS Paris 940 190 614). Proprietary — see LICENSE (Standards SDK License 1.0). */
|
|
3
|
-
import { readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import ts from "typescript";
|
|
6
|
-
//#region src/codemod/source-files.ts
|
|
7
|
-
const IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
8
|
-
"node_modules",
|
|
9
|
-
"dist",
|
|
10
|
-
".next",
|
|
11
|
-
".turbo",
|
|
12
|
-
".git",
|
|
13
|
-
"coverage"
|
|
14
|
-
]);
|
|
15
|
-
const SOURCE_FILE = /\.(?:[cm]?tsx?|[cm]?jsx?)$/;
|
|
16
|
-
const DECLARATION_FILE = /\.d\.[cm]?ts$/;
|
|
17
|
-
function scriptKindOf(fileName) {
|
|
18
|
-
if (/\.tsx$/.test(fileName)) return ts.ScriptKind.TSX;
|
|
19
|
-
if (/\.jsx$/.test(fileName)) return ts.ScriptKind.JSX;
|
|
20
|
-
if (/\.[cm]?js$/.test(fileName)) return ts.ScriptKind.JS;
|
|
21
|
-
return ts.ScriptKind.TS;
|
|
22
|
-
}
|
|
23
|
-
/** One TS or JS file as a tree, with its first parse error if it has one. */
|
|
24
|
-
function parseSourceFile(text, fileName) {
|
|
25
|
-
const file = ts.createSourceFile(fileName, text, ts.ScriptTarget.Latest, true, scriptKindOf(fileName));
|
|
26
|
-
const first = file.parseDiagnostics?.[0];
|
|
27
|
-
if (first === void 0) return { file };
|
|
28
|
-
return {
|
|
29
|
-
file,
|
|
30
|
-
error: `${fileName}: cannot parse (${ts.flattenDiagnosticMessageText(first.messageText, " ")})`
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
async function collectInto(path, accept, into) {
|
|
34
|
-
if ((await stat(path)).isFile()) {
|
|
35
|
-
if (accept(path)) into.push(path);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
for (const entry of await readdir(path)) if (!IGNORED_DIRS.has(entry)) await collectInto(join(path, entry), accept, into);
|
|
39
|
-
}
|
|
40
|
-
function isSourceFile(path) {
|
|
41
|
-
return SOURCE_FILE.test(path) && !DECLARATION_FILE.test(path);
|
|
42
|
-
}
|
|
43
|
-
/** Every file under `paths` that `accept` takes, build output and dependencies left out. */
|
|
44
|
-
async function collectFiles(paths, accept) {
|
|
45
|
-
const files = [];
|
|
46
|
-
for (const path of paths) await collectInto(path, accept, files);
|
|
47
|
-
return files;
|
|
48
|
-
}
|
|
49
|
-
/** Applies non-overlapping edits to `text`, last offset first so earlier ones stay valid. */
|
|
50
|
-
function applyEdits(text, edits) {
|
|
51
|
-
let output = text;
|
|
52
|
-
for (const edit of [...edits].sort((x, y) => y.start - x.start)) output = output.slice(0, edit.start) + edit.text + output.slice(edit.end);
|
|
53
|
-
return output;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Runs `rewrite` on every source file under `paths`, writes back the ones it
|
|
57
|
-
* changed when `write` is set, and hands every result back for the report.
|
|
58
|
-
*/
|
|
59
|
-
function rewriteSourceFiles(paths, write, rewrite) {
|
|
60
|
-
return rewriteFiles(paths, isSourceFile, write, rewrite);
|
|
61
|
-
}
|
|
62
|
-
/** `rewriteSourceFiles` over the files `accept` takes, whatever their language. */
|
|
63
|
-
async function rewriteFiles(paths, accept, write, rewrite) {
|
|
64
|
-
const results = [];
|
|
65
|
-
for (const path of await collectFiles(paths, accept)) {
|
|
66
|
-
const result = rewrite(await readFile(path, "utf8"), path);
|
|
67
|
-
if (write && result.error === void 0 && result.changed > 0) await writeFile(path, result.output);
|
|
68
|
-
results.push({
|
|
69
|
-
path,
|
|
70
|
-
result
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
return results;
|
|
74
|
-
}
|
|
75
|
-
//#endregion
|
|
76
|
-
export { rewriteSourceFiles as i, parseSourceFile as n, rewriteFiles as r, applyEdits as t };
|