@itznexus/itznexus-cli 1.29.0 → 1.31.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.
@@ -1,7 +1,24 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
1
3
  import { Command } from "commander";
2
4
  import chalk from "chalk";
3
5
  import { api } from "../../lib/api.js";
4
6
  import { printList, printDetail, handleError } from "../../lib/format.js";
7
+ const MIME_BY_EXTENSION = {
8
+ ".mp4": "video/mp4",
9
+ ".mov": "video/quicktime",
10
+ ".webm": "video/webm",
11
+ ".png": "image/png",
12
+ ".jpg": "image/jpeg",
13
+ ".jpeg": "image/jpeg",
14
+ ".gif": "image/gif",
15
+ ".webp": "image/webp",
16
+ ".pdf": "application/pdf",
17
+ ".md": "text/markdown",
18
+ ".txt": "text/plain",
19
+ ".json": "application/json",
20
+ ".zip": "application/zip",
21
+ };
5
22
  const listCommand = new Command("list")
6
23
  .description("List files")
7
24
  .option("--entity-type <type>", "Filter by entity type")
@@ -86,11 +103,63 @@ const uploadUrlCommand = new Command("upload-url")
86
103
  console.log(JSON.stringify(data, null, 2));
87
104
  }
88
105
  else {
89
- console.log(chalk.green("✓"), `Upload URL ready for ${chalk.bold(data.name)} (${data.id})`);
106
+ console.log(chalk.green("✓"), `Upload URL ready for ${chalk.bold(data.file.name)} (${data.file.id})`);
90
107
  console.log();
91
108
  console.log(chalk.dim("Next:"));
92
109
  console.log(chalk.dim(` 1. PUT the file bytes to:\n ${data.uploadUrl}`));
93
- console.log(chalk.dim(` 2. itznexus file confirm ${data.id}`));
110
+ console.log(chalk.dim(` 2. itznexus file confirm ${data.file.id}`));
111
+ }
112
+ }
113
+ catch (err) {
114
+ handleError(err);
115
+ }
116
+ });
117
+ const uploadCommand = new Command("upload")
118
+ .description("Upload a local file in one step (requests the signed URL, uploads the bytes, confirms)")
119
+ .argument("<path>", "Path to the local file")
120
+ .option("--name <name>", "Stored file name (defaults to the local file name)")
121
+ .option("--mime-type <type>", "MIME type (detected from the extension when omitted)")
122
+ .option("--folder <id>", "Folder ID")
123
+ .option("--entity-type <type>", 'Entity type to attach to (e.g. "lead")')
124
+ .option("--entity-id <id>", "Entity ID to attach to")
125
+ .option("--json", "Output as JSON")
126
+ .action(async (filePath, opts) => {
127
+ try {
128
+ const absolute = path.resolve(filePath);
129
+ if (!fs.existsSync(absolute)) {
130
+ throw new Error(`File not found: ${absolute}`);
131
+ }
132
+ const bytes = fs.readFileSync(absolute);
133
+ const name = opts.name ?? path.basename(absolute);
134
+ const mimeType = opts.mimeType ??
135
+ MIME_BY_EXTENSION[path.extname(absolute).toLowerCase()] ??
136
+ "application/octet-stream";
137
+ const payload = {
138
+ name,
139
+ mimeType,
140
+ size: bytes.length,
141
+ };
142
+ if (opts.folder !== undefined)
143
+ payload.folderId = opts.folder;
144
+ if (opts.entityType !== undefined)
145
+ payload.entityType = opts.entityType;
146
+ if (opts.entityId !== undefined)
147
+ payload.entityId = opts.entityId;
148
+ const requested = await api.post("/files/upload-url", payload);
149
+ const uploadRes = await fetch(requested.uploadUrl, {
150
+ method: "PUT",
151
+ headers: { "Content-Type": mimeType },
152
+ body: bytes,
153
+ });
154
+ if (!uploadRes.ok) {
155
+ throw new Error(`Upload to storage failed: ${uploadRes.status} ${uploadRes.statusText}`);
156
+ }
157
+ const data = await api.post(`/files/${requested.file.id}/confirm`, {});
158
+ if (opts.json) {
159
+ console.log(JSON.stringify(data, null, 2));
160
+ }
161
+ else {
162
+ console.log(chalk.green("✓"), `Uploaded ${chalk.bold(data.name)} (${data.id}, ${data.size} bytes)`);
94
163
  }
95
164
  }
96
165
  catch (err) {
@@ -159,6 +228,7 @@ export const fileCommand = new Command("file")
159
228
  .description("Manage files")
160
229
  .addCommand(listCommand)
161
230
  .addCommand(getCommand)
231
+ .addCommand(uploadCommand)
162
232
  .addCommand(uploadUrlCommand)
163
233
  .addCommand(confirmCommand)
164
234
  .addCommand(folderCommand)
@@ -1 +1 @@
1
- {"version":3,"file":"files.js","sourceRoot":"","sources":["../../../src/commands/api/files.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../../src/commands/api/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE1E,MAAM,iBAAiB,GAA2B;IAChD,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,iBAAiB;IACzB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,iBAAiB;IACzB,KAAK,EAAE,eAAe;IACtB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,kBAAkB;IAC3B,MAAM,EAAE,iBAAiB;CAC1B,CAAC;AAsBF,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KACpC,WAAW,CAAC,YAAY,CAAC;KACzB,MAAM,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;KACvD,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC;KACjD,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC;KAC3C,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CACL,KAAK,EAAE,IAKN,EAAE,EAAE;IACH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,UAAU;YAAE,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/D,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAErD,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,GAAG,CAAe,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAExE,SAAS,CACP,IAA4C,EAC5C;YACE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;YACzC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;YAC7C,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;YACzC,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE;YAC7C,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;SAClD,EACD,IAAI,CACL,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CACF,CAAC;AAEJ,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC;KAClC,WAAW,CAAC,mBAAmB,CAAC;KAChC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;KAC3B,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAwB,EAAE,EAAE;IACrD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,GAAG,CAAa,UAAU,EAAE,EAAE,CAAC,CAAC;QAEvD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACnC,WAAW,CACT,IAA0C,EAC1C;YACE,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;YAC1B,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE;YAClC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;YAC9B,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;YAClC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE;YACpC,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE;YAC3C,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE;YACvC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;YAC5B,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE;SACvC,EACD,IAAI,CACL,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,MAAM,gBAAgB,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC;KAC/C,WAAW,CAAC,qDAAqD,CAAC;KAClE,cAAc,CAAC,eAAe,EAAE,WAAW,CAAC;KAC5C,cAAc,CAAC,oBAAoB,EAAE,WAAW,CAAC;KACjD,cAAc,CAAC,gBAAgB,EAAE,eAAe,EAAE,QAAQ,CAAC;KAC3D,MAAM,CAAC,eAAe,EAAE,WAAW,CAAC;KACpC,MAAM,CAAC,sBAAsB,EAAE,aAAa,CAAC;KAC7C,MAAM,CAAC,kBAAkB,EAAE,WAAW,CAAC;KACvC,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CACL,KAAK,EAAE,IAQN,EAAE,EAAE;IACH,IAAI,CAAC;QACH,MAAM,OAAO,GAA4B;YACvC,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC;QACF,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;QAC9D,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;YAAE,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACxE,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;YAAE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAElE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CACzB,mBAAmB,EACnB,OAAO,CACR,CAAC;QAEF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAChB,wBAAwB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CACvE,CAAC;YACF,OAAO,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YAChC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CAAC,qCAAqC,IAAI,CAAC,SAAS,EAAE,CAAC,CACjE,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CACF,CAAC;AAEJ,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KACxC,WAAW,CACV,wFAAwF,CACzF;KACA,QAAQ,CAAC,QAAQ,EAAE,wBAAwB,CAAC;KAC5C,MAAM,CAAC,eAAe,EAAE,oDAAoD,CAAC;KAC7E,MAAM,CACL,oBAAoB,EACpB,sDAAsD,CACvD;KACA,MAAM,CAAC,eAAe,EAAE,WAAW,CAAC;KACpC,MAAM,CAAC,sBAAsB,EAAE,wCAAwC,CAAC;KACxE,MAAM,CAAC,kBAAkB,EAAE,wBAAwB,CAAC;KACpD,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CACL,KAAK,EACH,QAAgB,EAChB,IAOC,EACD,EAAE;IACF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,QAAQ,GACZ,IAAI,CAAC,QAAQ;YACb,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;YACvD,0BAA0B,CAAC;QAE7B,MAAM,OAAO,GAA4B;YACvC,IAAI;YACJ,QAAQ;YACR,IAAI,EAAE,KAAK,CAAC,MAAM;SACnB,CAAC;QACF,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;QAC9D,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;YAAE,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACxE,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;YAAE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAElE,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,IAAI,CAC9B,mBAAmB,EACnB,OAAO,CACR,CAAC;QAEF,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE;YACjD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE;YACrC,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;QACH,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb,6BAA6B,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,UAAU,EAAE,CACxE,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CACzB,UAAU,SAAS,CAAC,IAAI,CAAC,EAAE,UAAU,EACrC,EAAE,CACH,CAAC;QAEF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAChB,YAAY,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,SAAS,CACrE,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CACF,CAAC;AAEJ,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KAC1C,WAAW,CAAC,mDAAmD,CAAC;KAChE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;KAC3B,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAwB,EAAE,EAAE;IACrD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAa,UAAU,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QAEpE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAChB,mBAAmB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3C,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KACxC,WAAW,CAAC,yBAAyB,CAAC;KACtC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;KAC3B,QAAQ,CAAC,YAAY,EAAE,0CAA0C,CAAC;KAClE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,QAAgB,EAAE,IAAwB,EAAE,EAAE;IACvE,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;QACpD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAa,UAAU,EAAE,SAAS,EAAE;YAC7D,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KACxC,WAAW,CAAC,eAAe,CAAC;KAC5B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;KAC3B,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAwB,EAAE,EAAE;IACrD,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAEjC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,cAAc,CAAC;KAC3B,UAAU,CAAC,WAAW,CAAC;KACvB,UAAU,CAAC,UAAU,CAAC;KACtB,UAAU,CAAC,aAAa,CAAC;KACzB,UAAU,CAAC,gBAAgB,CAAC;KAC5B,UAAU,CAAC,cAAc,CAAC;KAC1B,UAAU,CAAC,aAAa,CAAC;KACzB,UAAU,CAAC,aAAa,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const instructionsCommand: Command;
@@ -0,0 +1,134 @@
1
+ import fs from "node:fs";
2
+ import { Command } from "commander";
3
+ import chalk from "chalk";
4
+ import { api } from "../../lib/api.js";
5
+ import { printList, handleError } from "../../lib/format.js";
6
+ async function findByPath(projectId, filePath) {
7
+ const rows = await api.get(`/projects/${projectId}/agent-instructions`);
8
+ return rows.find((r) => r.path === filePath);
9
+ }
10
+ const listCommand = new Command("list")
11
+ .description("List the project's agent instruction files")
12
+ .argument("<id>", "Project ID or key (e.g. NEX)")
13
+ .option("--json", "Output as JSON")
14
+ .action(async (id, opts) => {
15
+ try {
16
+ const data = await api.get(`/projects/${id}/agent-instructions`);
17
+ printList(data, [
18
+ { key: "path", label: "Path", width: 40 },
19
+ { key: "template", label: "Template", width: 10 },
20
+ { key: "name", label: "Name", width: 24 },
21
+ { key: "id", label: "ID", width: 38 },
22
+ ], opts);
23
+ }
24
+ catch (err) {
25
+ handleError(err);
26
+ }
27
+ });
28
+ const templatesCommand = new Command("templates")
29
+ .description("List the code-defined templates an instruction file can start from")
30
+ .argument("<id>", "Project ID or key (e.g. NEX)")
31
+ .option("--json", "Output as JSON")
32
+ .action(async (id, opts) => {
33
+ try {
34
+ const data = await api.get(`/projects/${id}/agent-instructions/templates`);
35
+ printList(data, [
36
+ { key: "name", label: "Name", width: 10 },
37
+ { key: "title", label: "Default title", width: 24 },
38
+ { key: "titleOverridable", label: "Name allowed", width: 12 },
39
+ { key: "description", label: "Description", width: 60 },
40
+ ], opts);
41
+ }
42
+ catch (err) {
43
+ handleError(err);
44
+ }
45
+ });
46
+ const setCommand = new Command("set")
47
+ .description("Create or update the agent instruction file at a path. Only the provided options change; content and template are independent.")
48
+ .argument("<id>", "Project ID or key (e.g. NEX)")
49
+ .argument("<path>", "File path relative to the project folder (root files like CLAUDE.md, or <repo>/CLAUDE.local.md)")
50
+ .option("--template <name>", 'Template to render above the content (see `instructions templates`); "none" to clear')
51
+ .option("--name <name>", 'File title, rendered as the "# ..." heading; needs a template with an overridable title; "none" to clear')
52
+ .option("--content <text>", "Free-text content appended below the template")
53
+ .option("--content-file <file>", "Read the content from a local file")
54
+ .option("--json", "Output as JSON")
55
+ .action(async (id, filePath, opts) => {
56
+ if (opts.content !== undefined && opts.contentFile !== undefined) {
57
+ console.error(chalk.red("✗"), "Provide --content or --content-file, not both.");
58
+ process.exit(1);
59
+ }
60
+ let content;
61
+ if (opts.contentFile !== undefined) {
62
+ if (!fs.existsSync(opts.contentFile)) {
63
+ console.error(chalk.red("✗"), `File not found: ${opts.contentFile}`);
64
+ process.exit(1);
65
+ }
66
+ content = fs.readFileSync(opts.contentFile, "utf-8").trim() || null;
67
+ }
68
+ else if (opts.content !== undefined) {
69
+ content = opts.content.trim() || null;
70
+ }
71
+ const template = opts.template === undefined
72
+ ? undefined
73
+ : opts.template === "none"
74
+ ? null
75
+ : opts.template;
76
+ const name = opts.name === undefined
77
+ ? undefined
78
+ : opts.name === "none"
79
+ ? null
80
+ : opts.name;
81
+ if (template === undefined &&
82
+ name === undefined &&
83
+ content === undefined) {
84
+ console.error(chalk.red("✗"), "Nothing to set: provide --template, --name, --content, or --content-file.");
85
+ process.exit(1);
86
+ }
87
+ try {
88
+ const existing = await findByPath(id, filePath);
89
+ const data = existing
90
+ ? await api.post(`/projects/${id}/agent-instructions/${existing.id}`, { template, name, content })
91
+ : await api.post(`/projects/${id}/agent-instructions`, {
92
+ path: filePath,
93
+ template: template ?? undefined,
94
+ name: name ?? undefined,
95
+ content: content ?? undefined,
96
+ });
97
+ if (opts.json)
98
+ console.log(JSON.stringify(data, null, 2));
99
+ else
100
+ console.log(chalk.green("✓"), `${existing ? "Updated" : "Created"} ${chalk.bold(data.path)}${data.template ? ` (template: ${data.template})` : ""}. Run \`itznexus project sync\` in the project folder to materialize it.`);
101
+ }
102
+ catch (err) {
103
+ handleError(err);
104
+ }
105
+ });
106
+ const deleteCommand = new Command("delete")
107
+ .description("Delete the agent instruction file at a path; the local file disappears on the next sync")
108
+ .argument("<id>", "Project ID or key (e.g. NEX)")
109
+ .argument("<path>", "File path, e.g. itznexus-api/CLAUDE.local.md")
110
+ .option("--json", "Output as JSON")
111
+ .action(async (id, filePath, opts) => {
112
+ try {
113
+ const existing = await findByPath(id, filePath);
114
+ if (!existing) {
115
+ console.error(chalk.red("✗"), `No agent instruction file at "${filePath}".`);
116
+ process.exit(1);
117
+ }
118
+ const data = await api.delete(`/projects/${id}/agent-instructions/${existing.id}`);
119
+ if (opts.json)
120
+ console.log(JSON.stringify(data, null, 2));
121
+ else
122
+ console.log(chalk.green("✓"), `Deleted ${chalk.bold(filePath)}. Run \`itznexus project sync\` to remove the local file.`);
123
+ }
124
+ catch (err) {
125
+ handleError(err);
126
+ }
127
+ });
128
+ export const instructionsCommand = new Command("instructions")
129
+ .description("Manage the project's agent instruction files (path-addressed, optionally template-based), materialized by `itznexus project sync`")
130
+ .addCommand(listCommand)
131
+ .addCommand(templatesCommand)
132
+ .addCommand(setCommand)
133
+ .addCommand(deleteCommand);
134
+ //# sourceMappingURL=project-instructions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-instructions.js","sourceRoot":"","sources":["../../../src/commands/api/project-instructions.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,8 @@ import { Command } from "commander";
5
5
  import chalk from "chalk";
6
6
  import { api } from "../../lib/api.js";
7
7
  import { printList, printDetail, handleError } from "../../lib/format.js";
8
- import { CLAUDE_MD_CONFLICT_MESSAGE, fetchAgentContext, fetchProjectBySlug, hasHandWrittenClaudeMd, shortId, syncRepoInstructions, writeClaudeMd, } from "../../lib/project-context.js";
8
+ import { cleanupStaleInstructionFiles, fetchProjectBySlug, fetchRenderedInstructions, findInstructionConflicts, syncInstructionFiles, } from "../../lib/project-context.js";
9
+ import { instructionsCommand } from "./project-instructions.js";
9
10
  const listCommand = new Command("list")
10
11
  .description("List all projects")
11
12
  .option("--status <status>", "Filter by status (draft, active, paused, completed, cancelled)")
@@ -26,9 +27,10 @@ const listCommand = new Command("list")
26
27
  printList(data, [
27
28
  { key: "name", label: "Name", width: 30 },
28
29
  { key: "key", label: "Key", width: 12 },
30
+ { key: "organizationName", label: "Organization", width: 20 },
29
31
  { key: "status", label: "Status", width: 12 },
30
32
  { key: "sprintCount", label: "Sprints", width: 10 },
31
- { key: "createdAt", label: "Created", width: 24 },
33
+ { key: "lastActivityAt", label: "Activity", width: 24 },
32
34
  ], opts);
33
35
  }
34
36
  catch (err) {
@@ -215,43 +217,6 @@ const technicalDescriptionCommand = new Command("technical-description")
215
217
  handleError(err);
216
218
  }
217
219
  });
218
- const projectSetInstructionsCommand = new Command("set-instructions")
219
- .description("Set the project's agent instructions, rendered verbatim as the <instructions> section of the agent context (root CLAUDE.md)")
220
- .argument("<id>", "Project ID or key (e.g. NEX)")
221
- .argument("[instructions]", "Instruction text (or use --file / --clear)")
222
- .option("--file <path>", "Read instructions from a file")
223
- .option("--clear", "Clear the instructions")
224
- .option("--json", "Output as JSON")
225
- .action(async (id, instructions, opts) => {
226
- const sources = [instructions, opts.file, opts.clear].filter((v) => v !== undefined && v !== false);
227
- if (sources.length !== 1) {
228
- console.error(chalk.red("✗"), "Provide exactly one of: instruction text, --file <path>, or --clear.");
229
- process.exit(1);
230
- }
231
- let value = null;
232
- if (opts.file) {
233
- if (!fs.existsSync(opts.file)) {
234
- console.error(chalk.red("✗"), `File not found: ${opts.file}`);
235
- process.exit(1);
236
- }
237
- value = fs.readFileSync(opts.file, "utf-8").trim() || null;
238
- }
239
- else if (instructions !== undefined) {
240
- value = instructions.trim() || null;
241
- }
242
- try {
243
- const data = await api.post(`/projects/${id}/agent-instructions`, { agentInstructions: value });
244
- if (opts.json)
245
- console.log(JSON.stringify(data, null, 2));
246
- else
247
- console.log(chalk.green("✓"), value
248
- ? `Agent instructions set for ${chalk.bold(data.name)} (${value.length} chars). Run \`itznexus project sync\` in the project folder to refresh CLAUDE.md.`
249
- : `Agent instructions cleared for ${chalk.bold(data.name)}. Run \`itznexus project sync\` to refresh CLAUDE.md.`);
250
- }
251
- catch (err) {
252
- handleError(err);
253
- }
254
- });
255
220
  const organizationCommand = new Command("organization")
256
221
  .description("Set project organization")
257
222
  .argument("<id>", "Project ID or key (e.g. NEX)")
@@ -458,32 +423,27 @@ const dossierCommand = new Command("dossier")
458
423
  handleError(err);
459
424
  }
460
425
  });
461
- // Prints per-repo CLAUDE.local.md sync outcomes and returns true when any repo
462
- // errored (tracked file, ignore rule not applying), so callers can exit non-zero.
463
- function reportRepoInstructions(results) {
426
+ // Prints per-file sync outcomes and returns true when any file errored
427
+ // (tracked file, ignore rule not applying), so callers can exit non-zero.
428
+ function reportInstructionFiles(results, removed) {
464
429
  let hasError = false;
465
430
  for (const r of results) {
466
431
  switch (r.status) {
467
432
  case "written":
468
- console.log(chalk.green("✓"), `${r.repo}/CLAUDE.local.md synced${r.gitignoreUpdated ? " (.gitignore updated)" : ""}`);
469
- break;
470
- case "removed":
471
- console.log(chalk.green("✓"), `${r.repo}/CLAUDE.local.md removed (instructions cleared in Nexus)`);
433
+ console.log(chalk.green("\u2713"), `${r.path} synced${r.gitignoreUpdated ? " (.gitignore updated)" : ""}`);
472
434
  break;
473
435
  case "skipped-no-folder":
474
- console.error(chalk.yellow("!"), `${r.repo}: has agent instructions but is not cloned here, skipping`);
475
- break;
476
- case "skipped-not-git":
477
- console.error(chalk.yellow("!"), `${r.repo}: folder exists but is not a git repo, skipping CLAUDE.local.md`);
436
+ console.error(chalk.yellow("!"), `${r.path}: repo folder is not cloned here, skipping`);
478
437
  break;
479
438
  case "error":
480
439
  hasError = true;
481
- console.error(chalk.red("✗"), `${r.repo}: ${r.error}`);
482
- break;
483
- case "unchanged":
440
+ console.error(chalk.red("\u2717"), `${r.path}: ${r.error}`);
484
441
  break;
485
442
  }
486
443
  }
444
+ for (const rel of removed) {
445
+ console.log(chalk.green("\u2713"), `${rel} removed (deleted in Nexus)`);
446
+ }
487
447
  return hasError;
488
448
  }
489
449
  function git(args, cwd) {
@@ -495,27 +455,32 @@ function cloneUrl(repo, https) {
495
455
  : `git@github.com:${repo.owner}/${repo.name}.git`;
496
456
  }
497
457
  const syncCommand = new Command("sync")
498
- .description("Sync the project folder from Nexus: clone missing repositories, write ./CLAUDE.md (agent context), and overwrite each repo's gitignored CLAUDE.local.md from its Nexus agent instructions. Existing repos' git state is never touched. Run inside the project folder; slug defaults to the folder name.")
458
+ .description("Sync the project folder from Nexus: clone missing repositories and materialize the project's agent instruction files (root CLAUDE.md, gitignored CLAUDE.local.md inside repos). Nexus-managed files are overwritten and files deleted in Nexus are removed; existing repos' git state is never touched. Run inside the project folder; slug defaults to the folder name.")
499
459
  .argument("[slug]", "Project slug (defaults to the current folder name)")
500
460
  .option("--https", "Clone over HTTPS instead of SSH")
501
461
  .option("--all", "Include archived repositories")
502
- .option("--force", "Overwrite CLAUDE.md even if it is not a Nexus-managed context block")
462
+ .option("--force", "Overwrite instruction files that exist but are not Nexus-managed")
503
463
  .option("--json", "Output as JSON")
504
464
  .action(async (slug, opts) => {
505
465
  const cwd = process.cwd();
506
466
  const resolvedSlug = (slug ?? path.basename(cwd)).trim();
507
467
  if (!resolvedSlug) {
508
- console.error(chalk.red("✗"), "Could not determine a project slug.");
509
- process.exit(1);
510
- }
511
- // Fail fast before cloning anything: never clobber a hand-written CLAUDE.md.
512
- if (!opts.force && hasHandWrittenClaudeMd(cwd)) {
513
- console.error(chalk.red("✗"), CLAUDE_MD_CONFLICT_MESSAGE);
468
+ console.error(chalk.red("\u2717"), "Could not determine a project slug.");
514
469
  process.exit(1);
515
470
  }
516
471
  try {
517
472
  const project = await fetchProjectBySlug(resolvedSlug);
518
- const context = await fetchAgentContext(project.id);
473
+ const files = await fetchRenderedInstructions(project.id);
474
+ // Fail fast before cloning anything: never clobber hand-written files.
475
+ if (!opts.force) {
476
+ const conflicts = findInstructionConflicts(cwd, files);
477
+ if (conflicts.length > 0) {
478
+ for (const rel of conflicts) {
479
+ console.error(chalk.red("\u2717"), `${rel} exists and is not Nexus-managed. Pass --force to overwrite.`);
480
+ }
481
+ process.exit(1);
482
+ }
483
+ }
519
484
  const archivedSkipped = opts.all
520
485
  ? []
521
486
  : project.repositories.filter((r) => r.archived);
@@ -530,7 +495,7 @@ const syncCommand = new Command("sync")
530
495
  if (fs.existsSync(path.join(cwd, repo.name)))
531
496
  continue;
532
497
  if (!opts.json)
533
- console.log(chalk.dim(`\n→ ${repo.name} (clone)`));
498
+ console.log(chalk.dim(`\n\u2192 ${repo.name} (clone)`));
534
499
  if (git(["clone", cloneUrl(repo, !!opts.https), repo.name], cwd)) {
535
500
  cloned.push(repo.name);
536
501
  }
@@ -538,13 +503,9 @@ const syncCommand = new Command("sync")
538
503
  failed.push(repo.name);
539
504
  }
540
505
  }
541
- const { created, replacedProjectId } = writeClaudeMd(cwd, context, shortId(project.id));
542
- if (replacedProjectId && !opts.json) {
543
- console.error(chalk.yellow("!"), `Replacing context for a different project (was ${replacedProjectId}, now ${shortId(project.id)}).`);
544
- }
545
- const repoInstructions = syncRepoInstructions(cwd, repos);
546
- const hasError = failed.length > 0 ||
547
- repoInstructions.some((r) => r.status === "error");
506
+ const fileResults = syncInstructionFiles(cwd, files);
507
+ const removed = cleanupStaleInstructionFiles(cwd, files, repos.map((r) => r.name));
508
+ const hasError = failed.length > 0 || fileResults.some((r) => r.status === "error");
548
509
  const label = project.key ?? project.name;
549
510
  if (opts.json) {
550
511
  console.log(JSON.stringify({
@@ -556,24 +517,25 @@ const syncCommand = new Command("sync")
556
517
  cloned,
557
518
  failed,
558
519
  archivedSkipped: archivedSkipped.map((r) => r.name),
559
- claudeMd: { created },
560
- repoInstructions,
520
+ files: fileResults,
521
+ removed,
561
522
  }));
562
523
  if (hasError)
563
524
  process.exitCode = 1;
564
525
  return;
565
526
  }
566
- console.log(chalk.green("\n✓"), `Synced ${chalk.bold(label)} in ${cwd}`);
527
+ console.log(chalk.green("\n\u2713"), `Synced ${chalk.bold(label)} in ${cwd}`);
528
+ const written = fileResults.filter((r) => r.status === "written").length;
567
529
  const parts = [
568
- `CLAUDE.md ${created ? "created" : "updated"}`,
530
+ `${written}/${files.length} instruction files`,
569
531
  `${cloned.length} cloned`,
570
532
  ];
571
533
  if (failed.length)
572
534
  parts.push(chalk.red(`${failed.length} clone failed`));
573
535
  if (archivedSkipped.length)
574
536
  parts.push(chalk.dim(`${archivedSkipped.length} archived (use --all)`));
575
- console.log(chalk.dim(` ${parts.join(" · ")}`));
576
- reportRepoInstructions(repoInstructions);
537
+ console.log(chalk.dim(` ${parts.join(" \u00b7 ")}`));
538
+ reportInstructionFiles(fileResults, removed);
577
539
  if (hasError)
578
540
  process.exitCode = 1;
579
541
  }
@@ -1013,7 +975,7 @@ export const projectCommand = new Command("project")
1013
975
  .addCommand(nameCommand)
1014
976
  .addCommand(descriptionCommand)
1015
977
  .addCommand(technicalDescriptionCommand)
1016
- .addCommand(projectSetInstructionsCommand)
978
+ .addCommand(instructionsCommand)
1017
979
  .addCommand(organizationCommand)
1018
980
  .addCommand(personCommand)
1019
981
  .addCommand(leadCommand)