@curenorway/kode-cli 1.12.1 → 1.14.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.
@@ -1229,13 +1229,16 @@ Full documentation: [.cure-kode/KODE.md](.cure-kode/KODE.md)
1229
1229
  function hasKodeReference(content) {
1230
1230
  return content.includes(".cure-kode/KODE.md") || content.includes("cure-kode/KODE.md") || content.includes("KODE.md");
1231
1231
  }
1232
- function generateKodeMd(siteName, siteSlug, scripts, pages) {
1232
+ function generateKodeMd(siteName, siteSlug, scripts, pages, options) {
1233
+ const productionEnabled = options?.productionEnabled ?? false;
1233
1234
  let md = `# Cure Kode: ${siteName}
1234
1235
 
1235
1236
  This project uses **Cure Kode** CDN for JavaScript/CSS delivery to Webflow.
1236
1237
 
1237
1238
  > **This file is auto-generated.** Do not edit manually - changes will be overwritten by \`kode pull\`, \`kode push\`, and \`kode sync\`.
1238
1239
 
1240
+ **Produksjon:** ${productionEnabled ? "\u2713 Aktivert \u2014 deploy til staging og produksjon" : "\u25CB Deaktivert \u2014 kun staging. Ikke hent fra produksjons-URL."}
1241
+
1239
1242
  ---
1240
1243
 
1241
1244
  `;
@@ -1288,6 +1291,29 @@ Page-specific scripts only load when URL matches these patterns:
1288
1291
  `;
1289
1292
  }
1290
1293
  md += `
1294
+ `;
1295
+ }
1296
+ const pageSpecificScripts = scripts.filter(
1297
+ (s) => s.scope === "page-specific" && s.pageAssignments && s.pageAssignments.length > 0
1298
+ );
1299
+ if (pageSpecificScripts.length > 0) {
1300
+ md += `---
1301
+
1302
+ ## Script \u2192 Page Assignments
1303
+
1304
+ | Script | Pages |
1305
+ |--------|-------|
1306
+ `;
1307
+ for (const script of pageSpecificScripts) {
1308
+ const pageList = script.pageAssignments.map((pa) => {
1309
+ const page = pages.find((p) => p.slug === pa.pageSlug);
1310
+ const patterns = page ? ` (\`${page.patterns.join("`, `")}\`)` : "";
1311
+ return `\`${pa.pageSlug}\`${patterns}`;
1312
+ }).join(", ");
1313
+ md += `| \`${script.slug}\` | ${pageList} |
1314
+ `;
1315
+ }
1316
+ md += `
1291
1317
  `;
1292
1318
  }
1293
1319
  md += `---
@@ -1371,27 +1397,34 @@ function ensureClaudeMdReference(projectRoot) {
1371
1397
  writeFileSync3(claudeMdPath, newContent);
1372
1398
  return { created: false, updated: true, skipped: false };
1373
1399
  }
1374
- function updateKodeMd(projectRoot, siteName, siteSlug, scripts, pages) {
1400
+ function updateKodeMd(projectRoot, siteName, siteSlug, scripts, pages, options) {
1375
1401
  const kodeMdPath = join3(projectRoot, ".cure-kode", "KODE.md");
1376
1402
  const existed = existsSync3(kodeMdPath);
1377
- const content = generateKodeMd(siteName, siteSlug, scripts, pages);
1403
+ const content = generateKodeMd(siteName, siteSlug, scripts, pages, options);
1378
1404
  writeFileSync3(kodeMdPath, content);
1379
1405
  return { created: !existed, updated: existed };
1380
1406
  }
1381
- function updateKodeDocs(projectRoot, siteName, siteSlug, scripts, pages) {
1382
- const kodeMd = updateKodeMd(projectRoot, siteName, siteSlug, scripts, pages);
1407
+ function updateKodeDocs(projectRoot, siteName, siteSlug, scripts, pages, options) {
1408
+ const kodeMd = updateKodeMd(projectRoot, siteName, siteSlug, scripts, pages, options);
1383
1409
  const claudeMd = ensureClaudeMdReference(projectRoot);
1384
1410
  return { kodeMd, claudeMd };
1385
1411
  }
1386
- function scriptsToDocsFormat(scripts) {
1387
- return scripts.map((s) => ({
1388
- slug: s.slug,
1389
- name: s.name,
1390
- type: s.type,
1391
- scope: s.scope,
1392
- autoLoad: s.auto_load,
1393
- purpose: s.metadata?.purpose || s.description
1394
- }));
1412
+ function scriptsToDocsFormat(scripts, pages) {
1413
+ return scripts.map((s) => {
1414
+ const pageAssignments = (s.pages || []).filter((p) => p.is_enabled).map((p) => {
1415
+ const page = pages?.find((pg) => pg.id === p.page_id);
1416
+ return page ? { pageId: page.id, pageSlug: page.slug, pageName: page.name } : null;
1417
+ }).filter((p) => p !== null);
1418
+ return {
1419
+ slug: s.slug,
1420
+ name: s.name,
1421
+ type: s.type,
1422
+ scope: s.scope,
1423
+ autoLoad: s.auto_load,
1424
+ purpose: s.metadata?.purpose || s.description,
1425
+ pageAssignments: pageAssignments.length > 0 ? pageAssignments : void 0
1426
+ };
1427
+ });
1395
1428
  }
1396
1429
  function pagesToInfoFormat(pages) {
1397
1430
  return pages.filter((p) => p.is_active).map((p) => ({
@@ -1563,13 +1596,17 @@ config.json
1563
1596
  spinner.start("Genererer AI-dokumentasjon...");
1564
1597
  let scripts = [];
1565
1598
  let pages = [];
1599
+ let productionEnabled = false;
1566
1600
  try {
1567
- const [scriptsResponse, pagesResponse] = await Promise.all([
1601
+ const [scriptsResponse, pagesResponse, prodResponse] = await Promise.all([
1568
1602
  fetch(`https://app.cure.no/api/cdn/sites/${site.id}/scripts`, {
1569
1603
  headers: { "X-API-Key": apiKey }
1570
1604
  }),
1571
1605
  fetch(`https://app.cure.no/api/cdn/sites/${site.id}/pages`, {
1572
1606
  headers: { "X-API-Key": apiKey }
1607
+ }),
1608
+ fetch(`https://app.cure.no/api/cdn/sites/${site.id}/production`, {
1609
+ headers: { "X-API-Key": apiKey }
1573
1610
  })
1574
1611
  ]);
1575
1612
  if (scriptsResponse.ok) {
@@ -1578,14 +1615,19 @@ config.json
1578
1615
  if (pagesResponse.ok) {
1579
1616
  pages = await pagesResponse.json();
1580
1617
  }
1618
+ if (prodResponse.ok) {
1619
+ const prodData = await prodResponse.json();
1620
+ productionEnabled = prodData.production_enabled ?? false;
1621
+ }
1581
1622
  } catch {
1582
1623
  }
1583
1624
  const docsResult = updateKodeDocs(
1584
1625
  cwd,
1585
1626
  config.siteName,
1586
1627
  config.siteSlug,
1587
- scriptsToDocsFormat(scripts),
1588
- pagesToInfoFormat(pages)
1628
+ scriptsToDocsFormat(scripts, pages),
1629
+ pagesToInfoFormat(pages),
1630
+ { productionEnabled }
1589
1631
  );
1590
1632
  const siteInfo = {
1591
1633
  domain: site.domain,
@@ -2034,10 +2076,19 @@ Fant ikke skript "${options.script}".`));
2034
2076
  if (skipped > 0) {
2035
2077
  console.log(chalk2.dim(`Hoppet over ${skipped} skript`));
2036
2078
  }
2079
+ let pages = [];
2080
+ try {
2081
+ pages = await client.listPages(config.siteId);
2082
+ } catch {
2083
+ }
2037
2084
  const now = (/* @__PURE__ */ new Date()).toISOString();
2038
2085
  const metadata = scripts.map((s) => {
2039
2086
  const filePath = join5(scriptsDir, `${s.slug}.${s.type === "javascript" ? "js" : "css"}`);
2040
2087
  const localContent = existsSync5(filePath) ? readFileSync5(filePath, "utf-8") : s.content;
2088
+ const pageAssignments = (s.pages || []).filter((p) => p.is_enabled).map((p) => {
2089
+ const page = pages.find((pg) => pg.id === p.page_id);
2090
+ return page ? { pageId: page.id, pageSlug: page.slug, pageName: page.name } : null;
2091
+ }).filter((p) => p !== null);
2041
2092
  return {
2042
2093
  id: s.id,
2043
2094
  slug: s.slug,
@@ -2047,6 +2098,7 @@ Fant ikke skript "${options.script}".`));
2047
2098
  autoLoad: s.auto_load,
2048
2099
  version: s.current_version,
2049
2100
  loadOrder: s.load_order,
2101
+ pageAssignments: pageAssignments.length > 0 ? pageAssignments : void 0,
2050
2102
  lastPulledVersion: s.current_version,
2051
2103
  lastPulledAt: now,
2052
2104
  contentHash: hashContent(localContent)
@@ -2054,12 +2106,11 @@ Fant ikke skript "${options.script}".`));
2054
2106
  });
2055
2107
  writeFileSync5(metadataPath, JSON.stringify(metadata, null, 2));
2056
2108
  try {
2057
- const pages = await client.listPages(config.siteId);
2058
2109
  const result = updateClaudeMd(
2059
2110
  projectRoot,
2060
2111
  config.siteName,
2061
2112
  config.siteSlug,
2062
- scriptsToDocsFormat(scripts),
2113
+ scriptsToDocsFormat(scripts, pages),
2063
2114
  pagesToInfoFormat(pages)
2064
2115
  );
2065
2116
  if (result.kodeMd.created) {
@@ -2233,12 +2284,21 @@ ${conflicts} skript med konflikter (bruk --force for \xE5 overskrive)`));
2233
2284
  ${emptyScriptCount} tomme skript lastet opp`));
2234
2285
  console.log(chalk3.dim("Tomme skript har ingen effekt ved deploy."));
2235
2286
  }
2287
+ let pages = [];
2288
+ try {
2289
+ pages = await client.listPages(config.siteId);
2290
+ } catch {
2291
+ }
2236
2292
  const updatedScripts = await client.listScripts(config.siteId);
2237
2293
  const now = (/* @__PURE__ */ new Date()).toISOString();
2238
2294
  const updatedMetadata = updatedScripts.map((s) => {
2239
2295
  const ext = s.type === "javascript" ? "js" : "css";
2240
2296
  const filePath = join6(scriptsDir, `${s.slug}.${ext}`);
2241
2297
  const localContent = existsSync6(filePath) ? readFileSync6(filePath, "utf-8") : s.content;
2298
+ const pageAssignments = (s.pages || []).filter((p) => p.is_enabled).map((p) => {
2299
+ const page = pages.find((pg) => pg.id === p.page_id);
2300
+ return page ? { pageId: page.id, pageSlug: page.slug, pageName: page.name } : null;
2301
+ }).filter((p) => p !== null);
2242
2302
  return {
2243
2303
  id: s.id,
2244
2304
  slug: s.slug,
@@ -2248,6 +2308,7 @@ ${emptyScriptCount} tomme skript lastet opp`));
2248
2308
  autoLoad: s.auto_load,
2249
2309
  version: s.current_version,
2250
2310
  loadOrder: s.load_order,
2311
+ pageAssignments: pageAssignments.length > 0 ? pageAssignments : void 0,
2251
2312
  lastPulledVersion: s.current_version,
2252
2313
  lastPulledAt: now,
2253
2314
  contentHash: hashContent2(localContent)
@@ -2255,12 +2316,11 @@ ${emptyScriptCount} tomme skript lastet opp`));
2255
2316
  });
2256
2317
  writeFileSync6(metadataPath, JSON.stringify(updatedMetadata, null, 2));
2257
2318
  try {
2258
- const pages = await client.listPages(config.siteId);
2259
2319
  const result = updateClaudeMd(
2260
2320
  projectRoot,
2261
2321
  config.siteName,
2262
2322
  config.siteSlug,
2263
- scriptsToDocsFormat(updatedScripts),
2323
+ scriptsToDocsFormat(updatedScripts, pages),
2264
2324
  pagesToInfoFormat(pages)
2265
2325
  );
2266
2326
  if (result.kodeMd.created) {
package/dist/cli.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  updateClaudeMd,
22
22
  updateKodeDocs,
23
23
  watchCommand
24
- } from "./chunk-NQ7RJJNI.js";
24
+ } from "./chunk-I7TVOZJR.js";
25
25
 
26
26
  // src/cli.ts
27
27
  import { Command } from "commander";
@@ -65,7 +65,7 @@ async function upgradeCommand() {
65
65
  projectRoot,
66
66
  config.siteName,
67
67
  config.siteSlug,
68
- scriptsToDocsFormat(scripts),
68
+ scriptsToDocsFormat(scripts, pages),
69
69
  pagesToInfoFormat(pages)
70
70
  );
71
71
  if (result.kodeMd.created) {
@@ -836,17 +836,19 @@ async function updateClaudeMdCommand() {
836
836
  const spinner = ora5("Henter skript og sider...").start();
837
837
  try {
838
838
  const client = createApiClient(config);
839
- const [scripts, pages] = await Promise.all([
839
+ const [scripts, pages, deployStatus] = await Promise.all([
840
840
  client.listScripts(config.siteId),
841
- client.listPages(config.siteId)
841
+ client.listPages(config.siteId),
842
+ client.getDeploymentStatus(config.siteId).catch(() => null)
842
843
  ]);
843
844
  spinner.succeed(`Fant ${scripts.length} skript og ${pages.length} sider`);
844
845
  const result = updateKodeDocs(
845
846
  projectRoot,
846
847
  config.siteName,
847
848
  config.siteSlug,
848
- scriptsToDocsFormat(scripts),
849
- pagesToInfoFormat(pages)
849
+ scriptsToDocsFormat(scripts, pages),
850
+ pagesToInfoFormat(pages),
851
+ { productionEnabled: deployStatus?.productionEnabled ?? false }
850
852
  );
851
853
  if (result.kodeMd.created) {
852
854
  console.log(chalk6.green("\u2705 Opprettet .cure-kode/KODE.md"));
@@ -1077,11 +1079,20 @@ async function syncCommand(options) {
1077
1079
  console.log(chalk7.dim(' Bruk "kode pull --force <script>" for \xE5 overskrive lokalt'));
1078
1080
  }
1079
1081
  const updatedScripts = await client.listScripts(config.siteId);
1082
+ let pages = [];
1083
+ try {
1084
+ pages = await client.listPages(config.siteId);
1085
+ } catch {
1086
+ }
1080
1087
  const now = (/* @__PURE__ */ new Date()).toISOString();
1081
1088
  const updatedMetadata = updatedScripts.map((s) => {
1082
1089
  const ext = s.type === "javascript" ? "js" : "css";
1083
1090
  const filePath = join2(scriptsDir, `${s.slug}.${ext}`);
1084
1091
  const localContent = existsSync2(filePath) ? readFileSync2(filePath, "utf-8") : s.content;
1092
+ const pageAssignments = (s.pages || []).filter((p) => p.is_enabled).map((p) => {
1093
+ const page = pages.find((pg) => pg.id === p.page_id);
1094
+ return page ? { pageId: page.id, pageSlug: page.slug, pageName: page.name } : null;
1095
+ }).filter((p) => p !== null);
1085
1096
  return {
1086
1097
  id: s.id,
1087
1098
  slug: s.slug,
@@ -1091,6 +1102,7 @@ async function syncCommand(options) {
1091
1102
  autoLoad: s.auto_load,
1092
1103
  version: s.current_version,
1093
1104
  loadOrder: s.load_order,
1105
+ pageAssignments: pageAssignments.length > 0 ? pageAssignments : void 0,
1094
1106
  lastPulledVersion: s.current_version,
1095
1107
  lastPulledAt: now,
1096
1108
  contentHash: hashContent(localContent)
package/dist/index.d.ts CHANGED
@@ -66,6 +66,10 @@ interface CdnScript {
66
66
  current_version: number;
67
67
  is_active: boolean;
68
68
  load_order: number;
69
+ pages?: Array<{
70
+ page_id: string;
71
+ is_enabled: boolean;
72
+ }>;
69
73
  }
70
74
  interface CdnPage {
71
75
  id: string;
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  updateScriptPurpose,
28
28
  watchCommand,
29
29
  writeContext
30
- } from "./chunk-NQ7RJJNI.js";
30
+ } from "./chunk-I7TVOZJR.js";
31
31
  export {
32
32
  KodeApiClient,
33
33
  KodeApiError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curenorway/kode-cli",
3
- "version": "1.12.1",
3
+ "version": "1.14.0",
4
4
  "description": "CLI for Cure Kode CDN - manage, deploy, and sync JS/CSS scripts for Webflow sites with AI agent support",
5
5
  "type": "module",
6
6
  "bin": {