@panneau/codemods 0.0.0-stage → 5.0.0-alpha.10
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 +28 -2
- package/bin/panneau-codemods.js +5 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +62 -0
- package/dist/cli.js.map +1 -0
- package/dist/context.d.ts +80 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +117 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/mappings.d.ts +49 -0
- package/dist/mappings.d.ts.map +1 -0
- package/dist/mappings.js +574 -0
- package/dist/mappings.js.map +1 -0
- package/dist/names.d.ts +5 -0
- package/dist/names.d.ts.map +1 -0
- package/dist/names.js +13 -0
- package/dist/names.js.map +1 -0
- package/dist/run.d.ts +23 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +65 -0
- package/dist/run.js.map +1 -0
- package/dist/transform.d.ts +28 -0
- package/dist/transform.d.ts.map +1 -0
- package/dist/transform.js +192 -0
- package/dist/transform.js.map +1 -0
- package/dist/transforms/bootstrap.d.ts +6 -0
- package/dist/transforms/bootstrap.d.ts.map +1 -0
- package/dist/transforms/bootstrap.js +65 -0
- package/dist/transforms/bootstrap.js.map +1 -0
- package/dist/transforms/entry.d.ts +15 -0
- package/dist/transforms/entry.d.ts.map +1 -0
- package/dist/transforms/entry.js +239 -0
- package/dist/transforms/entry.js.map +1 -0
- package/dist/transforms/fieldEntries.d.ts +20 -0
- package/dist/transforms/fieldEntries.d.ts.map +1 -0
- package/dist/transforms/fieldEntries.js +238 -0
- package/dist/transforms/fieldEntries.js.map +1 -0
- package/dist/transforms/fields.d.ts +3 -0
- package/dist/transforms/fields.d.ts.map +1 -0
- package/dist/transforms/fields.js +241 -0
- package/dist/transforms/fields.js.map +1 -0
- package/dist/transforms/imports.d.ts +3 -0
- package/dist/transforms/imports.d.ts.map +1 -0
- package/dist/transforms/imports.js +60 -0
- package/dist/transforms/imports.js.map +1 -0
- package/package.json +44 -5
package/README.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @panneau/codemods
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Codemods that move Panneau 4 projects to Panneau 5: the app entry, imports and custom field components, with a report of what they can't rewrite.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx @panneau/codemods@alpha v4-to-v5 resources/js/panneau.tsx resources/js/components/Panneau.jsx resources/js/components/panneau --dry
|
|
7
|
+
npx @panneau/codemods@alpha v4-to-v5 resources/js/panneau.tsx resources/js/components/Panneau.jsx resources/js/components/panneau
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
`--dry` writes nothing and prints what would change, and every finding: what the codemods couldn't rewrite, and what needs a check. Without it, the files are rewritten (format them with Prettier afterwards), and each finding to fix by hand also gets a `// TODO(panneau-5): …` comment in its file. Running the codemods again changes nothing more, and lists what is left. `--json` prints the result as JSON.
|
|
11
|
+
|
|
12
|
+
The steps, and what each rewrite does, are in the migration guide: [Custom fields](../../docs/migration.md#custom-fields).
|
|
13
|
+
|
|
14
|
+
| Export | Content |
|
|
15
|
+
| ------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
16
|
+
| `@panneau/codemods` | `runCodemods()` (files on disk), `transformSources()` (sources in memory), `formatReport()` and `runCli()` |
|
|
17
|
+
| `panneau-codemods` | The command (`bin`) |
|
|
18
|
+
|
|
19
|
+
## Why jscodeshift
|
|
20
|
+
|
|
21
|
+
The codemods are built on [jscodeshift](https://github.com/facebook/jscodeshift), the tool of the React and Next.js codemods:
|
|
22
|
+
|
|
23
|
+
- **It keeps the code as it was written.** Recast reprints only the nodes a codemod changes, so a component keeps its formatting, comments and quotes around a rewritten import or prop.
|
|
24
|
+
- **One parser for the code of v4 projects.** Babel's `tsx` parser reads their `.jsx` with PropTypes and their `.tsx` alike.
|
|
25
|
+
- **No type checker needed.** The rewrites are about imports, JSX and props, which the syntax gives. v4 projects don't typecheck cleanly (props destructured outside of their interface), and ts-morph would bring a second TypeScript and its program for nothing.
|
|
26
|
+
|
|
27
|
+
The codemods read every file of a run before they rewrite any: the container of the app says which components are fields, and the entry of v5 gets the plugin made from the container.
|
|
28
|
+
|
|
29
|
+
The package layout, scripts and API reports are explained in [`docs/packages.md`](../../docs/packages.md).
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const USAGE = "Usage: panneau-codemods v4-to-v5 <paths...> [--dry] [--json]\n\nMoves the JS of a Panneau 4 project to Panneau 5: the container of the app becomes the plugin of the\nproject, custom field components get their entry, and imports of @panneau/* 4 are rewritten. What\ncan't be rewritten is reported, and marked with a // TODO(panneau-5) comment.\n\n <paths> Files and folders: the container of the app, its field components, and the entry\n written by `php artisan panneau:install --upgrade`. Folders are read recursively.\n --dry Report what would change, and write nothing.\n --json Print the result as JSON.";
|
|
2
|
+
/** Runs the command with its arguments. Returns the exit code. */
|
|
3
|
+
export declare function runCli(args: readonly string[], { cwd, log }?: {
|
|
4
|
+
cwd?: string;
|
|
5
|
+
log?: (text: string) => void;
|
|
6
|
+
}): Promise<number>;
|
|
7
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,KAAK,2nBASoB,CAAC;AAEvC,kEAAkE;AAClE,wBAAsB,MAAM,CACxB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,GAAmB,EAAE,GAAiB,EAAE,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAO,GAChG,OAAO,CAAC,MAAM,CAAC,CA6BjB"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { formatReport, runCodemods } from "./run.js";
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
//#region src/cli.ts
|
|
4
|
+
var USAGE = `Usage: panneau-codemods v4-to-v5 <paths...> [--dry] [--json]
|
|
5
|
+
|
|
6
|
+
Moves the JS of a Panneau 4 project to Panneau 5: the container of the app becomes the plugin of the
|
|
7
|
+
project, custom field components get their entry, and imports of @panneau/* 4 are rewritten. What
|
|
8
|
+
can't be rewritten is reported, and marked with a // TODO(panneau-5) comment.
|
|
9
|
+
|
|
10
|
+
<paths> Files and folders: the container of the app, its field components, and the entry
|
|
11
|
+
written by \`php artisan panneau:install --upgrade\`. Folders are read recursively.
|
|
12
|
+
--dry Report what would change, and write nothing.
|
|
13
|
+
--json Print the result as JSON.`;
|
|
14
|
+
/** Runs the command with its arguments. Returns the exit code. */
|
|
15
|
+
async function runCli(args, { cwd = process.cwd(), log = console.log } = {}) {
|
|
16
|
+
let parsed;
|
|
17
|
+
try {
|
|
18
|
+
parsed = parseArgs({
|
|
19
|
+
args: [...args],
|
|
20
|
+
allowPositionals: true,
|
|
21
|
+
options: {
|
|
22
|
+
dry: {
|
|
23
|
+
type: "boolean",
|
|
24
|
+
default: false
|
|
25
|
+
},
|
|
26
|
+
json: {
|
|
27
|
+
type: "boolean",
|
|
28
|
+
default: false
|
|
29
|
+
},
|
|
30
|
+
help: {
|
|
31
|
+
type: "boolean",
|
|
32
|
+
short: "h",
|
|
33
|
+
default: false
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
} catch (error) {
|
|
38
|
+
log(`${error instanceof Error ? error.message : String(error)}\n\n${USAGE}`);
|
|
39
|
+
return 2;
|
|
40
|
+
}
|
|
41
|
+
const { values, positionals } = parsed;
|
|
42
|
+
const [command, ...paths] = positionals;
|
|
43
|
+
if (values.help) {
|
|
44
|
+
log(USAGE);
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
if (command !== "v4-to-v5" || paths.length === 0) {
|
|
48
|
+
log(USAGE);
|
|
49
|
+
return 2;
|
|
50
|
+
}
|
|
51
|
+
const result = await runCodemods({
|
|
52
|
+
paths,
|
|
53
|
+
dry: values.dry,
|
|
54
|
+
cwd
|
|
55
|
+
});
|
|
56
|
+
log(values.json ? JSON.stringify(result, null, 2) : formatReport(result, { dry: values.dry }));
|
|
57
|
+
return result.findings.some((finding) => finding.rule === "parse") ? 1 : 0;
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
export { USAGE, runCli };
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["// The `panneau-codemods` command, for Node only: `bin/panneau-codemods.js` runs it.\nimport { parseArgs } from 'node:util';\n\nimport { formatReport, runCodemods } from './run';\n\nexport const USAGE = `Usage: panneau-codemods v4-to-v5 <paths...> [--dry] [--json]\n\nMoves the JS of a Panneau 4 project to Panneau 5: the container of the app becomes the plugin of the\nproject, custom field components get their entry, and imports of @panneau/* 4 are rewritten. What\ncan't be rewritten is reported, and marked with a // TODO(panneau-5) comment.\n\n <paths> Files and folders: the container of the app, its field components, and the entry\n written by \\`php artisan panneau:install --upgrade\\`. Folders are read recursively.\n --dry Report what would change, and write nothing.\n --json Print the result as JSON.`;\n\n/** Runs the command with its arguments. Returns the exit code. */\nexport async function runCli(\n args: readonly string[],\n { cwd = process.cwd(), log = console.log }: { cwd?: string; log?: (text: string) => void } = {},\n): Promise<number> {\n let parsed;\n try {\n parsed = parseArgs({\n args: [...args],\n allowPositionals: true,\n options: {\n dry: { type: 'boolean', default: false },\n json: { type: 'boolean', default: false },\n help: { type: 'boolean', short: 'h', default: false },\n },\n });\n } catch (error) {\n log(`${error instanceof Error ? error.message : String(error)}\\n\\n${USAGE}`);\n return 2;\n }\n const { values, positionals } = parsed;\n const [command, ...paths] = positionals;\n if (values.help) {\n log(USAGE);\n return 0;\n }\n if (command !== 'v4-to-v5' || paths.length === 0) {\n log(USAGE);\n return 2;\n }\n const result = await runCodemods({ paths, dry: values.dry, cwd });\n log(values.json ? JSON.stringify(result, null, 2) : formatReport(result, { dry: values.dry }));\n return result.findings.some((finding) => finding.rule === 'parse') ? 1 : 0;\n}\n"],"mappings":";;;AAKA,IAAa,QAAQ;;;;;;;;;;;AAYrB,eAAsB,OAClB,MACA,EAAE,MAAM,QAAQ,IAAI,GAAG,MAAM,QAAQ,QAAwD,CAAC,GAC/E;CACf,IAAI;CACJ,IAAI;EACA,SAAS,UAAU;GACf,MAAM,CAAC,GAAG,IAAI;GACd,kBAAkB;GAClB,SAAS;IACL,KAAK;KAAE,MAAM;KAAW,SAAS;IAAM;IACvC,MAAM;KAAE,MAAM;KAAW,SAAS;IAAM;IACxC,MAAM;KAAE,MAAM;KAAW,OAAO;KAAK,SAAS;IAAM;GACxD;EACJ,CAAC;CACL,SAAS,OAAO;EACZ,IAAI,GAAG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,MAAM,OAAO;EAC3E,OAAO;CACX;CACA,MAAM,EAAE,QAAQ,gBAAgB;CAChC,MAAM,CAAC,SAAS,GAAG,SAAS;CAC5B,IAAI,OAAO,MAAM;EACb,IAAI,KAAK;EACT,OAAO;CACX;CACA,IAAI,YAAY,cAAc,MAAM,WAAW,GAAG;EAC9C,IAAI,KAAK;EACT,OAAO;CACX;CACA,MAAM,SAAS,MAAM,YAAY;EAAE;EAAO,KAAK,OAAO;EAAK;CAAI,CAAC;CAChE,IAAI,OAAO,OAAO,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,aAAa,QAAQ,EAAE,KAAK,OAAO,IAAI,CAAC,CAAC;CAC7F,OAAO,OAAO,SAAS,MAAM,YAAY,QAAQ,SAAS,OAAO,IAAI,IAAI;AAC7E"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { ASTPath, Collection, ImportDeclaration, JSCodeshift } from 'jscodeshift';
|
|
2
|
+
/** Something a codemod couldn't rewrite, or that needs a check. */
|
|
3
|
+
export interface Finding {
|
|
4
|
+
/** Path of the file, relative to where the codemods ran. */
|
|
5
|
+
file: string;
|
|
6
|
+
/** Line in the file before the codemods, when there is one. */
|
|
7
|
+
line: number | null;
|
|
8
|
+
/** What it is about: `import`, `entry`, `field-component`, `bootstrap`… */
|
|
9
|
+
rule: string;
|
|
10
|
+
message: string;
|
|
11
|
+
}
|
|
12
|
+
/** What the codemods know about a file of the run, before they rewrite it. */
|
|
13
|
+
export interface FileInfo {
|
|
14
|
+
/** The file renders the app of v4: the codemods make it a plugin module. */
|
|
15
|
+
isContainer: boolean;
|
|
16
|
+
/** Modules of the `components` of the app, by v4 namespace (`fields`), as written. */
|
|
17
|
+
namespaces: ReadonlyMap<string, string>;
|
|
18
|
+
/** Re-exports of default exports: `export { default as Agency } from './Agency'`. */
|
|
19
|
+
defaultReExports: ReadonlyMap<string, string>;
|
|
20
|
+
/** Whether the file imports a module of `@panneau/*`. */
|
|
21
|
+
importsPanneau: boolean;
|
|
22
|
+
/** Whether the file has a default export. */
|
|
23
|
+
hasDefaultExport: boolean;
|
|
24
|
+
/** The name of the field entry the file exports, or will export. */
|
|
25
|
+
fieldEntry: string | null;
|
|
26
|
+
}
|
|
27
|
+
/** What a transform knows about the other files of the run. */
|
|
28
|
+
export interface Project {
|
|
29
|
+
/** The path of a module imported from a file of the run, when it is one too. */
|
|
30
|
+
resolve(from: string, specifier: string): string | null;
|
|
31
|
+
info(path: string): FileInfo | null;
|
|
32
|
+
/** Whether the default export of a file is registered as a field. */
|
|
33
|
+
isField(path: string): boolean;
|
|
34
|
+
/** Plugin modules made from v4 containers, for the entry of v5. */
|
|
35
|
+
pluginModules(): readonly string[];
|
|
36
|
+
}
|
|
37
|
+
export interface TransformApi {
|
|
38
|
+
j: JSCodeshift;
|
|
39
|
+
root: Collection;
|
|
40
|
+
/** Absolute path of the file. */
|
|
41
|
+
path: string;
|
|
42
|
+
/** Whether the file is TypeScript. */
|
|
43
|
+
typescript: boolean;
|
|
44
|
+
project: Project;
|
|
45
|
+
/**
|
|
46
|
+
* Reports a finding at a node. With `todo`, the statement of the node also gets a
|
|
47
|
+
* `// TODO(panneau-5): …` comment, so it can be found once the files are written.
|
|
48
|
+
*/
|
|
49
|
+
report(node: ASTPath | null, rule: string, message: string, options?: {
|
|
50
|
+
todo?: boolean;
|
|
51
|
+
}): void;
|
|
52
|
+
}
|
|
53
|
+
export declare const TODO_PREFIX = "TODO(panneau-5):";
|
|
54
|
+
/** Adds a `// TODO(panneau-5): …` comment over the statement of a node, once. */
|
|
55
|
+
export declare function addTodo(j: JSCodeshift, path: ASTPath, message: string): void;
|
|
56
|
+
/** The line of a node in the source, or of the closest node that has one. */
|
|
57
|
+
export declare function getLine(path: ASTPath | null): number | null;
|
|
58
|
+
/** The import declarations of a module. */
|
|
59
|
+
export declare function findImports(api: TransformApi, source: string): Collection<ImportDeclaration>;
|
|
60
|
+
/**
|
|
61
|
+
* Adds `import { name as local } from 'source'` to an import of the module, or in a new one.
|
|
62
|
+
* Types are imported with `type` in the list of names. Returns the local name.
|
|
63
|
+
*/
|
|
64
|
+
export declare function addNamedImport(api: TransformApi, source: string, name: string, options?: {
|
|
65
|
+
local?: string;
|
|
66
|
+
type?: boolean;
|
|
67
|
+
}): string;
|
|
68
|
+
/** Inserts an import of a package before the relative imports of the file, or after its imports. */
|
|
69
|
+
export declare function insertImport(api: TransformApi, declaration: ImportDeclaration): void;
|
|
70
|
+
/** A string for a JSX attribute, in double quotes as JSX has them. */
|
|
71
|
+
export declare function jsxString(j: JSCodeshift, value: string): import("ast-types").namedTypes.Literal;
|
|
72
|
+
/** Removes a specifier from an import, and the import when it has none left. */
|
|
73
|
+
export declare function removeSpecifier(api: TransformApi, path: ASTPath): void;
|
|
74
|
+
/** Removes an import, keeping the comments above it on the next statement. */
|
|
75
|
+
export declare function removeImport(api: TransformApi, path: ASTPath<ImportDeclaration>): void;
|
|
76
|
+
/** Whether a name is still used in the file, outside of imports. */
|
|
77
|
+
export declare function isUsed(api: TransformApi, name: string): boolean;
|
|
78
|
+
/** Removes the imports of names that are no longer used. */
|
|
79
|
+
export declare function removeUnusedImports(api: TransformApi, names: readonly string[]): void;
|
|
80
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
//#region src/context.ts
|
|
2
|
+
var TODO_PREFIX = "TODO(panneau-5):";
|
|
3
|
+
/** The statement (or declaration) a node belongs to, where comments can go. */
|
|
4
|
+
function getStatement(path) {
|
|
5
|
+
let current = path;
|
|
6
|
+
while (current !== null) {
|
|
7
|
+
const parent = current.parent;
|
|
8
|
+
const parentType = parent?.node.type;
|
|
9
|
+
if (parent === null || parentType === "Program" || parentType === "BlockStatement" || parentType === "ExportNamedDeclaration" || parentType === "ExportDefaultDeclaration") return parentType === "ExportNamedDeclaration" || parentType === "ExportDefaultDeclaration" ? parent : current;
|
|
10
|
+
current = parent;
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
/** Adds a `// TODO(panneau-5): …` comment over the statement of a node, once. */
|
|
15
|
+
function addTodo(j, path, message) {
|
|
16
|
+
const statement = getStatement(path);
|
|
17
|
+
if (statement === null) return;
|
|
18
|
+
const node = statement.node;
|
|
19
|
+
const text = ` ${TODO_PREFIX} ${message}`;
|
|
20
|
+
if ((node.comments ?? []).some((comment) => comment.value === text)) return;
|
|
21
|
+
node.comments = [...node.comments ?? [], j.commentLine(text, true, false)];
|
|
22
|
+
}
|
|
23
|
+
/** The line of a node in the source, or of the closest node that has one. */
|
|
24
|
+
function getLine(path) {
|
|
25
|
+
let current = path;
|
|
26
|
+
while (current !== null) {
|
|
27
|
+
const loc = current.node.loc;
|
|
28
|
+
if (loc) return loc.start.line;
|
|
29
|
+
current = current.parent;
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
/** The import declarations of a module. */
|
|
34
|
+
function findImports(api, source) {
|
|
35
|
+
return api.root.find(api.j.ImportDeclaration, { source: { value: source } });
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Adds `import { name as local } from 'source'` to an import of the module, or in a new one.
|
|
39
|
+
* Types are imported with `type` in the list of names. Returns the local name.
|
|
40
|
+
*/
|
|
41
|
+
function addNamedImport(api, source, name, options = {}) {
|
|
42
|
+
const { j } = api;
|
|
43
|
+
const local = options.local ?? name;
|
|
44
|
+
const existing = findImports(api, source).filter((path) => path.node.importKind !== "type" && !(path.node.specifiers ?? []).some((specifier) => specifier.type === "ImportNamespaceSpecifier"));
|
|
45
|
+
if (existing.find(j.ImportSpecifier, { imported: { name } }).filter((path) => (path.node.local?.name ?? name) === local).size() > 0) return local;
|
|
46
|
+
const specifier = j.importSpecifier(j.identifier(name), local !== name ? j.identifier(local) : null);
|
|
47
|
+
if (options.type === true && api.typescript) specifier.importKind = "type";
|
|
48
|
+
if (existing.size() > 0) {
|
|
49
|
+
const declaration = existing.get().node;
|
|
50
|
+
declaration.specifiers = [...declaration.specifiers ?? [], specifier];
|
|
51
|
+
return local;
|
|
52
|
+
}
|
|
53
|
+
insertImport(api, j.importDeclaration([specifier], j.literal(source)));
|
|
54
|
+
return local;
|
|
55
|
+
}
|
|
56
|
+
/** Inserts an import of a package before the relative imports of the file, or after its imports. */
|
|
57
|
+
function insertImport(api, declaration) {
|
|
58
|
+
const { j, root } = api;
|
|
59
|
+
const imports = root.find(j.ImportDeclaration);
|
|
60
|
+
const source = String(declaration.source.value);
|
|
61
|
+
const relative = imports.filter((path) => String(path.node.source.value).startsWith("."));
|
|
62
|
+
if (!source.startsWith(".") && relative.size() > 0) {
|
|
63
|
+
relative.at(0).insertBefore(declaration);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (imports.size() > 0) {
|
|
67
|
+
imports.at(imports.size() - 1).insertAfter(declaration);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
root.find(j.Program).get().node.body.unshift(declaration);
|
|
71
|
+
}
|
|
72
|
+
/** A string for a JSX attribute, in double quotes as JSX has them. */
|
|
73
|
+
function jsxString(j, value) {
|
|
74
|
+
const literal = j.literal(value);
|
|
75
|
+
literal.extra = {
|
|
76
|
+
raw: JSON.stringify(value),
|
|
77
|
+
rawValue: value
|
|
78
|
+
};
|
|
79
|
+
return literal;
|
|
80
|
+
}
|
|
81
|
+
/** Removes a specifier from an import, and the import when it has none left. */
|
|
82
|
+
function removeSpecifier(api, path) {
|
|
83
|
+
const declaration = path.parent;
|
|
84
|
+
const node = declaration.node;
|
|
85
|
+
node.specifiers = (node.specifiers ?? []).filter((specifier) => specifier !== path.node);
|
|
86
|
+
if (node.specifiers.length === 0) removeImport(api, declaration);
|
|
87
|
+
}
|
|
88
|
+
/** Removes an import, keeping the comments above it on the next statement. */
|
|
89
|
+
function removeImport(api, path) {
|
|
90
|
+
const leading = (path.node.comments ?? []).filter((comment) => comment.leading !== false);
|
|
91
|
+
const body = path.parent.node;
|
|
92
|
+
const index = body.body?.indexOf(path.node) ?? -1;
|
|
93
|
+
const next = index >= 0 ? body.body?.[index + 1] : void 0;
|
|
94
|
+
if (leading.length > 0 && next !== void 0) next.comments = [...leading, ...next.comments ?? []];
|
|
95
|
+
api.j(path).remove();
|
|
96
|
+
}
|
|
97
|
+
/** Whether a name is still used in the file, outside of imports. */
|
|
98
|
+
function isUsed(api, name) {
|
|
99
|
+
const { j, root } = api;
|
|
100
|
+
return root.find(j.Identifier, { name }).filter((path) => {
|
|
101
|
+
const parent = path.parent.node;
|
|
102
|
+
return parent.type !== "ImportSpecifier" && parent.type !== "ImportDefaultSpecifier" && parent.type !== "ImportNamespaceSpecifier";
|
|
103
|
+
}).size() > 0 || root.find(j.JSXIdentifier, { name }).size() > 0;
|
|
104
|
+
}
|
|
105
|
+
/** Removes the imports of names that are no longer used. */
|
|
106
|
+
function removeUnusedImports(api, names) {
|
|
107
|
+
const { j, root } = api;
|
|
108
|
+
names.forEach((name) => {
|
|
109
|
+
if (isUsed(api, name)) return;
|
|
110
|
+
root.find(j.ImportSpecifier, { local: { name } }).forEach((path) => removeSpecifier(api, path));
|
|
111
|
+
root.find(j.ImportDefaultSpecifier, { local: { name } }).forEach((path) => removeSpecifier(api, path));
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
export { TODO_PREFIX, addNamedImport, addTodo, findImports, getLine, insertImport, isUsed, jsxString, removeImport, removeSpecifier, removeUnusedImports };
|
|
116
|
+
|
|
117
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","names":[],"sources":["../src/context.ts"],"sourcesContent":["import type { ASTPath, Collection, ImportDeclaration, JSCodeshift } from 'jscodeshift';\n\n/** Something a codemod couldn't rewrite, or that needs a check. */\nexport interface Finding {\n /** Path of the file, relative to where the codemods ran. */\n file: string;\n /** Line in the file before the codemods, when there is one. */\n line: number | null;\n /** What it is about: `import`, `entry`, `field-component`, `bootstrap`… */\n rule: string;\n message: string;\n}\n\n/** What the codemods know about a file of the run, before they rewrite it. */\nexport interface FileInfo {\n /** The file renders the app of v4: the codemods make it a plugin module. */\n isContainer: boolean;\n /** Modules of the `components` of the app, by v4 namespace (`fields`), as written. */\n namespaces: ReadonlyMap<string, string>;\n /** Re-exports of default exports: `export { default as Agency } from './Agency'`. */\n defaultReExports: ReadonlyMap<string, string>;\n /** Whether the file imports a module of `@panneau/*`. */\n importsPanneau: boolean;\n /** Whether the file has a default export. */\n hasDefaultExport: boolean;\n /** The name of the field entry the file exports, or will export. */\n fieldEntry: string | null;\n}\n\n/** What a transform knows about the other files of the run. */\nexport interface Project {\n /** The path of a module imported from a file of the run, when it is one too. */\n resolve(from: string, specifier: string): string | null;\n info(path: string): FileInfo | null;\n /** Whether the default export of a file is registered as a field. */\n isField(path: string): boolean;\n /** Plugin modules made from v4 containers, for the entry of v5. */\n pluginModules(): readonly string[];\n}\n\nexport interface TransformApi {\n j: JSCodeshift;\n root: Collection;\n /** Absolute path of the file. */\n path: string;\n /** Whether the file is TypeScript. */\n typescript: boolean;\n project: Project;\n /**\n * Reports a finding at a node. With `todo`, the statement of the node also gets a\n * `// TODO(panneau-5): …` comment, so it can be found once the files are written.\n */\n report(node: ASTPath | null, rule: string, message: string, options?: { todo?: boolean }): void;\n}\n\nexport const TODO_PREFIX = 'TODO(panneau-5):';\n\n/** The statement (or declaration) a node belongs to, where comments can go. */\nfunction getStatement(path: ASTPath): ASTPath | null {\n let current: ASTPath | null = path;\n while (current !== null) {\n const parent = current.parent as ASTPath | null;\n const parentType = parent?.node.type;\n if (\n parent === null ||\n parentType === 'Program' ||\n parentType === 'BlockStatement' ||\n parentType === 'ExportNamedDeclaration' ||\n parentType === 'ExportDefaultDeclaration'\n ) {\n return parentType === 'ExportNamedDeclaration' ||\n parentType === 'ExportDefaultDeclaration'\n ? parent\n : current;\n }\n current = parent;\n }\n return null;\n}\n\ninterface CommentNode {\n type: string;\n value: string;\n leading?: boolean;\n}\n\n/** Adds a `// TODO(panneau-5): …` comment over the statement of a node, once. */\nexport function addTodo(j: JSCodeshift, path: ASTPath, message: string): void {\n const statement = getStatement(path);\n if (statement === null) {\n return;\n }\n const node = statement.node as { comments?: CommentNode[] | null };\n const text = ` ${TODO_PREFIX} ${message}`;\n if ((node.comments ?? []).some((comment) => comment.value === text)) {\n return;\n }\n node.comments = [...(node.comments ?? []), j.commentLine(text, true, false) as CommentNode];\n}\n\n/** The line of a node in the source, or of the closest node that has one. */\nexport function getLine(path: ASTPath | null): number | null {\n let current = path;\n while (current !== null) {\n const loc = (current.node as { loc?: { start: { line: number } } | null }).loc;\n if (loc) {\n return loc.start.line;\n }\n current = current.parent as ASTPath | null;\n }\n return null;\n}\n\n/** The import declarations of a module. */\nexport function findImports(api: TransformApi, source: string): Collection<ImportDeclaration> {\n return api.root.find(api.j.ImportDeclaration, { source: { value: source } });\n}\n\n/**\n * Adds `import { name as local } from 'source'` to an import of the module, or in a new one.\n * Types are imported with `type` in the list of names. Returns the local name.\n */\nexport function addNamedImport(\n api: TransformApi,\n source: string,\n name: string,\n options: { local?: string; type?: boolean } = {},\n): string {\n const { j } = api;\n const local = options.local ?? name;\n const existing = findImports(api, source).filter(\n (path) =>\n path.node.importKind !== 'type' &&\n !(path.node.specifiers ?? []).some(\n (specifier) => specifier.type === 'ImportNamespaceSpecifier',\n ),\n );\n const present = existing\n .find(j.ImportSpecifier, { imported: { name } })\n .filter((path) => (path.node.local?.name ?? name) === local);\n if (present.size() > 0) {\n return local;\n }\n const specifier = j.importSpecifier(\n j.identifier(name),\n local !== name ? j.identifier(local) : null,\n );\n if (options.type === true && api.typescript) {\n (specifier as { importKind?: string }).importKind = 'type';\n }\n if (existing.size() > 0) {\n const declaration = existing.get().node as ImportDeclaration;\n declaration.specifiers = [...(declaration.specifiers ?? []), specifier];\n return local;\n }\n insertImport(api, j.importDeclaration([specifier], j.literal(source)));\n return local;\n}\n\n/** Inserts an import of a package before the relative imports of the file, or after its imports. */\nexport function insertImport(api: TransformApi, declaration: ImportDeclaration): void {\n const { j, root } = api;\n const imports = root.find(j.ImportDeclaration);\n const source = String(declaration.source.value);\n const relative = imports.filter((path) => String(path.node.source.value).startsWith('.'));\n if (!source.startsWith('.') && relative.size() > 0) {\n relative.at(0).insertBefore(declaration);\n return;\n }\n if (imports.size() > 0) {\n imports.at(imports.size() - 1).insertAfter(declaration);\n return;\n }\n const program = root.find(j.Program).get();\n program.node.body.unshift(declaration);\n}\n\n/** A string for a JSX attribute, in double quotes as JSX has them. */\nexport function jsxString(j: JSCodeshift, value: string) {\n const literal = j.literal(value);\n (literal as { extra?: unknown }).extra = { raw: JSON.stringify(value), rawValue: value };\n return literal;\n}\n\n/** Removes a specifier from an import, and the import when it has none left. */\nexport function removeSpecifier(api: TransformApi, path: ASTPath): void {\n const declaration = path.parent as ASTPath<ImportDeclaration>;\n const node = declaration.node;\n node.specifiers = (node.specifiers ?? []).filter((specifier) => specifier !== path.node);\n if (node.specifiers.length === 0) {\n removeImport(api, declaration);\n }\n}\n\n/** Removes an import, keeping the comments above it on the next statement. */\nexport function removeImport(api: TransformApi, path: ASTPath<ImportDeclaration>): void {\n const comments = (path.node as { comments?: CommentNode[] | null }).comments ?? [];\n const leading = comments.filter((comment) => comment.leading !== false);\n const body = (path.parent as ASTPath).node as { body?: unknown[] };\n const index = body.body?.indexOf(path.node) ?? -1;\n const next =\n index >= 0 ? (body.body?.[index + 1] as { comments?: CommentNode[] | null }) : undefined;\n if (leading.length > 0 && next !== undefined) {\n next.comments = [...leading, ...(next.comments ?? [])];\n }\n api.j(path).remove();\n}\n\n/** Whether a name is still used in the file, outside of imports. */\nexport function isUsed(api: TransformApi, name: string): boolean {\n const { j, root } = api;\n return (\n root\n .find(j.Identifier, { name })\n .filter((path) => {\n const parent = path.parent.node as { type: string };\n return (\n parent.type !== 'ImportSpecifier' &&\n parent.type !== 'ImportDefaultSpecifier' &&\n parent.type !== 'ImportNamespaceSpecifier'\n );\n })\n .size() > 0 || root.find(j.JSXIdentifier, { name }).size() > 0\n );\n}\n\n/** Removes the imports of names that are no longer used. */\nexport function removeUnusedImports(api: TransformApi, names: readonly string[]): void {\n const { j, root } = api;\n names.forEach((name) => {\n if (isUsed(api, name)) {\n return;\n }\n root.find(j.ImportSpecifier, { local: { name } }).forEach((path) =>\n removeSpecifier(api, path),\n );\n root.find(j.ImportDefaultSpecifier, { local: { name } }).forEach((path) =>\n removeSpecifier(api, path),\n );\n });\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { Finding } from './context.js';
|
|
2
|
+
export { runCli } from './cli.js';
|
|
3
|
+
export { type RunOptions, type RunResult, formatReport, runCodemods } from './run.js';
|
|
4
|
+
export { type SourcesResult, transformSources } from './transform.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACnF,OAAO,EAAE,KAAK,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** A v5 field component that replaces a v4 one. */
|
|
2
|
+
export interface FieldTarget {
|
|
3
|
+
/** Module of the v5 component. */
|
|
4
|
+
source: string;
|
|
5
|
+
/** Export of the v5 component. */
|
|
6
|
+
name: string;
|
|
7
|
+
/** Props of the v5 component besides those of every field (`FieldProps`). */
|
|
8
|
+
props: readonly string[];
|
|
9
|
+
/** v4 props that have another name in v5. */
|
|
10
|
+
renames?: Readonly<Record<string, string>>;
|
|
11
|
+
/** Props that give the v5 component the behavior of the v4 one (`widget="radios"`). */
|
|
12
|
+
adds?: Readonly<Record<string, string | true | readonly string[]>>;
|
|
13
|
+
/** The type of the value, for the input of a locale of a localized field in TypeScript. */
|
|
14
|
+
valueType?: 'string' | 'number' | 'boolean';
|
|
15
|
+
/** What to check after the rewrite, when the props of the v4 and v5 components differ. */
|
|
16
|
+
note?: string;
|
|
17
|
+
}
|
|
18
|
+
/** Props of every v5 field (`FieldProps` of `@panneau/fields`), plus React's `key`. */
|
|
19
|
+
export declare const FIELD_PROPS: readonly string[];
|
|
20
|
+
/** v4 props of every field with another name in v5. */
|
|
21
|
+
export declare const FIELD_RENAMES: Readonly<Record<string, string>>;
|
|
22
|
+
/**
|
|
23
|
+
* The v5 component of each v4 field, by the v4 id in kebab case: `useFieldComponent('date_time')`
|
|
24
|
+
* and `@panneau/field-date-time` both give `date-time`, as v4 looked components up by their name
|
|
25
|
+
* in Pascal case.
|
|
26
|
+
*/
|
|
27
|
+
export declare const FIELD_TARGETS: Readonly<Record<string, FieldTarget>>;
|
|
28
|
+
/** v4 fields with no v5 component, and what replaces them. */
|
|
29
|
+
export declare const FIELDS_WITHOUT_TARGET: Readonly<Record<string, string>>;
|
|
30
|
+
/** The v5 component of a v4 field id (`date_time`, `DateTime`, `date-time`). */
|
|
31
|
+
export declare function getFieldTarget(id: string): FieldTarget | null;
|
|
32
|
+
/** v4 namespaces of the `components` prop of the app, and the kinds of v5 plugins. */
|
|
33
|
+
export declare const NAMESPACES: Readonly<Record<string, {
|
|
34
|
+
kind: string | null;
|
|
35
|
+
note?: string;
|
|
36
|
+
constant: string;
|
|
37
|
+
}>>;
|
|
38
|
+
/** The namespace of a constant of `@panneau/core/contexts` (`FIELDS_NAMESPACE`). */
|
|
39
|
+
export declare function getNamespaceOfConstant(constant: string): string | null;
|
|
40
|
+
/**
|
|
41
|
+
* Packages of v4 that have a package of the same name in v5. Their main entry point is v5 for
|
|
42
|
+
* every name but those listed here, which only v4 exported (`default` is the default export).
|
|
43
|
+
*/
|
|
44
|
+
export declare const SHARED_PACKAGES: Readonly<Record<string, readonly string[]>>;
|
|
45
|
+
/** Packages that only exist in v4. Their imports are rewritten or reported. */
|
|
46
|
+
export declare function isV4Package(name: string): boolean;
|
|
47
|
+
/** What replaces v4 exports, by module and name, for the messages of the report. */
|
|
48
|
+
export declare const REPLACEMENTS: Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
49
|
+
//# sourceMappingURL=mappings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mappings.d.ts","sourceRoot":"","sources":["../src/mappings.ts"],"names":[],"mappings":"AAIA,mDAAmD;AACnD,MAAM,WAAW,WAAW;IACxB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,uFAAuF;IACvF,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;IACnE,2FAA2F;IAC3F,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC5C,0FAA0F;IAC1F,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAmBxC,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAA+B,CAAC;AAqE3F;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CA6G/D,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQlE,CAAC;AAEF,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAE7D;AAED,sFAAsF;AACtF,eAAO,MAAM,UAAU,EAAE,QAAQ,CAC7B,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAiC3E,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKtE;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAyIvE,CAAC;AAEF,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAejD;AAED,oFAAoF;AACpF,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAsEnF,CAAC"}
|