@kntic/kntic 0.4.2 → 0.4.3
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 +1 -1
- package/src/cli.js +2 -1
- package/src/commands/update.js +42 -4
- package/src/commands/update.test.js +116 -1
- package/src/commands/usage.js +2 -1
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -30,7 +30,8 @@ if (!subcommand || subcommand === "usage") {
|
|
|
30
30
|
process.exit(1);
|
|
31
31
|
}
|
|
32
32
|
} else if (subcommand === "update") {
|
|
33
|
-
|
|
33
|
+
const updateOpts = { libOnly: args.includes("--lib-only") };
|
|
34
|
+
commands.update(updateOpts).catch((err) => {
|
|
34
35
|
console.error(`Error: ${err.message}`);
|
|
35
36
|
process.exit(1);
|
|
36
37
|
});
|
package/src/commands/update.js
CHANGED
|
@@ -182,7 +182,35 @@ function extractLibOnly(tarball, destDir) {
|
|
|
182
182
|
);
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Extract .kntic/lib/** and .kntic/adrs/** from a tarball into the destination
|
|
187
|
+
* directory. Clears both directories first, then extracts fresh content.
|
|
188
|
+
*
|
|
189
|
+
* @param {string} tarball – path to the .tar.gz file
|
|
190
|
+
* @param {string} destDir – target directory (usually ".")
|
|
191
|
+
*/
|
|
192
|
+
function extractUpdate(tarball, destDir) {
|
|
193
|
+
const libDir = path.join(destDir, ".kntic", "lib");
|
|
194
|
+
const adrsDir = path.join(destDir, ".kntic", "adrs");
|
|
195
|
+
|
|
196
|
+
// Ensure target directories exist
|
|
197
|
+
fs.mkdirSync(libDir, { recursive: true });
|
|
198
|
+
fs.mkdirSync(adrsDir, { recursive: true });
|
|
199
|
+
|
|
200
|
+
// Clear existing contents
|
|
201
|
+
clearDirectory(libDir);
|
|
202
|
+
clearDirectory(adrsDir);
|
|
203
|
+
|
|
204
|
+
// Extract both .kntic/lib/ and .kntic/adrs/ from the archive.
|
|
205
|
+
execSync(
|
|
206
|
+
`tar xzf "${tarball}" -C "${destDir}" "./.kntic/lib/" "./.kntic/adrs/"`,
|
|
207
|
+
{ stdio: "pipe" }
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async function update(options = {}) {
|
|
212
|
+
const libOnly = options.libOnly || false;
|
|
213
|
+
|
|
186
214
|
// Resolve current version from the artifact metadata file
|
|
187
215
|
const artifactFilename = await fetchText(BOOTSTRAP_ARTIFACT_URL);
|
|
188
216
|
const version = extractVersion(artifactFilename);
|
|
@@ -192,8 +220,13 @@ async function update() {
|
|
|
192
220
|
console.log(`Downloading KNTIC bootstrap archive… (v${version})`);
|
|
193
221
|
await download(BOOTSTRAP_URL, tmpFile);
|
|
194
222
|
|
|
195
|
-
|
|
196
|
-
|
|
223
|
+
if (libOnly) {
|
|
224
|
+
console.log("Updating .kntic/lib …");
|
|
225
|
+
extractLibOnly(tmpFile, ".");
|
|
226
|
+
} else {
|
|
227
|
+
console.log("Updating .kntic/lib and .kntic/adrs …");
|
|
228
|
+
extractUpdate(tmpFile, ".");
|
|
229
|
+
}
|
|
197
230
|
|
|
198
231
|
// Update KNTIC_VERSION in .kntic.env
|
|
199
232
|
updateEnvVersion(version);
|
|
@@ -202,11 +235,16 @@ async function update() {
|
|
|
202
235
|
fs.unlinkSync(tmpFile);
|
|
203
236
|
|
|
204
237
|
console.log(`@kntic/kntic@${version}`);
|
|
205
|
-
|
|
238
|
+
if (libOnly) {
|
|
239
|
+
console.log("Done. .kntic/lib updated successfully.");
|
|
240
|
+
} else {
|
|
241
|
+
console.log("Done. .kntic/lib and .kntic/adrs updated successfully.");
|
|
242
|
+
}
|
|
206
243
|
}
|
|
207
244
|
|
|
208
245
|
module.exports = update;
|
|
209
246
|
module.exports.extractLibOnly = extractLibOnly;
|
|
247
|
+
module.exports.extractUpdate = extractUpdate;
|
|
210
248
|
module.exports.extractVersion = extractVersion;
|
|
211
249
|
module.exports.clearDirectory = clearDirectory;
|
|
212
250
|
module.exports.updateEnvVersion = updateEnvVersion;
|
|
@@ -7,7 +7,7 @@ const path = require("path");
|
|
|
7
7
|
const os = require("os");
|
|
8
8
|
const { execSync } = require("child_process");
|
|
9
9
|
|
|
10
|
-
const { extractLibOnly, extractVersion, clearDirectory, updateEnvVersion } = require("./update");
|
|
10
|
+
const { extractLibOnly, extractUpdate, extractVersion, clearDirectory, updateEnvVersion } = require("./update");
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Helper — create a tar.gz archive in `tmpDir` containing the given files.
|
|
@@ -202,6 +202,121 @@ describe("extractLibOnly", () => {
|
|
|
202
202
|
});
|
|
203
203
|
});
|
|
204
204
|
|
|
205
|
+
describe("extractUpdate", () => {
|
|
206
|
+
let tmpDir;
|
|
207
|
+
let destDir;
|
|
208
|
+
|
|
209
|
+
beforeEach(() => {
|
|
210
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "kntic-test-extractupdate-"));
|
|
211
|
+
destDir = path.join(tmpDir, "dest");
|
|
212
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
afterEach(() => {
|
|
216
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("extracts both .kntic/lib and .kntic/adrs from the archive", () => {
|
|
220
|
+
const tarball = createTarball(tmpDir, {
|
|
221
|
+
".kntic/lib/orchestrator.py": "# orchestrator\n",
|
|
222
|
+
".kntic/lib/skills/validator.py": "# validator\n",
|
|
223
|
+
".kntic/adrs/ADR-001.md": "# ADR 001\n",
|
|
224
|
+
".kntic/adrs/ADR-002.md": "# ADR 002\n",
|
|
225
|
+
".kntic/MEMORY.MD": "# Memory\n",
|
|
226
|
+
"README.md": "# Hello\n",
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
extractUpdate(tarball, destDir);
|
|
230
|
+
|
|
231
|
+
// lib files must be extracted
|
|
232
|
+
assert.equal(
|
|
233
|
+
fs.readFileSync(path.join(destDir, ".kntic", "lib", "orchestrator.py"), "utf8"),
|
|
234
|
+
"# orchestrator\n"
|
|
235
|
+
);
|
|
236
|
+
assert.equal(
|
|
237
|
+
fs.readFileSync(path.join(destDir, ".kntic", "lib", "skills", "validator.py"), "utf8"),
|
|
238
|
+
"# validator\n"
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// adrs files must be extracted
|
|
242
|
+
assert.equal(
|
|
243
|
+
fs.readFileSync(path.join(destDir, ".kntic", "adrs", "ADR-001.md"), "utf8"),
|
|
244
|
+
"# ADR 001\n"
|
|
245
|
+
);
|
|
246
|
+
assert.equal(
|
|
247
|
+
fs.readFileSync(path.join(destDir, ".kntic", "adrs", "ADR-002.md"), "utf8"),
|
|
248
|
+
"# ADR 002\n"
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
// Files outside lib/adrs must NOT be extracted
|
|
252
|
+
assert.ok(
|
|
253
|
+
!fs.existsSync(path.join(destDir, ".kntic", "MEMORY.MD")),
|
|
254
|
+
"MEMORY.MD must not be extracted"
|
|
255
|
+
);
|
|
256
|
+
assert.ok(
|
|
257
|
+
!fs.existsSync(path.join(destDir, "README.md")),
|
|
258
|
+
"README.md must not be extracted"
|
|
259
|
+
);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("replaces existing .kntic/lib and .kntic/adrs content", () => {
|
|
263
|
+
const libDir = path.join(destDir, ".kntic", "lib");
|
|
264
|
+
const adrsDir = path.join(destDir, ".kntic", "adrs");
|
|
265
|
+
fs.mkdirSync(libDir, { recursive: true });
|
|
266
|
+
fs.mkdirSync(adrsDir, { recursive: true });
|
|
267
|
+
fs.writeFileSync(path.join(libDir, "old_lib.py"), "# old lib\n");
|
|
268
|
+
fs.writeFileSync(path.join(adrsDir, "ADR-OLD.md"), "# old adr\n");
|
|
269
|
+
|
|
270
|
+
const tarball = createTarball(tmpDir, {
|
|
271
|
+
".kntic/lib/new_lib.py": "# new lib\n",
|
|
272
|
+
".kntic/adrs/ADR-NEW.md": "# new adr\n",
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
extractUpdate(tarball, destDir);
|
|
276
|
+
|
|
277
|
+
// Old files must be gone
|
|
278
|
+
assert.ok(!fs.existsSync(path.join(libDir, "old_lib.py")), "old lib file must be removed");
|
|
279
|
+
assert.ok(!fs.existsSync(path.join(adrsDir, "ADR-OLD.md")), "old adr file must be removed");
|
|
280
|
+
|
|
281
|
+
// New files must be present
|
|
282
|
+
assert.equal(
|
|
283
|
+
fs.readFileSync(path.join(libDir, "new_lib.py"), "utf8"),
|
|
284
|
+
"# new lib\n"
|
|
285
|
+
);
|
|
286
|
+
assert.equal(
|
|
287
|
+
fs.readFileSync(path.join(adrsDir, "ADR-NEW.md"), "utf8"),
|
|
288
|
+
"# new adr\n"
|
|
289
|
+
);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it("preserves files outside .kntic/lib and .kntic/adrs", () => {
|
|
293
|
+
const knticDir = path.join(destDir, ".kntic");
|
|
294
|
+
fs.mkdirSync(knticDir, { recursive: true });
|
|
295
|
+
fs.writeFileSync(path.join(knticDir, "MEMORY.MD"), "# My memory\n");
|
|
296
|
+
fs.writeFileSync(path.join(destDir, "README.md"), "# My readme\n");
|
|
297
|
+
|
|
298
|
+
const tarball = createTarball(tmpDir, {
|
|
299
|
+
".kntic/lib/orchestrator.py": "# orchestrator\n",
|
|
300
|
+
".kntic/adrs/ADR-001.md": "# ADR 001\n",
|
|
301
|
+
".kntic/MEMORY.MD": "# Archive memory\n",
|
|
302
|
+
"README.md": "# Archive readme\n",
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
extractUpdate(tarball, destDir);
|
|
306
|
+
|
|
307
|
+
assert.equal(
|
|
308
|
+
fs.readFileSync(path.join(knticDir, "MEMORY.MD"), "utf8"),
|
|
309
|
+
"# My memory\n",
|
|
310
|
+
"MEMORY.MD must not be overwritten"
|
|
311
|
+
);
|
|
312
|
+
assert.equal(
|
|
313
|
+
fs.readFileSync(path.join(destDir, "README.md"), "utf8"),
|
|
314
|
+
"# My readme\n",
|
|
315
|
+
"README.md must not be overwritten"
|
|
316
|
+
);
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
205
320
|
describe("updateEnvVersion", () => {
|
|
206
321
|
let tmpDir;
|
|
207
322
|
|
package/src/commands/usage.js
CHANGED
|
@@ -9,7 +9,8 @@ function usage() {
|
|
|
9
9
|
console.log(" start Build and start KNTIC services via docker compose (uses kntic.yml + .kntic.env)");
|
|
10
10
|
console.log(" --screen Run inside a GNU screen session");
|
|
11
11
|
console.log(" stop Stop KNTIC services via docker compose");
|
|
12
|
-
console.log(" update Download the latest KNTIC bootstrap and update .kntic/lib
|
|
12
|
+
console.log(" update Download the latest KNTIC bootstrap and update .kntic/lib and .kntic/adrs");
|
|
13
|
+
console.log(" --lib-only Update only .kntic/lib (skip .kntic/adrs)");
|
|
13
14
|
console.log("");
|
|
14
15
|
}
|
|
15
16
|
|