rbxts-transformer-commit-migrations 1.0.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/init.js +1 -1
- package/index.d.ts +2 -2
- package/out/abc.js +7 -0
- package/out/cli/resolveMacros.js +50 -16
- package/out/index.js +12 -9
- package/out/macro.js +8 -4
- package/out/test.js +7 -0
- package/out/util/loadMigrationEntries.js +1 -1
- package/out/util/macro.js +35 -0
- package/package.json +1 -1
package/bin/init.js
CHANGED
|
@@ -15,7 +15,7 @@ if (!existsSync(huskyDir)) {
|
|
|
15
15
|
process.exit(1);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const setupResolve = `npx resolve-commit-migrations\n`;
|
|
18
|
+
const setupResolve = `npx resolve-commit-migrations | xargs git add\n`;
|
|
19
19
|
|
|
20
20
|
if (existsSync(hookFile)) {
|
|
21
21
|
const existing = readFileSync(hookFile, "utf-8");
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export declare function $migrate(order: number): never;
|
|
2
|
-
export declare function $migrate(order: "__resolved"): number;
|
|
3
|
-
export declare function $migrate(order: number | "__resolved"): number | undefined;
|
|
2
|
+
export declare function $migrate(order: "__resolved", path: string[]): number;
|
|
3
|
+
export declare function $migrate(order: number | "__resolved", path: string[]): number | undefined;
|
package/out/abc.js
ADDED
package/out/cli/resolveMacros.js
CHANGED
|
@@ -4,29 +4,56 @@ import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
|
4
4
|
import { glob } from "glob";
|
|
5
5
|
import loadMigrationEntries from "../util/loadMigrationEntries.js";
|
|
6
6
|
import { CONFIG, MACRO, MACRO_CALL_REGEX, MACRO_REGEX } from "../config.js";
|
|
7
|
-
function
|
|
7
|
+
function getConfigPathFromTransformerConfig(tsconfigPath = "tsconfig.json") {
|
|
8
|
+
const raw = readFileSync(tsconfigPath, "utf-8");
|
|
9
|
+
if (!raw)
|
|
10
|
+
return;
|
|
11
|
+
const result = ts.parseConfigFileTextToJson(tsconfigPath, raw);
|
|
12
|
+
if (result.error || !result.config)
|
|
13
|
+
return undefined;
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
15
|
+
const plugins = result.config.compilerOptions?.plugins ?? [];
|
|
16
|
+
const entry = plugins.find((p) => p.transform === "rbxts-transformer-commit-migrations");
|
|
17
|
+
if (!entry)
|
|
18
|
+
return undefined;
|
|
19
|
+
return entry.configPath;
|
|
20
|
+
}
|
|
21
|
+
function findEntryPath(node) {
|
|
22
|
+
const parts = [];
|
|
8
23
|
let current = node.parent;
|
|
9
24
|
while (current) {
|
|
10
25
|
if (ts.isPropertyAssignment(current) || ts.isShorthandPropertyAssignment(current)) {
|
|
11
|
-
|
|
12
|
-
|
|
26
|
+
if (ts.isIdentifier(current.name) || ts.isStringLiteral(current.name)) {
|
|
27
|
+
parts.push(current.name.text);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
current = current.parent;
|
|
13
33
|
}
|
|
14
|
-
if (ts.isCallExpression(current) ||
|
|
34
|
+
else if (ts.isCallExpression(current) ||
|
|
35
|
+
ts.isPropertyAccessExpression(current) ||
|
|
36
|
+
ts.isObjectLiteralExpression(current)) {
|
|
15
37
|
current = current.parent;
|
|
16
38
|
}
|
|
17
39
|
else {
|
|
18
40
|
break;
|
|
19
41
|
}
|
|
20
42
|
}
|
|
21
|
-
return null;
|
|
43
|
+
return parts.length > 0 ? parts.reverse() : null;
|
|
22
44
|
}
|
|
45
|
+
const config = getConfigPathFromTransformerConfig() ?? CONFIG;
|
|
23
46
|
const files = glob.sync("src/**/*.ts");
|
|
24
47
|
const migrations = [];
|
|
25
48
|
const migrationData = {};
|
|
26
49
|
const usedOrders = new Set();
|
|
50
|
+
const changed = [];
|
|
27
51
|
function walk(node, ctx) {
|
|
28
52
|
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && MACRO_REGEX.test(node.expression.text)) {
|
|
29
|
-
const
|
|
53
|
+
const path = findEntryPath(node);
|
|
54
|
+
if (!path || path.length === 0)
|
|
55
|
+
return;
|
|
56
|
+
const entry = path.join("/");
|
|
30
57
|
const orderArg = node.arguments[0];
|
|
31
58
|
const order = orderArg ? ts.isNumericLiteral(orderArg) ? parseInt(orderArg.getText()) : null : 0;
|
|
32
59
|
if (order !== null && usedOrders.has(order)) {
|
|
@@ -41,10 +68,10 @@ function walk(node, ctx) {
|
|
|
41
68
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
42
69
|
usedOrders.add(order);
|
|
43
70
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
44
|
-
migrationData[entry] = { timestamp: Date.now(), order: order };
|
|
71
|
+
migrationData[entry] = { timestamp: Date.now(), order: order, path };
|
|
45
72
|
ctx.changed = true;
|
|
73
|
+
migrations.push(entry);
|
|
46
74
|
}
|
|
47
|
-
migrations.push(entry);
|
|
48
75
|
}
|
|
49
76
|
ts.forEachChild(node, (node) => {
|
|
50
77
|
walk(node, ctx);
|
|
@@ -56,32 +83,39 @@ for (const file of files) {
|
|
|
56
83
|
const ctx = { changed: false };
|
|
57
84
|
walk(sourceFile, ctx);
|
|
58
85
|
if (ctx.changed) {
|
|
86
|
+
changed.push(file);
|
|
59
87
|
writeFileSync(file, src.replaceAll(MACRO_CALL_REGEX, `${MACRO}("__resolved")`));
|
|
60
88
|
}
|
|
61
89
|
}
|
|
62
|
-
const [previousMigrations] = loadMigrationEntries(
|
|
90
|
+
const [previousMigrations] = loadMigrationEntries(config);
|
|
63
91
|
const removedMigrations = previousMigrations.filter((v) => !migrations.includes(v));
|
|
64
92
|
if (removedMigrations.length > 0) {
|
|
65
93
|
console.error(`Removed migrations: ${removedMigrations}. Migrations should never be removed!`);
|
|
66
94
|
process.exit(1);
|
|
67
95
|
}
|
|
68
96
|
const newMigrations = migrations.filter((v) => !previousMigrations.includes(v));
|
|
69
|
-
if (newMigrations.length === 0)
|
|
97
|
+
if (newMigrations.length === 0) {
|
|
98
|
+
console.error("No new migrations to resolve.");
|
|
70
99
|
process.exit(0);
|
|
100
|
+
}
|
|
71
101
|
const newLines = newMigrations
|
|
72
|
-
.map((e) => `\t${e}: { timestamp: ${migrationData[e].timestamp}, order: ${migrationData[e].order} },`)
|
|
102
|
+
.map((e) => `\t"${e}": { timestamp: ${migrationData[e].timestamp}, order: ${migrationData[e].order}, path: ${JSON.stringify(migrationData[e].path)} },`)
|
|
73
103
|
.join("\n");
|
|
74
104
|
const migratedEntries = migrations.map((e) => `"${e}"`).join(" | ");
|
|
75
|
-
if (!existsSync(
|
|
76
|
-
writeFileSync(
|
|
105
|
+
if (!existsSync(config)) {
|
|
106
|
+
writeFileSync(config, `type MigratedEntries = ${migratedEntries}\n\ninterface MigrationData {\n\tpath: string[]\n\ttimestamp: number\n\torder: number\n}\n\n// AUTO-GENERATED MIGRATION CONFIG - DO NOT EDIT\nexport const MIGRATED_ENTRIES: Record<MigratedEntries, MigrationData> = {\n${newLines}\n};\n`);
|
|
77
107
|
}
|
|
78
108
|
else {
|
|
79
|
-
const lines = readFileSync(
|
|
109
|
+
const lines = readFileSync(config, "utf-8").split("\n");
|
|
80
110
|
const typeIndex = lines.findIndex((l) => l.startsWith("type MigratedEntries"));
|
|
81
111
|
if (typeIndex !== -1) {
|
|
82
112
|
lines[typeIndex] = `type MigratedEntries = ${migratedEntries}`;
|
|
83
113
|
}
|
|
84
114
|
const updated = lines.join("\n").replace(/\};\s*$/, `${newLines}\n};`);
|
|
85
|
-
writeFileSync(
|
|
115
|
+
writeFileSync(config, updated);
|
|
116
|
+
}
|
|
117
|
+
changed.push(config);
|
|
118
|
+
console.error(`Successfuly resolved ${newMigrations.length} new migrations. [${newMigrations}]`);
|
|
119
|
+
for (const path of changed) {
|
|
120
|
+
console.log(path.replace(/\\/g, "/"));
|
|
86
121
|
}
|
|
87
|
-
console.log(`Successfuly resolved ${newMigrations.length} new migrations. [${newMigrations}]`);
|
package/out/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
|
-
import { findMacroCall, replaceMacroCall } from "./macro.js";
|
|
2
|
+
import { findMacroCall, replaceMacroCall } from "./util/macro.js";
|
|
3
3
|
import loadMigrationEntries from "./util/loadMigrationEntries.js";
|
|
4
4
|
import { CONFIG } from "./config.js";
|
|
5
5
|
import { existsSync } from "node:fs";
|
|
@@ -18,18 +18,21 @@ export default function (_, config) {
|
|
|
18
18
|
return (file) => {
|
|
19
19
|
if (config?.files && !config.files.some((f) => file.fileName.includes(f)))
|
|
20
20
|
return file;
|
|
21
|
-
function visit(node) {
|
|
22
|
-
if (!ts.isPropertyAssignment(node)
|
|
23
|
-
return ts.visitEachChild(node, visit, ctx);
|
|
21
|
+
function visit(node, currentPath) {
|
|
22
|
+
if (!ts.isPropertyAssignment(node))
|
|
23
|
+
return ts.visitEachChild(node, (node) => visit(node, currentPath), ctx);
|
|
24
24
|
const entry = ts.isIdentifier(node.name) ? node.name.text : node.name.getText(file);
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
|
|
25
|
+
const newPath = [...currentPath, entry];
|
|
26
|
+
if (!findMacroCall(node.initializer))
|
|
27
|
+
return ts.visitEachChild(node, (node) => visit(node, newPath), ctx);
|
|
28
|
+
const order = orderedEntries.indexOf(newPath.join("/"));
|
|
29
|
+
if (order !== -1) {
|
|
30
|
+
const newInit = replaceMacroCall(node.initializer, order, newPath);
|
|
28
31
|
return ts.factory.createPropertyAssignment(node.name, newInit);
|
|
29
32
|
}
|
|
30
|
-
return ts.visitEachChild(node, visit, ctx);
|
|
33
|
+
return ts.visitEachChild(node, (node) => visit(node, newPath), ctx);
|
|
31
34
|
}
|
|
32
|
-
return ts.visitNode(file, visit);
|
|
35
|
+
return ts.visitNode(file, (node) => visit(node, []));
|
|
33
36
|
};
|
|
34
37
|
};
|
|
35
38
|
}
|
package/out/macro.js
CHANGED
|
@@ -4,10 +4,14 @@ export function findMacroCall(node) {
|
|
|
4
4
|
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && MACRO_REGEX.test(node.expression.text)) {
|
|
5
5
|
return node;
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
if (ts.isCallExpression(node)) {
|
|
8
|
+
for (const arg of node.arguments) {
|
|
9
|
+
if (ts.isCallExpression(arg) && ts.isIdentifier(arg.expression) && MACRO_REGEX.test(arg.expression.text)) {
|
|
10
|
+
return arg;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return undefined;
|
|
11
15
|
}
|
|
12
16
|
export function replaceMacroCall(node, replacement) {
|
|
13
17
|
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && MACRO_REGEX.test(node.expression.text)) {
|
package/out/test.js
ADDED
|
@@ -26,7 +26,7 @@ export default function (config) {
|
|
|
26
26
|
const result = [];
|
|
27
27
|
const object = {};
|
|
28
28
|
for (const prop of declaration.initializer.properties) {
|
|
29
|
-
if (!ts.isPropertyAssignment(prop) || !ts.
|
|
29
|
+
if (!ts.isPropertyAssignment(prop) || !ts.isStringLiteral(prop.name) || !ts.isObjectLiteralExpression(prop.initializer))
|
|
30
30
|
continue;
|
|
31
31
|
result.push(prop.name.text);
|
|
32
32
|
object[prop.name.text] = reconstructProperties(prop.initializer.properties);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { MACRO_REGEX } from "../config.js";
|
|
3
|
+
export function findMacroCall(node) {
|
|
4
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && MACRO_REGEX.test(node.expression.text)) {
|
|
5
|
+
return node;
|
|
6
|
+
}
|
|
7
|
+
if (ts.isCallExpression(node)) {
|
|
8
|
+
for (const arg of node.arguments) {
|
|
9
|
+
if (ts.isCallExpression(arg) && ts.isIdentifier(arg.expression) && MACRO_REGEX.test(arg.expression.text)) {
|
|
10
|
+
return arg;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
export function replaceMacroCall(node, order, path) {
|
|
17
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
|
|
18
|
+
const newArgs = [];
|
|
19
|
+
let changed = false;
|
|
20
|
+
for (const arg of node.arguments) {
|
|
21
|
+
if (ts.isCallExpression(arg) && ts.isIdentifier(arg.expression) && MACRO_REGEX.test(arg.expression.text)) {
|
|
22
|
+
newArgs.push(ts.factory.createNumericLiteral(order));
|
|
23
|
+
newArgs.push(ts.factory.createArrayLiteralExpression(path.map(p => ts.factory.createStringLiteral(p)), false));
|
|
24
|
+
changed = true;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
newArgs.push(arg);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (changed) {
|
|
31
|
+
return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, newArgs);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return ts.visitEachChild(node, (child) => replaceMacroCall(child, order, path), undefined);
|
|
35
|
+
}
|