sovr-patch 0.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.
Potentially problematic release.
This version of sovr-patch might be problematic. Click here for more details.
- package/LICENSE +66 -0
- package/README.md +112 -0
- package/dist/audit/engine.js +140 -0
- package/dist/audit/engine.js.map +1 -0
- package/dist/audit/packs.js +21 -0
- package/dist/audit/packs.js.map +1 -0
- package/dist/audit/report.js +79 -0
- package/dist/audit/report.js.map +1 -0
- package/dist/audit/types.js +5 -0
- package/dist/audit/types.js.map +1 -0
- package/dist/cli/help.js +108 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/parse-argv.js +73 -0
- package/dist/cli/parse-argv.js.map +1 -0
- package/dist/commands/activate.js +179 -0
- package/dist/commands/activate.js.map +1 -0
- package/dist/commands/audit.js +89 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/ci-gate.js +239 -0
- package/dist/commands/ci-gate.js.map +1 -0
- package/dist/commands/list-rules.js +11 -0
- package/dist/commands/list-rules.js.map +1 -0
- package/dist/commands/run.js +107 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/status.js +174 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/core/engine.js +68 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/license.js +243 -0
- package/dist/core/license.js.map +1 -0
- package/dist/core/load-project.js +41 -0
- package/dist/core/load-project.js.map +1 -0
- package/dist/core/report.js +68 -0
- package/dist/core/report.js.map +1 -0
- package/dist/core/rollback.js +160 -0
- package/dist/core/rollback.js.map +1 -0
- package/dist/core/safe-apply.js +75 -0
- package/dist/core/safe-apply.js.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/update-check.js +162 -0
- package/dist/core/update-check.js.map +1 -0
- package/dist/core/verify.js +32 -0
- package/dist/core/verify.js.map +1 -0
- package/dist/index.js +124 -0
- package/dist/index.js.map +1 -0
- package/dist/patch/apply.js +14 -0
- package/dist/patch/apply.js.map +1 -0
- package/dist/patch/overlap.js +12 -0
- package/dist/patch/overlap.js.map +1 -0
- package/dist/patch/preview.js +48 -0
- package/dist/patch/preview.js.map +1 -0
- package/dist/rules/design-token/classify.js +16 -0
- package/dist/rules/design-token/classify.js.map +1 -0
- package/dist/rules/design-token/locate.js +113 -0
- package/dist/rules/design-token/locate.js.map +1 -0
- package/dist/rules/design-token/presets.js +53 -0
- package/dist/rules/design-token/presets.js.map +1 -0
- package/dist/rules/design-token/rule.js +13 -0
- package/dist/rules/design-token/rule.js.map +1 -0
- package/dist/rules/design-token/schema.js +84 -0
- package/dist/rules/design-token/schema.js.map +1 -0
- package/dist/rules/design-token/transform.js +27 -0
- package/dist/rules/design-token/transform.js.map +1 -0
- package/dist/rules/field-rename/classify.js +77 -0
- package/dist/rules/field-rename/classify.js.map +1 -0
- package/dist/rules/field-rename/locate.js +294 -0
- package/dist/rules/field-rename/locate.js.map +1 -0
- package/dist/rules/field-rename/rule.js +13 -0
- package/dist/rules/field-rename/rule.js.map +1 -0
- package/dist/rules/field-rename/schema.js +35 -0
- package/dist/rules/field-rename/schema.js.map +1 -0
- package/dist/rules/field-rename/transform.js +160 -0
- package/dist/rules/field-rename/transform.js.map +1 -0
- package/dist/rules/inline-style/classify.js +17 -0
- package/dist/rules/inline-style/classify.js.map +1 -0
- package/dist/rules/inline-style/locate.js +163 -0
- package/dist/rules/inline-style/locate.js.map +1 -0
- package/dist/rules/inline-style/presets.js +71 -0
- package/dist/rules/inline-style/presets.js.map +1 -0
- package/dist/rules/inline-style/rule.js +13 -0
- package/dist/rules/inline-style/rule.js.map +1 -0
- package/dist/rules/inline-style/schema.js +97 -0
- package/dist/rules/inline-style/schema.js.map +1 -0
- package/dist/rules/inline-style/transform.js +52 -0
- package/dist/rules/inline-style/transform.js.map +1 -0
- package/dist/rules/nullish-fallback/classify.js +22 -0
- package/dist/rules/nullish-fallback/classify.js.map +1 -0
- package/dist/rules/nullish-fallback/locate.js +175 -0
- package/dist/rules/nullish-fallback/locate.js.map +1 -0
- package/dist/rules/nullish-fallback/rule.js +13 -0
- package/dist/rules/nullish-fallback/rule.js.map +1 -0
- package/dist/rules/nullish-fallback/schema.js +10 -0
- package/dist/rules/nullish-fallback/schema.js.map +1 -0
- package/dist/rules/nullish-fallback/transform.js +49 -0
- package/dist/rules/nullish-fallback/transform.js.map +1 -0
- package/dist/rules/registry.js +21 -0
- package/dist/rules/registry.js.map +1 -0
- package/dist/rules/types.js +2 -0
- package/dist/rules/types.js.map +1 -0
- package/license.json +13 -0
- package/package.json +64 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { parseNullishFallbackConfig } from "./schema.js";
|
|
2
|
+
import { locateNullishFallback } from "./locate.js";
|
|
3
|
+
import { classifyNullishFallback } from "./classify.js";
|
|
4
|
+
import { transformNullishFallback } from "./transform.js";
|
|
5
|
+
export const nullishFallbackRule = {
|
|
6
|
+
name: "nullish-fallback",
|
|
7
|
+
description: "Inject ?? fallback for repeated property access targets.",
|
|
8
|
+
parseConfig: parseNullishFallbackConfig,
|
|
9
|
+
locate: locateNullishFallback,
|
|
10
|
+
classify: classifyNullishFallback,
|
|
11
|
+
transform: transformNullishFallback,
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule.js","sourceRoot":"","sources":["../../../src/rules/nullish-fallback/rule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAI1D,MAAM,CAAC,MAAM,mBAAmB,GAA0C;IACxE,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,0DAA0D;IACvE,WAAW,EAAE,0BAA0B;IACvC,MAAM,EAAE,qBAAqB;IAC7B,QAAQ,EAAE,uBAAuB;IACjC,SAAS,EAAE,wBAAwB;CACpC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function parseNullishFallbackConfig(input) {
|
|
2
|
+
const target = String(input.target ?? "").trim();
|
|
3
|
+
const fallback = String(input.fallback ?? "").trim();
|
|
4
|
+
if (!target)
|
|
5
|
+
throw new Error(`nullish-fallback: "target" is required`);
|
|
6
|
+
if (!fallback)
|
|
7
|
+
throw new Error(`nullish-fallback: "fallback" is required`);
|
|
8
|
+
return { target, fallback };
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/rules/nullish-fallback/schema.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,0BAA0B,CACxC,KAA8B;IAE9B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAErD,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IACvE,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAE3E,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export function transformNullishFallback(hit, context) {
|
|
2
|
+
const kind = String(hit.metadata?.kind ?? "");
|
|
3
|
+
const fallback = context.config.fallback;
|
|
4
|
+
const wrapParens = Boolean(hit.metadata?.needsParentheses);
|
|
5
|
+
if (kind === "nullish-target-chain") {
|
|
6
|
+
// The matched target is part of a larger chain.
|
|
7
|
+
// e.g., data.result?.data where target = "data.result"
|
|
8
|
+
//
|
|
9
|
+
// We replace the ENTIRE outer chain:
|
|
10
|
+
// Before: data.result?.data
|
|
11
|
+
// After: (data.result ?? '').data
|
|
12
|
+
const matchedText = String(hit.metadata?.matchedText ?? "");
|
|
13
|
+
const tailText = String(hit.metadata?.tailText ?? "");
|
|
14
|
+
let after = `(${matchedText} ?? ${fallback})${tailText}`;
|
|
15
|
+
// If the chain is inside a binary expression (e.g., x?.y > 100),
|
|
16
|
+
// wrap the entire replacement in parentheses
|
|
17
|
+
if (wrapParens) {
|
|
18
|
+
after = `(${after})`;
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
filePath: hit.filePath,
|
|
22
|
+
start: hit.start,
|
|
23
|
+
end: hit.end,
|
|
24
|
+
before: hit.sourceText,
|
|
25
|
+
after,
|
|
26
|
+
ruleName: "nullish-fallback",
|
|
27
|
+
reason: "inject-nullish-fallback-chain",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
// Standalone target (no further chain after it)
|
|
31
|
+
// e.g., data.result → data.result ?? ''
|
|
32
|
+
//
|
|
33
|
+
// If inside a binary expression (e.g., plan.yearlyPrice > 100),
|
|
34
|
+
// wrap in parentheses: (plan.yearlyPrice ?? 0) > 100
|
|
35
|
+
let after = `${hit.sourceText} ?? ${fallback}`;
|
|
36
|
+
if (wrapParens) {
|
|
37
|
+
after = `(${after})`;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
filePath: hit.filePath,
|
|
41
|
+
start: hit.start,
|
|
42
|
+
end: hit.end,
|
|
43
|
+
before: hit.sourceText,
|
|
44
|
+
after,
|
|
45
|
+
ruleName: "nullish-fallback",
|
|
46
|
+
reason: "inject-nullish-fallback",
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../../../src/rules/nullish-fallback/transform.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,wBAAwB,CACtC,GAAgB,EAChB,OAA2C;IAE3C,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;IACzC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAE3D,IAAI,IAAI,KAAK,sBAAsB,EAAE,CAAC;QACpC,gDAAgD;QAChD,wDAAwD;QACxD,EAAE;QACF,qCAAqC;QACrC,8BAA8B;QAC9B,qCAAqC;QACrC,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC;QAEtD,IAAI,KAAK,GAAG,IAAI,WAAW,OAAO,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAEzD,iEAAiE;QACjE,6CAA6C;QAC7C,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,GAAG,IAAI,KAAK,GAAG,CAAC;QACvB,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,MAAM,EAAE,GAAG,CAAC,UAAU;YACtB,KAAK;YACL,QAAQ,EAAE,kBAAkB;YAC5B,MAAM,EAAE,+BAA+B;SACxC,CAAC;IACJ,CAAC;IAED,gDAAgD;IAChD,0CAA0C;IAC1C,EAAE;IACF,gEAAgE;IAChE,qDAAqD;IACrD,IAAI,KAAK,GAAG,GAAG,GAAG,CAAC,UAAU,OAAO,QAAQ,EAAE,CAAC;IAC/C,IAAI,UAAU,EAAE,CAAC;QACf,KAAK,GAAG,IAAI,KAAK,GAAG,CAAC;IACvB,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,MAAM,EAAE,GAAG,CAAC,UAAU;QACtB,KAAK;QACL,QAAQ,EAAE,kBAAkB;QAC5B,MAAM,EAAE,yBAAyB;KAClC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { fieldRenameRule } from "./field-rename/rule.js";
|
|
2
|
+
import { nullishFallbackRule } from "./nullish-fallback/rule.js";
|
|
3
|
+
import { designTokenRule } from "./design-token/rule.js";
|
|
4
|
+
import { inlineStyleRule } from "./inline-style/rule.js";
|
|
5
|
+
export function createRuleRegistry() {
|
|
6
|
+
const registry = new Map();
|
|
7
|
+
registry.set(fieldRenameRule.name, fieldRenameRule);
|
|
8
|
+
registry.set(nullishFallbackRule.name, nullishFallbackRule);
|
|
9
|
+
registry.set(designTokenRule.name, designTokenRule);
|
|
10
|
+
registry.set(inlineStyleRule.name, inlineStyleRule);
|
|
11
|
+
return registry;
|
|
12
|
+
}
|
|
13
|
+
export function getRuleOrThrow(registry, name) {
|
|
14
|
+
const rule = registry.get(name);
|
|
15
|
+
if (!rule) {
|
|
16
|
+
const available = [...registry.keys()].join(", ");
|
|
17
|
+
throw new Error(`unknown rule: "${name}". Available rules: ${available}`);
|
|
18
|
+
}
|
|
19
|
+
return rule;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/rules/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,MAAM,UAAU,kBAAkB;IAChC,MAAM,QAAQ,GAAiB,IAAI,GAAG,EAAE,CAAC;IAEzC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IACpD,QAAQ,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;IAC5D,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IACpD,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAEpD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAsB,EAAE,IAAY;IACjE,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,SAAS,GAAG,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,uBAAuB,SAAS,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/rules/types.ts"],"names":[],"mappings":""}
|
package/license.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"email": "test@test.com",
|
|
3
|
+
"plan": "full-engine",
|
|
4
|
+
"rules": [
|
|
5
|
+
"field-rename",
|
|
6
|
+
"nullish-fallback",
|
|
7
|
+
"design-token",
|
|
8
|
+
"inline-style"
|
|
9
|
+
],
|
|
10
|
+
"exp": "2027-03-07T11:22:52.007Z",
|
|
11
|
+
"iat": "2026-03-07T11:22:52.007Z",
|
|
12
|
+
"signature": "fIcH07l6gQyFuhidadMK5w+7SGN+Y39SOe5965PbtRi8kye3JIfpk3yHPcGW0dyMm3DO6obhoJnLi/kFMJ84Bg=="
|
|
13
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sovr-patch",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Rule-driven TypeScript migration engine. AST-powered scanning, safe patches, tsc verification.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"sovr-patch": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc -p tsconfig.json",
|
|
11
|
+
"dev": "tsx src/index.ts",
|
|
12
|
+
"list-rules": "tsx src/index.ts list-rules",
|
|
13
|
+
"demo": "tsx scripts/demo.ts",
|
|
14
|
+
"demo:apply": "tsx scripts/demo.ts --apply",
|
|
15
|
+
"trial:field-rename": "tsx src/index.ts run --rule field-rename --from \"config.baseUrl\" --to \"config.endpoint\" --repo ./fixtures/demo-repo-baseurl --report",
|
|
16
|
+
"trial:field-rename:apply": "tsx src/index.ts run --rule field-rename --from \"config.baseUrl\" --to \"config.endpoint\" --repo ./fixtures/demo-repo-baseurl --apply --report",
|
|
17
|
+
"test:scan": "tsx scripts/test-scan.ts",
|
|
18
|
+
"test:rewrite": "tsx scripts/test-rewrite.ts",
|
|
19
|
+
"test:safe-apply": "tsx scripts/test-safe-apply.ts",
|
|
20
|
+
"test": "npm run test:scan && npm run test:rewrite && npm run test:safe-apply",
|
|
21
|
+
"test:engine": "tsx scripts/test-engine.ts",
|
|
22
|
+
"test:nullish-chain": "tsx scripts/test-nullish-chain.ts",
|
|
23
|
+
"test:nullish-precedence": "tsx scripts/test-nullish-precedence.ts",
|
|
24
|
+
"test:destructuring": "tsx scripts/test-destructuring.ts",
|
|
25
|
+
"test:design-token": "tsx scripts/test-design-token.ts",
|
|
26
|
+
"test:inline-style": "tsx scripts/test-inline-style.ts",
|
|
27
|
+
"test:all": "npm run test && npm run test:engine && npm run test:nullish-chain && npm run test:nullish-precedence && npm run test:destructuring && npm run test:design-token && npm run test:inline-style",
|
|
28
|
+
"ci": "tsx scripts/ci-gate.ts"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"diff": "^7.0.0",
|
|
32
|
+
"ts-morph": "^25.0.0",
|
|
33
|
+
"typescript": "^5.9.2"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/diff": "^7.0.2",
|
|
37
|
+
"@types/node": "^24.3.0",
|
|
38
|
+
"tsx": "^4.19.2",
|
|
39
|
+
"vitest": "^4.0.18"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=20"
|
|
43
|
+
},
|
|
44
|
+
"keywords": [
|
|
45
|
+
"codemod",
|
|
46
|
+
"typescript",
|
|
47
|
+
"migration",
|
|
48
|
+
"ast",
|
|
49
|
+
"patch",
|
|
50
|
+
"sovr",
|
|
51
|
+
"rule-engine"
|
|
52
|
+
],
|
|
53
|
+
"license": "BSL-1.1",
|
|
54
|
+
"files": [
|
|
55
|
+
"dist",
|
|
56
|
+
"LICENSE",
|
|
57
|
+
"README.md"
|
|
58
|
+
],
|
|
59
|
+
"author": "SOVR",
|
|
60
|
+
"repository": {
|
|
61
|
+
"type": "git",
|
|
62
|
+
"url": "https://github.com/xie38388/sovr-patch"
|
|
63
|
+
}
|
|
64
|
+
}
|