@shrkcrft/generator 0.1.0-alpha.16 → 0.1.0-alpha.17
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"folder-apply.d.ts","sourceRoot":"","sources":["../src/folder-apply.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"folder-apply.d.ts","sourceRoot":"","sources":["../src/folder-apply.ts"],"names":[],"mappings":"AAeA,OAAO,EAAuB,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,CAAC;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,+BAA+B,CAAC;IACjD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;CAC/C;AAMD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,SAAS,cAAc,EAAE,EAC9B,OAAO,EAAE,gBAAgB,GACxB,oBAAoB,CAwHtB"}
|
package/dist/folder-apply.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { existsSync, renameSync, rmSync } from 'node:fs';
|
|
14
14
|
import * as nodePath from 'node:path';
|
|
15
|
+
import { safeResolveTargetPath } from '@shrkcrft/core';
|
|
15
16
|
import { checkFolderOpSafety, FolderOpSafety } from "./folder-safety.js";
|
|
16
17
|
function resolveAbs(projectRoot, p) {
|
|
17
18
|
return nodePath.isAbsolute(p) ? p : nodePath.resolve(projectRoot, p);
|
|
@@ -60,7 +61,26 @@ export function applyFolderOps(ops, options) {
|
|
|
60
61
|
});
|
|
61
62
|
continue;
|
|
62
63
|
}
|
|
63
|
-
|
|
64
|
+
// The rename DESTINATION is never validated by checkFolderOpSafety (which
|
|
65
|
+
// only checks targetPath), and resolveAbs even allows absolute newPaths —
|
|
66
|
+
// so `newPath: '../sibling'` or '/etc/x' would move the folder OUTSIDE the
|
|
67
|
+
// project root. Enforce containment through the same chokepoint as writes.
|
|
68
|
+
let safeNew;
|
|
69
|
+
try {
|
|
70
|
+
safeNew = safeResolveTargetPath(op.newPath, options.projectRoot);
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
const pathErr = e;
|
|
74
|
+
rejected.push({
|
|
75
|
+
...baseResult,
|
|
76
|
+
applied: false,
|
|
77
|
+
safety: FolderOpSafety.Unsafe,
|
|
78
|
+
reason: `rename-folder destination "${op.newPath}" is outside the project root (${pathErr.code}).`,
|
|
79
|
+
});
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const safeAbsNewPath = safeNew.absolutePath;
|
|
83
|
+
if (existsSync(safeAbsNewPath)) {
|
|
64
84
|
rejected.push({
|
|
65
85
|
...baseResult,
|
|
66
86
|
applied: false,
|
|
@@ -74,7 +94,7 @@ export function applyFolderOps(ops, options) {
|
|
|
74
94
|
continue;
|
|
75
95
|
}
|
|
76
96
|
try {
|
|
77
|
-
renameSync(absTarget,
|
|
97
|
+
renameSync(absTarget, safeAbsNewPath);
|
|
78
98
|
applied.push({ ...baseResult, applied: true });
|
|
79
99
|
}
|
|
80
100
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"synthetic-plan.d.ts","sourceRoot":"","sources":["../src/synthetic-plan.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"synthetic-plan.d.ts","sourceRoot":"","sources":["../src/synthetic-plan.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAE9C,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,UAAU,EAChB,WAAW,EAAE,MAAM,GAClB,eAAe,CAsCjB;AAwCD,OAAO,EAAsC,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAChG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;CACjC;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,eAAe,GACpB,MAAM,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAsCzC"}
|
package/dist/synthetic-plan.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { existsSync, readFileSync } from 'node:fs';
|
|
17
17
|
import * as nodePath from 'node:path';
|
|
18
|
+
import { safeResolveTargetPath } from '@shrkcrft/core';
|
|
18
19
|
import { evaluatePlannedChange } from "./planned-change.js";
|
|
19
20
|
import { FileChangeType } from "./file-change.js";
|
|
20
21
|
export const SYNTHETIC_TEMPLATE_PREFIX = '__';
|
|
@@ -62,12 +63,30 @@ export function evaluateSavedPlanInPlace(plan, projectRoot) {
|
|
|
62
63
|
return out;
|
|
63
64
|
}
|
|
64
65
|
function applyOperation(projectRoot, relativePath, operation) {
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
// Route through the single generator chokepoint instead of a bare resolve, so
|
|
67
|
+
// a traversal / absolute `relativePath` in a hand-crafted or tampered plan
|
|
68
|
+
// can't write OUTSIDE the project root. An unsafe path becomes a Conflict,
|
|
69
|
+
// which writeSyntheticPlan refuses (matching the template path in dry-run.ts).
|
|
70
|
+
let safe;
|
|
71
|
+
try {
|
|
72
|
+
safe = safeResolveTargetPath(relativePath, projectRoot);
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
const pathErr = e;
|
|
76
|
+
return {
|
|
77
|
+
type: FileChangeType.Conflict,
|
|
78
|
+
absolutePath: pathErr.rawPath,
|
|
79
|
+
relativePath: pathErr.rawPath,
|
|
80
|
+
contents: '',
|
|
81
|
+
reason: `Refused unsafe target path (${pathErr.code}): ${pathErr.message}`,
|
|
82
|
+
sizeBytes: 0,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const existing = existsSync(safe.absolutePath) ? readFileSync(safe.absolutePath, 'utf8') : null;
|
|
67
86
|
return evaluatePlannedChange({
|
|
68
|
-
change: { targetPath: relativePath, operation },
|
|
69
|
-
absolutePath,
|
|
70
|
-
relativePath,
|
|
87
|
+
change: { targetPath: safe.relativePath, operation },
|
|
88
|
+
absolutePath: safe.absolutePath,
|
|
89
|
+
relativePath: safe.relativePath,
|
|
71
90
|
existing,
|
|
72
91
|
});
|
|
73
92
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shrkcrft/generator",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.17",
|
|
4
4
|
"description": "SharkCraft plan-first generator: GenerationPlan, FileChange, dry-run, safe writes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "SharkCraft contributors",
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@shrkcrft/core": "^0.1.0-alpha.
|
|
47
|
-
"@shrkcrft/templates": "^0.1.0-alpha.
|
|
48
|
-
"@shrkcrft/rules": "^0.1.0-alpha.
|
|
49
|
-
"@shrkcrft/paths": "^0.1.0-alpha.
|
|
46
|
+
"@shrkcrft/core": "^0.1.0-alpha.17",
|
|
47
|
+
"@shrkcrft/templates": "^0.1.0-alpha.17",
|
|
48
|
+
"@shrkcrft/rules": "^0.1.0-alpha.17",
|
|
49
|
+
"@shrkcrft/paths": "^0.1.0-alpha.17"
|
|
50
50
|
},
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"access": "public"
|