@aipper/aiws 0.0.1 → 0.0.2
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/package.json +2 -2
- package/src/template.js +46 -6
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aipper/aiws",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "AI Workspace CLI (init/update/validate) for Claude Code / OpenCode / Codex / iFlow.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"aiws": "./bin/aiws.js"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@aipper/aiws-spec": "0.0.
|
|
10
|
+
"@aipper/aiws-spec": "0.0.2"
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"bin",
|
package/src/template.js
CHANGED
|
@@ -6,6 +6,40 @@ import { normalizeNewlines } from "./hash.js";
|
|
|
6
6
|
import { extractTemplateBlock, upsertManagedBlock } from "./managed-blocks.js";
|
|
7
7
|
import { UserError } from "./errors.js";
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Template file candidates for a given manifest/workspace path.
|
|
11
|
+
*
|
|
12
|
+
* NOTE: npm excludes files named `.gitignore` from published tarballs, even when placed under templates/.
|
|
13
|
+
* We store it as `gitignore` in templates and map it back at runtime.
|
|
14
|
+
*
|
|
15
|
+
* @param {string} relPosix
|
|
16
|
+
* @returns {string[]}
|
|
17
|
+
*/
|
|
18
|
+
function templateRelCandidates(relPosix) {
|
|
19
|
+
const rel = normalizeRel(relPosix);
|
|
20
|
+
if (!rel) return [];
|
|
21
|
+
/** @type {string[]} */
|
|
22
|
+
const out = [rel];
|
|
23
|
+
if (rel === ".gitignore" || rel.endsWith("/.gitignore")) {
|
|
24
|
+
out.push(rel.replace(/(^|\/)\.gitignore$/, "$1gitignore"));
|
|
25
|
+
}
|
|
26
|
+
return Array.from(new Set(out));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a template source file path for a given workspace-relative path.
|
|
31
|
+
*
|
|
32
|
+
* @param {string} templateDir
|
|
33
|
+
* @param {string} relPosix
|
|
34
|
+
*/
|
|
35
|
+
async function resolveTemplateSourcePath(templateDir, relPosix) {
|
|
36
|
+
for (const cand of templateRelCandidates(relPosix)) {
|
|
37
|
+
const abs = templatePath(templateDir, cand);
|
|
38
|
+
if (await pathExists(abs)) return abs;
|
|
39
|
+
}
|
|
40
|
+
return templatePath(templateDir, relPosix);
|
|
41
|
+
}
|
|
42
|
+
|
|
9
43
|
/**
|
|
10
44
|
* Expand manifest paths, supporting patterns ending with `/**`.
|
|
11
45
|
*
|
|
@@ -48,9 +82,13 @@ export function templatePath(templateDir, relPosix) {
|
|
|
48
82
|
* @param {{ templateDir: string, workspaceRoot: string, relPosix: string, chmod?: number }} options
|
|
49
83
|
*/
|
|
50
84
|
export async function copyTemplateFileToWorkspace(options) {
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
|
|
85
|
+
const rel = normalizeRel(options.relPosix);
|
|
86
|
+
const src = await resolveTemplateSourcePath(options.templateDir, rel);
|
|
87
|
+
const dest = joinRel(options.workspaceRoot, rel);
|
|
88
|
+
if (!(await pathExists(src))) {
|
|
89
|
+
const tried = templateRelCandidates(rel).map((c) => templatePath(options.templateDir, c));
|
|
90
|
+
throw new UserError(`Template file missing: ${options.relPosix}`, { details: `Tried:\n- ${tried.join("\n- ")}` });
|
|
91
|
+
}
|
|
54
92
|
await copyFile(src, dest, typeof options.chmod === "number" ? { chmod: options.chmod } : undefined);
|
|
55
93
|
}
|
|
56
94
|
|
|
@@ -63,9 +101,12 @@ export async function copyTemplateFileToWorkspace(options) {
|
|
|
63
101
|
export async function applyManagedBlocksFromTemplate(options) {
|
|
64
102
|
const fileRel = normalizeRel(options.fileRel);
|
|
65
103
|
const dest = joinRel(options.workspaceRoot, fileRel);
|
|
66
|
-
const src =
|
|
104
|
+
const src = await resolveTemplateSourcePath(options.templateDir, fileRel);
|
|
67
105
|
|
|
68
|
-
if (!(await pathExists(src)))
|
|
106
|
+
if (!(await pathExists(src))) {
|
|
107
|
+
const tried = templateRelCandidates(fileRel).map((c) => templatePath(options.templateDir, c));
|
|
108
|
+
throw new UserError(`Template file missing: ${fileRel}`, { details: `Tried:\n- ${tried.join("\n- ")}` });
|
|
109
|
+
}
|
|
69
110
|
const templateText = normalizeNewlines(await readText(src));
|
|
70
111
|
|
|
71
112
|
if (!(await pathExists(dest))) {
|
|
@@ -104,4 +145,3 @@ export async function ensureWorkspaceDir(workspaceRoot, relPosix) {
|
|
|
104
145
|
const abs = joinRel(workspaceRoot, relPosix);
|
|
105
146
|
await fs.mkdir(abs, { recursive: true });
|
|
106
147
|
}
|
|
107
|
-
|