@fluid-app/fluid-cli-assets 0.1.31 → 0.1.33
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 +34 -6
- package/src/generated/index.ts +1 -4
- package/src/generated/primary.ts +25 -82
- package/.turbo/turbo-build.log +0 -18
- package/.turbo/turbo-typecheck.log +0 -4
- package/dist/index.d.mts +0 -7
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluid-app/fluid-cli-assets",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.33",
|
|
4
4
|
"description": "Fluid CLI commands for digital asset management (DAM)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -17,20 +17,48 @@
|
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"
|
|
21
|
-
"
|
|
20
|
+
"@fluid-app/fluid-cli": "0.1.31",
|
|
21
|
+
"commander": "^12.0.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
+
"@fluid-app/api-client-scripts": "0.0.0",
|
|
25
|
+
"@fluid-app/typescript-config": "0.0.0",
|
|
24
26
|
"@types/node": "24.10.12",
|
|
25
27
|
"tsdown": "^0.21.0",
|
|
26
28
|
"tsx": "^4.21.0",
|
|
27
|
-
"typescript": "^5"
|
|
28
|
-
"@fluid-app/api-client-scripts": "0.0.0",
|
|
29
|
-
"@fluid-app/typescript-config": "0.0.0"
|
|
29
|
+
"typescript": "^5"
|
|
30
30
|
},
|
|
31
31
|
"engines": {
|
|
32
32
|
"node": ">=18.0.0"
|
|
33
33
|
},
|
|
34
|
+
"nx": {
|
|
35
|
+
"implicitDependencies": [
|
|
36
|
+
"@fluid-app/fluid-cli-specs"
|
|
37
|
+
],
|
|
38
|
+
"targets": {
|
|
39
|
+
"typecheck": {
|
|
40
|
+
"dependsOn": [
|
|
41
|
+
{
|
|
42
|
+
"target": "build",
|
|
43
|
+
"projects": [
|
|
44
|
+
"@fluid-app/fluid-cli"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
"build": {
|
|
50
|
+
"dependsOn": [
|
|
51
|
+
"typecheck",
|
|
52
|
+
{
|
|
53
|
+
"target": "build",
|
|
54
|
+
"projects": [
|
|
55
|
+
"@fluid-app/fluid-cli"
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
34
62
|
"scripts": {
|
|
35
63
|
"build": "tsdown",
|
|
36
64
|
"dev": "tsdown --watch",
|
package/src/generated/index.ts
CHANGED
|
@@ -4,9 +4,6 @@ import type { CommandContext } from "@fluid-app/fluid-cli";
|
|
|
4
4
|
|
|
5
5
|
import { registerPrimary } from "./primary.js";
|
|
6
6
|
|
|
7
|
-
export function registerAllCommands(
|
|
8
|
-
parent: Command,
|
|
9
|
-
ctx: CommandContext,
|
|
10
|
-
): void {
|
|
7
|
+
export function registerAllCommands(parent: Command, ctx: CommandContext): void {
|
|
11
8
|
registerPrimary(parent, ctx);
|
|
12
9
|
}
|
package/src/generated/primary.ts
CHANGED
|
@@ -3,15 +3,13 @@ import { Command } from "commander";
|
|
|
3
3
|
import type { CommandContext } from "@fluid-app/fluid-cli";
|
|
4
4
|
|
|
5
5
|
export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
6
|
+
|
|
6
7
|
parent
|
|
7
8
|
.command("get-asset-paths <code>")
|
|
8
9
|
.description("Lists asset paths for an existing asset")
|
|
9
10
|
.action(async (code) => {
|
|
10
11
|
const client = await ctx.getClient();
|
|
11
|
-
if (ctx.verbose)
|
|
12
|
-
process.stderr.write(
|
|
13
|
-
"GET " + `/api/dam/assets/${code}/asset_paths` + "\n",
|
|
14
|
-
);
|
|
12
|
+
if (ctx.verbose) process.stderr.write("GET " + `/api/dam/assets/${code}/asset_paths` + "\n");
|
|
15
13
|
const result = await client.get(`/api/dam/assets/${code}/asset_paths`);
|
|
16
14
|
ctx.output(result);
|
|
17
15
|
});
|
|
@@ -30,14 +28,8 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
30
28
|
} else if (opts.body) {
|
|
31
29
|
body = ctx.parseBody(opts.body);
|
|
32
30
|
}
|
|
33
|
-
if (ctx.verbose)
|
|
34
|
-
|
|
35
|
-
"POST " + `/api/dam/assets/${code}/asset_paths` + "\n",
|
|
36
|
-
);
|
|
37
|
-
const result = await client.post(
|
|
38
|
-
`/api/dam/assets/${code}/asset_paths`,
|
|
39
|
-
body,
|
|
40
|
-
);
|
|
31
|
+
if (ctx.verbose) process.stderr.write("POST " + `/api/dam/assets/${code}/asset_paths` + "\n");
|
|
32
|
+
const result = await client.post(`/api/dam/assets/${code}/asset_paths`, body);
|
|
41
33
|
ctx.output(result);
|
|
42
34
|
});
|
|
43
35
|
|
|
@@ -46,13 +38,8 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
46
38
|
.description("Destroys an asset path")
|
|
47
39
|
.action(async (code, id) => {
|
|
48
40
|
const client = await ctx.getClient();
|
|
49
|
-
if (ctx.verbose)
|
|
50
|
-
|
|
51
|
-
"DELETE " + `/api/dam/assets/${code}/asset_paths/${id}` + "\n",
|
|
52
|
-
);
|
|
53
|
-
const result = await client.delete(
|
|
54
|
-
`/api/dam/assets/${code}/asset_paths/${id}`,
|
|
55
|
-
);
|
|
41
|
+
if (ctx.verbose) process.stderr.write("DELETE " + `/api/dam/assets/${code}/asset_paths/${id}` + "\n");
|
|
42
|
+
const result = await client.delete(`/api/dam/assets/${code}/asset_paths/${id}`);
|
|
56
43
|
ctx.output(result);
|
|
57
44
|
});
|
|
58
45
|
|
|
@@ -70,14 +57,8 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
70
57
|
} else if (opts.body) {
|
|
71
58
|
body = ctx.parseBody(opts.body);
|
|
72
59
|
}
|
|
73
|
-
if (ctx.verbose)
|
|
74
|
-
|
|
75
|
-
"POST " + `/api/dam/assets/backfill_imagekit` + "\n",
|
|
76
|
-
);
|
|
77
|
-
const result = await client.post(
|
|
78
|
-
`/api/dam/assets/backfill_imagekit`,
|
|
79
|
-
body,
|
|
80
|
-
);
|
|
60
|
+
if (ctx.verbose) process.stderr.write("POST " + `/api/dam/assets/backfill_imagekit` + "\n");
|
|
61
|
+
const result = await client.post(`/api/dam/assets/backfill_imagekit`, body);
|
|
81
62
|
ctx.output(result);
|
|
82
63
|
});
|
|
83
64
|
|
|
@@ -105,8 +86,7 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
105
86
|
.description("Retrieves an asset by code")
|
|
106
87
|
.action(async (code) => {
|
|
107
88
|
const client = await ctx.getClient();
|
|
108
|
-
if (ctx.verbose)
|
|
109
|
-
process.stderr.write("GET " + `/api/dam/assets/${code}` + "\n");
|
|
89
|
+
if (ctx.verbose) process.stderr.write("GET " + `/api/dam/assets/${code}` + "\n");
|
|
110
90
|
const result = await client.get(`/api/dam/assets/${code}`);
|
|
111
91
|
ctx.output(result);
|
|
112
92
|
});
|
|
@@ -125,8 +105,7 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
125
105
|
} else if (opts.body) {
|
|
126
106
|
body = ctx.parseBody(opts.body);
|
|
127
107
|
}
|
|
128
|
-
if (ctx.verbose)
|
|
129
|
-
process.stderr.write("PUT " + `/api/dam/assets/${code}` + "\n");
|
|
108
|
+
if (ctx.verbose) process.stderr.write("PUT " + `/api/dam/assets/${code}` + "\n");
|
|
130
109
|
const result = await client.put(`/api/dam/assets/${code}`, body);
|
|
131
110
|
ctx.output(result);
|
|
132
111
|
});
|
|
@@ -136,8 +115,7 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
136
115
|
.description("Deletes an asset")
|
|
137
116
|
.action(async (code) => {
|
|
138
117
|
const client = await ctx.getClient();
|
|
139
|
-
if (ctx.verbose)
|
|
140
|
-
process.stderr.write("DELETE " + `/api/dam/assets/${code}` + "\n");
|
|
118
|
+
if (ctx.verbose) process.stderr.write("DELETE " + `/api/dam/assets/${code}` + "\n");
|
|
141
119
|
const result = await client.delete(`/api/dam/assets/${code}`);
|
|
142
120
|
ctx.output(result);
|
|
143
121
|
});
|
|
@@ -147,23 +125,17 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
147
125
|
.description("Discard an asset (soft delete)")
|
|
148
126
|
.action(async (code) => {
|
|
149
127
|
const client = await ctx.getClient();
|
|
150
|
-
if (ctx.verbose)
|
|
151
|
-
process.stderr.write(
|
|
152
|
-
"PATCH " + `/api/dam/assets/${code}/discard` + "\n",
|
|
153
|
-
);
|
|
128
|
+
if (ctx.verbose) process.stderr.write("PATCH " + `/api/dam/assets/${code}/discard` + "\n");
|
|
154
129
|
const result = await client.patch(`/api/dam/assets/${code}/discard`);
|
|
155
130
|
ctx.output(result);
|
|
156
131
|
});
|
|
157
132
|
|
|
158
133
|
parent
|
|
159
134
|
.command("create-imagekit-auth")
|
|
160
|
-
.description(
|
|
161
|
-
"Creates ImageKit authentication credentials for large file uploads",
|
|
162
|
-
)
|
|
135
|
+
.description("Creates ImageKit authentication credentials for large file uploads")
|
|
163
136
|
.action(async () => {
|
|
164
137
|
const client = await ctx.getClient();
|
|
165
|
-
if (ctx.verbose)
|
|
166
|
-
process.stderr.write("POST " + `/api/dam/assets/imagekit_auth` + "\n");
|
|
138
|
+
if (ctx.verbose) process.stderr.write("POST " + `/api/dam/assets/imagekit_auth` + "\n");
|
|
167
139
|
const result = await client.post(`/api/dam/assets/imagekit_auth`);
|
|
168
140
|
ctx.output(result);
|
|
169
141
|
});
|
|
@@ -192,10 +164,7 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
192
164
|
.description("Returns all variants for an existing asset")
|
|
193
165
|
.action(async (code) => {
|
|
194
166
|
const client = await ctx.getClient();
|
|
195
|
-
if (ctx.verbose)
|
|
196
|
-
process.stderr.write(
|
|
197
|
-
"GET " + `/api/dam/assets/${code}/variants` + "\n",
|
|
198
|
-
);
|
|
167
|
+
if (ctx.verbose) process.stderr.write("GET " + `/api/dam/assets/${code}/variants` + "\n");
|
|
199
168
|
const result = await client.get(`/api/dam/assets/${code}/variants`);
|
|
200
169
|
ctx.output(result);
|
|
201
170
|
});
|
|
@@ -214,14 +183,8 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
214
183
|
} else if (opts.body) {
|
|
215
184
|
body = ctx.parseBody(opts.body);
|
|
216
185
|
}
|
|
217
|
-
if (ctx.verbose)
|
|
218
|
-
|
|
219
|
-
"POST " + `/api/dam/assets/${code}/variants` + "\n",
|
|
220
|
-
);
|
|
221
|
-
const result = await client.post(
|
|
222
|
-
`/api/dam/assets/${code}/variants`,
|
|
223
|
-
body,
|
|
224
|
-
);
|
|
186
|
+
if (ctx.verbose) process.stderr.write("POST " + `/api/dam/assets/${code}/variants` + "\n");
|
|
187
|
+
const result = await client.post(`/api/dam/assets/${code}/variants`, body);
|
|
225
188
|
ctx.output(result);
|
|
226
189
|
});
|
|
227
190
|
|
|
@@ -230,10 +193,7 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
230
193
|
.description("Returns a specific variant for an existing asset")
|
|
231
194
|
.action(async (code, id) => {
|
|
232
195
|
const client = await ctx.getClient();
|
|
233
|
-
if (ctx.verbose)
|
|
234
|
-
process.stderr.write(
|
|
235
|
-
"GET " + `/api/dam/assets/${code}/variants/${id}` + "\n",
|
|
236
|
-
);
|
|
196
|
+
if (ctx.verbose) process.stderr.write("GET " + `/api/dam/assets/${code}/variants/${id}` + "\n");
|
|
237
197
|
const result = await client.get(`/api/dam/assets/${code}/variants/${id}`);
|
|
238
198
|
ctx.output(result);
|
|
239
199
|
});
|
|
@@ -252,14 +212,8 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
252
212
|
} else if (opts.body) {
|
|
253
213
|
body = ctx.parseBody(opts.body);
|
|
254
214
|
}
|
|
255
|
-
if (ctx.verbose)
|
|
256
|
-
|
|
257
|
-
"PUT " + `/api/dam/assets/${code}/variants/${id}` + "\n",
|
|
258
|
-
);
|
|
259
|
-
const result = await client.put(
|
|
260
|
-
`/api/dam/assets/${code}/variants/${id}`,
|
|
261
|
-
body,
|
|
262
|
-
);
|
|
215
|
+
if (ctx.verbose) process.stderr.write("PUT " + `/api/dam/assets/${code}/variants/${id}` + "\n");
|
|
216
|
+
const result = await client.put(`/api/dam/assets/${code}/variants/${id}`, body);
|
|
263
217
|
ctx.output(result);
|
|
264
218
|
});
|
|
265
219
|
|
|
@@ -268,13 +222,8 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
268
222
|
.description("Destroys a variant for an existing asset")
|
|
269
223
|
.action(async (code, id) => {
|
|
270
224
|
const client = await ctx.getClient();
|
|
271
|
-
if (ctx.verbose)
|
|
272
|
-
|
|
273
|
-
"DELETE " + `/api/dam/assets/${code}/variants/${id}` + "\n",
|
|
274
|
-
);
|
|
275
|
-
const result = await client.delete(
|
|
276
|
-
`/api/dam/assets/${code}/variants/${id}`,
|
|
277
|
-
);
|
|
225
|
+
if (ctx.verbose) process.stderr.write("DELETE " + `/api/dam/assets/${code}/variants/${id}` + "\n");
|
|
226
|
+
const result = await client.delete(`/api/dam/assets/${code}/variants/${id}`);
|
|
278
227
|
ctx.output(result);
|
|
279
228
|
});
|
|
280
229
|
|
|
@@ -283,15 +232,9 @@ export function registerPrimary(parent: Command, ctx: CommandContext): void {
|
|
|
283
232
|
.description("Discards a variant for an existing asset (soft delete)")
|
|
284
233
|
.action(async (assetCode, id) => {
|
|
285
234
|
const client = await ctx.getClient();
|
|
286
|
-
if (ctx.verbose)
|
|
287
|
-
|
|
288
|
-
"PATCH " +
|
|
289
|
-
`/api/dam/assets/${assetCode}/variants/${id}/discard` +
|
|
290
|
-
"\n",
|
|
291
|
-
);
|
|
292
|
-
const result = await client.patch(
|
|
293
|
-
`/api/dam/assets/${assetCode}/variants/${id}/discard`,
|
|
294
|
-
);
|
|
235
|
+
if (ctx.verbose) process.stderr.write("PATCH " + `/api/dam/assets/${assetCode}/variants/${id}/discard` + "\n");
|
|
236
|
+
const result = await client.patch(`/api/dam/assets/${assetCode}/variants/${id}/discard`);
|
|
295
237
|
ctx.output(result);
|
|
296
238
|
});
|
|
239
|
+
|
|
297
240
|
}
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> @fluid-app/fluid-cli-assets@0.1.31 build /home/runner/_work/fluid-mono/fluid-mono/packages/cli/assets
|
|
3
|
-
> tsdown
|
|
4
|
-
|
|
5
|
-
[34mℹ[39m tsdown [2mv0.21.0[22m powered by rolldown [2mv1.0.0-rc.7[22m
|
|
6
|
-
[34mℹ[39m config file: [4m/home/runner/_work/fluid-mono/fluid-mono/packages/cli/assets/tsdown.config.ts[24m
|
|
7
|
-
[34mℹ[39m entry: [34msrc/index.ts[39m
|
|
8
|
-
[34mℹ[39m target: [34mnode24[39m
|
|
9
|
-
[34mℹ[39m tsconfig: [34mtsconfig.json[39m
|
|
10
|
-
[34mℹ[39m Build start
|
|
11
|
-
[34mℹ[39m [2mdist/[22m[1mindex.mjs[22m [2m12.11 kB[22m [2m│ gzip: 2.54 kB[22m
|
|
12
|
-
[34mℹ[39m [2mdist/[22mindex.mjs.map [2m26.57 kB[22m [2m│ gzip: 5.83 kB[22m
|
|
13
|
-
[34mℹ[39m [2mdist/[22mindex.d.mts.map [2m 0.11 kB[22m [2m│ gzip: 0.12 kB[22m
|
|
14
|
-
[34mℹ[39m [2mdist/[22m[32m[1mindex.d.mts[22m[39m [2m 0.19 kB[22m [2m│ gzip: 0.16 kB[22m
|
|
15
|
-
[34mℹ[39m 4 files, total: 38.99 kB
|
|
16
|
-
[33m[PLUGIN_TIMINGS] Warning:[0m Your build spent significant time in plugin `rolldown-plugin-dts:generate`. See https://rolldown.rs/options/checks#plugintimings for more details.
|
|
17
|
-
|
|
18
|
-
[32m✔[39m Build complete in [32m5382ms[39m
|
package/dist/index.d.mts
DELETED
package/dist/index.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;cAMM,MAAA,EAAQ,WAAA"}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/commands/upload.ts","../src/generated/primary.ts","../src/generated/index.ts","../src/index.ts"],"sourcesContent":["/**\n * `fluid assets upload` / `fluid dam upload` — wraps the\n * `upload.fluid.app/upload` Cloud Run service (../file-upload-\n * serverless) so users can drop a file or external URL onto the\n * Fluid DAM in one step instead of stitching together the three\n * underlying API calls (imagekit_auth → ImageKit → backfill_imagekit).\n *\n * Two input modes:\n * - Positional `<file>` path → multipart upload from disk.\n * - `--url <url>` → service-side fetch + upload.\n *\n * Auth comes from the same --token / --profile / env / active-profile\n * resolution path the rest of the CLI uses; we re-implement the\n * resolve here instead of going through `ctx.getClient()` because\n * the DAM upload service lives on a different host than the\n * regular Fluid API and we just need the bearer to forward.\n */\nimport { Command } from \"commander\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\nimport { findProjectConfig, getAuthToken } from \"@fluid-app/fluid-cli\";\nimport type { CommandContext } from \"@fluid-app/fluid-cli\";\n\n// Hard-coded — the bearer token we forward is the user's Fluid API\n// token, so the destination MUST be a Fluid-controlled host or any\n// `--upload-base evil.example` would exfiltrate it. We previously\n// shipped a `--upload-base` override for local-dev convenience; if\n// you're running the upload service locally, point at it via the\n// FLUID_UPLOAD_BASE env var instead (read at process start, not\n// from an end-user-typed argv string).\nconst UPLOAD_BASE = (\n process.env[\"FLUID_UPLOAD_BASE\"] ?? \"https://upload.fluid.app\"\n).replace(/\\/$/, \"\");\n\ninterface UploadOptions {\n url?: string;\n name?: string;\n description?: string;\n tags?: string;\n folder?: string;\n /**\n * commander maps `--no-unique-filename` onto `uniqueFilename: false`.\n * Default is true so the service keeps its existing behavior unless\n * the user explicitly opts out.\n */\n uniqueFilename: boolean;\n createMedia?: boolean;\n}\n\nexport function registerUpload(parent: Command, ctx: CommandContext): void {\n parent\n .command(\"upload [file]\")\n .description(\"Upload a file or URL to the Fluid DAM (via upload.fluid.app)\")\n .option(\n \"--url <url>\",\n \"Fetch from an external URL instead of attaching a local file\",\n )\n .option(\"--name <name>\", \"Display name for the DAM asset\")\n .option(\"--description <description>\", \"Asset description\")\n .option(\"--tags <tags>\", \"Comma-separated tags\")\n .option(\"--folder <folder>\", \"ImageKit folder override\")\n .option(\n \"--no-unique-filename\",\n \"Disable ImageKit's useUniqueFileName (default: enabled)\",\n )\n .option(\n \"--create-media\",\n \"Also create a Fluid Media resource (active, share, publish-now)\",\n )\n .action(async function (\n this: Command,\n filePath: string | undefined,\n opts: UploadOptions,\n ) {\n // --token / --profile live on the parent `assets` domain\n // command (createDomainCommand sets them there). Reach up to\n // pick them up here so the user can write\n // fluid dam --token X upload ./photo.jpg\n const parentOpts = (this.parent?.opts() ?? {}) as {\n token?: string;\n profile?: string;\n };\n const token = resolveToken(parentOpts);\n if (!token) {\n throw new Error(\n \"No API token found. Run `fluid login` or provide --token <token>.\",\n );\n }\n\n if (!filePath && !opts.url) {\n throw new Error(\n \"Provide a file path or --url <url>. Run `fluid dam upload --help` for usage.\",\n );\n }\n if (filePath && opts.url) {\n throw new Error(\"Provide either a file path OR --url, not both.\");\n }\n\n // Multipart order matters for streaming uploads (>~100 MB).\n // The service streams `file` straight through to ImageKit, so\n // any field ImageKit needs (`fileName`, `folder`,\n // `useUniqueFileName`) must arrive BEFORE the file part.\n // Fields consumed after upload (`name`, `description`, `tags`,\n // `create_media`) can sit anywhere — we put them last for\n // readability.\n const form = new FormData();\n if (opts.folder) form.append(\"folder\", opts.folder);\n if (opts.uniqueFilename === false) {\n form.append(\"useUniqueFileName\", \"false\");\n }\n\n if (opts.url) {\n form.append(\"external_asset_url\", opts.url);\n } else if (filePath) {\n // Validate first — `readFile` errors are friendlier than the\n // service returning a generic 500 for a missing file.\n await stat(filePath);\n const bytes = await readFile(filePath);\n const name = basename(filePath);\n form.append(\"fileName\", name);\n // Wrap as a Blob so the global fetch's multipart serializer\n // emits a proper Content-Disposition with filename. Node 20+\n // global FormData accepts (Blob, filename) pairs.\n form.append(\"file\", new Blob([bytes]), name);\n }\n\n if (opts.name) form.append(\"name\", opts.name);\n if (opts.description) form.append(\"description\", opts.description);\n if (opts.tags) form.append(\"tags\", opts.tags);\n if (opts.createMedia) form.append(\"create_media\", \"true\");\n\n if (ctx.verbose) {\n process.stderr.write(`POST ${UPLOAD_BASE}/upload\\n`);\n }\n\n const resp = await fetch(`${UPLOAD_BASE}/upload`, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${token}` },\n body: form,\n });\n\n if (!resp.ok) {\n let detail = \"\";\n try {\n detail = await resp.text();\n } catch {\n // No body or unreadable — error message stays generic.\n }\n throw new Error(\n `Upload failed (HTTP ${resp.status})${\n detail ? `: ${detail.slice(0, 400)}` : \"\"\n }`,\n );\n }\n\n const body: unknown = await resp.json();\n ctx.output(body);\n });\n}\n\n/**\n * Token resolution mirrors `createCommandContext.resolveToken` from\n * @fluid-app/fluid-cli: explicit flag → --profile lookup → env vars\n * → project-local `.fluidrc` → global active profile. Re-implemented\n * here instead of imported because the helper isn't exported, and\n * the duplication is tiny.\n */\nfunction resolveToken(opts: {\n token?: string;\n profile?: string;\n}): string | null {\n if (opts.token) return opts.token;\n if (opts.profile) return getAuthToken(opts.profile);\n const envToken = process.env[\"FLUID_TOKEN\"] ?? process.env[\"FLUID_API_TOKEN\"];\n if (envToken) return envToken;\n const projectConfig = findProjectConfig(process.cwd());\n if (projectConfig?.profile) {\n const rcToken = getAuthToken(projectConfig.profile);\n if (rcToken) return rcToken;\n }\n return getAuthToken();\n}\n","// primary.ts — AUTO-GENERATED, DO NOT EDIT\nimport { Command } from \"commander\";\nimport type { CommandContext } from \"@fluid-app/fluid-cli\";\n\nexport function registerPrimary(parent: Command, ctx: CommandContext): void {\n parent\n .command(\"get-asset-paths <code>\")\n .description(\"Lists asset paths for an existing asset\")\n .action(async (code) => {\n const client = await ctx.getClient();\n if (ctx.verbose)\n process.stderr.write(\n \"GET \" + `/api/dam/assets/${code}/asset_paths` + \"\\n\",\n );\n const result = await client.get(`/api/dam/assets/${code}/asset_paths`);\n ctx.output(result);\n });\n\n parent\n .command(\"create-asset-paths <code>\")\n .description(\"Creates asset paths for an existing asset\")\n .option(\"--body <json>\", \"Request body as JSON string\")\n .option(\"--body-file <path>\", \"Read request body from file\")\n .action(async (code, opts) => {\n const client = await ctx.getClient();\n let body: unknown;\n if (opts.bodyFile) {\n const { readFileSync } = await import(\"fs\");\n body = ctx.parseBody(readFileSync(opts.bodyFile, \"utf-8\"));\n } else if (opts.body) {\n body = ctx.parseBody(opts.body);\n }\n if (ctx.verbose)\n process.stderr.write(\n \"POST \" + `/api/dam/assets/${code}/asset_paths` + \"\\n\",\n );\n const result = await client.post(\n `/api/dam/assets/${code}/asset_paths`,\n body,\n );\n ctx.output(result);\n });\n\n parent\n .command(\"delete-asset-path <code> <id>\")\n .description(\"Destroys an asset path\")\n .action(async (code, id) => {\n const client = await ctx.getClient();\n if (ctx.verbose)\n process.stderr.write(\n \"DELETE \" + `/api/dam/assets/${code}/asset_paths/${id}` + \"\\n\",\n );\n const result = await client.delete(\n `/api/dam/assets/${code}/asset_paths/${id}`,\n );\n ctx.output(result);\n });\n\n parent\n .command(\"create-backfill-imagekit\")\n .description(\"Creates a DAM asset from ImageKit upload metadata\")\n .option(\"--body <json>\", \"Request body as JSON string\")\n .option(\"--body-file <path>\", \"Read request body from file\")\n .action(async (opts) => {\n const client = await ctx.getClient();\n let body: unknown;\n if (opts.bodyFile) {\n const { readFileSync } = await import(\"fs\");\n body = ctx.parseBody(readFileSync(opts.bodyFile, \"utf-8\"));\n } else if (opts.body) {\n body = ctx.parseBody(opts.body);\n }\n if (ctx.verbose)\n process.stderr.write(\n \"POST \" + `/api/dam/assets/backfill_imagekit` + \"\\n\",\n );\n const result = await client.post(\n `/api/dam/assets/backfill_imagekit`,\n body,\n );\n ctx.output(result);\n });\n\n parent\n .command(\"create-asset-invalid-mixed-payload\")\n .description(\"Errors when multiple asset types are provided\")\n .option(\"--body <json>\", \"Request body as JSON string\")\n .option(\"--body-file <path>\", \"Read request body from file\")\n .action(async (opts) => {\n const client = await ctx.getClient();\n let body: unknown;\n if (opts.bodyFile) {\n const { readFileSync } = await import(\"fs\");\n body = ctx.parseBody(readFileSync(opts.bodyFile, \"utf-8\"));\n } else if (opts.body) {\n body = ctx.parseBody(opts.body);\n }\n if (ctx.verbose) process.stderr.write(\"POST \" + `/api/dam/assets` + \"\\n\");\n const result = await client.post(`/api/dam/assets`, body);\n ctx.output(result);\n });\n\n parent\n .command(\"get-asset <code>\")\n .description(\"Retrieves an asset by code\")\n .action(async (code) => {\n const client = await ctx.getClient();\n if (ctx.verbose)\n process.stderr.write(\"GET \" + `/api/dam/assets/${code}` + \"\\n\");\n const result = await client.get(`/api/dam/assets/${code}`);\n ctx.output(result);\n });\n\n parent\n .command(\"update-asset <code>\")\n .description(\"Updates an existing asset\")\n .option(\"--body <json>\", \"Request body as JSON string\")\n .option(\"--body-file <path>\", \"Read request body from file\")\n .action(async (code, opts) => {\n const client = await ctx.getClient();\n let body: unknown;\n if (opts.bodyFile) {\n const { readFileSync } = await import(\"fs\");\n body = ctx.parseBody(readFileSync(opts.bodyFile, \"utf-8\"));\n } else if (opts.body) {\n body = ctx.parseBody(opts.body);\n }\n if (ctx.verbose)\n process.stderr.write(\"PUT \" + `/api/dam/assets/${code}` + \"\\n\");\n const result = await client.put(`/api/dam/assets/${code}`, body);\n ctx.output(result);\n });\n\n parent\n .command(\"delete-asset <code>\")\n .description(\"Deletes an asset\")\n .action(async (code) => {\n const client = await ctx.getClient();\n if (ctx.verbose)\n process.stderr.write(\"DELETE \" + `/api/dam/assets/${code}` + \"\\n\");\n const result = await client.delete(`/api/dam/assets/${code}`);\n ctx.output(result);\n });\n\n parent\n .command(\"discard-asset <code>\")\n .description(\"Discard an asset (soft delete)\")\n .action(async (code) => {\n const client = await ctx.getClient();\n if (ctx.verbose)\n process.stderr.write(\n \"PATCH \" + `/api/dam/assets/${code}/discard` + \"\\n\",\n );\n const result = await client.patch(`/api/dam/assets/${code}/discard`);\n ctx.output(result);\n });\n\n parent\n .command(\"create-imagekit-auth\")\n .description(\n \"Creates ImageKit authentication credentials for large file uploads\",\n )\n .action(async () => {\n const client = await ctx.getClient();\n if (ctx.verbose)\n process.stderr.write(\"POST \" + `/api/dam/assets/imagekit_auth` + \"\\n\");\n const result = await client.post(`/api/dam/assets/imagekit_auth`);\n ctx.output(result);\n });\n\n parent\n .command(\"query-assets\")\n .description(\"Query DAM assets using tree paths and tags\")\n .option(\"--body <json>\", \"Request body as JSON string\")\n .option(\"--body-file <path>\", \"Read request body from file\")\n .action(async (opts) => {\n const client = await ctx.getClient();\n let body: unknown;\n if (opts.bodyFile) {\n const { readFileSync } = await import(\"fs\");\n body = ctx.parseBody(readFileSync(opts.bodyFile, \"utf-8\"));\n } else if (opts.body) {\n body = ctx.parseBody(opts.body);\n }\n if (ctx.verbose) process.stderr.write(\"POST \" + `/api/dam/query` + \"\\n\");\n const result = await client.post(`/api/dam/query`, body);\n ctx.output(result);\n });\n\n parent\n .command(\"list-variants <code>\")\n .description(\"Returns all variants for an existing asset\")\n .action(async (code) => {\n const client = await ctx.getClient();\n if (ctx.verbose)\n process.stderr.write(\n \"GET \" + `/api/dam/assets/${code}/variants` + \"\\n\",\n );\n const result = await client.get(`/api/dam/assets/${code}/variants`);\n ctx.output(result);\n });\n\n parent\n .command(\"create-variants <code>\")\n .description(\"Creates variants for an existing asset\")\n .option(\"--body <json>\", \"Request body as JSON string\")\n .option(\"--body-file <path>\", \"Read request body from file\")\n .action(async (code, opts) => {\n const client = await ctx.getClient();\n let body: unknown;\n if (opts.bodyFile) {\n const { readFileSync } = await import(\"fs\");\n body = ctx.parseBody(readFileSync(opts.bodyFile, \"utf-8\"));\n } else if (opts.body) {\n body = ctx.parseBody(opts.body);\n }\n if (ctx.verbose)\n process.stderr.write(\n \"POST \" + `/api/dam/assets/${code}/variants` + \"\\n\",\n );\n const result = await client.post(\n `/api/dam/assets/${code}/variants`,\n body,\n );\n ctx.output(result);\n });\n\n parent\n .command(\"get-variant <code> <id>\")\n .description(\"Returns a specific variant for an existing asset\")\n .action(async (code, id) => {\n const client = await ctx.getClient();\n if (ctx.verbose)\n process.stderr.write(\n \"GET \" + `/api/dam/assets/${code}/variants/${id}` + \"\\n\",\n );\n const result = await client.get(`/api/dam/assets/${code}/variants/${id}`);\n ctx.output(result);\n });\n\n parent\n .command(\"update-variant <code> <id>\")\n .description(\"Updates tags for a specific variant\")\n .option(\"--body <json>\", \"Request body as JSON string\")\n .option(\"--body-file <path>\", \"Read request body from file\")\n .action(async (code, id, opts) => {\n const client = await ctx.getClient();\n let body: unknown;\n if (opts.bodyFile) {\n const { readFileSync } = await import(\"fs\");\n body = ctx.parseBody(readFileSync(opts.bodyFile, \"utf-8\"));\n } else if (opts.body) {\n body = ctx.parseBody(opts.body);\n }\n if (ctx.verbose)\n process.stderr.write(\n \"PUT \" + `/api/dam/assets/${code}/variants/${id}` + \"\\n\",\n );\n const result = await client.put(\n `/api/dam/assets/${code}/variants/${id}`,\n body,\n );\n ctx.output(result);\n });\n\n parent\n .command(\"delete-variant <code> <id>\")\n .description(\"Destroys a variant for an existing asset\")\n .action(async (code, id) => {\n const client = await ctx.getClient();\n if (ctx.verbose)\n process.stderr.write(\n \"DELETE \" + `/api/dam/assets/${code}/variants/${id}` + \"\\n\",\n );\n const result = await client.delete(\n `/api/dam/assets/${code}/variants/${id}`,\n );\n ctx.output(result);\n });\n\n parent\n .command(\"discard-variant <asset-code> <id>\")\n .description(\"Discards a variant for an existing asset (soft delete)\")\n .action(async (assetCode, id) => {\n const client = await ctx.getClient();\n if (ctx.verbose)\n process.stderr.write(\n \"PATCH \" +\n `/api/dam/assets/${assetCode}/variants/${id}/discard` +\n \"\\n\",\n );\n const result = await client.patch(\n `/api/dam/assets/${assetCode}/variants/${id}/discard`,\n );\n ctx.output(result);\n });\n}\n","// index.ts — AUTO-GENERATED, DO NOT EDIT\nimport { Command } from \"commander\";\nimport type { CommandContext } from \"@fluid-app/fluid-cli\";\n\nimport { registerPrimary } from \"./primary.js\";\n\nexport function registerAllCommands(\n parent: Command,\n ctx: CommandContext,\n): void {\n registerPrimary(parent, ctx);\n}\n","import type { FluidPlugin } from \"@fluid-app/fluid-cli\";\nimport { createDomainCommand } from \"@fluid-app/fluid-cli\";\n\nimport { registerUpload } from \"./commands/upload.js\";\nimport { registerAllCommands } from \"./generated/index.js\";\n\nconst plugin: FluidPlugin = {\n name: \"@fluid-app/fluid-cli-assets\",\n version: \"0.1.0\",\n register(ctx) {\n const assets = createDomainCommand(\n \"assets\",\n \"Manage Fluid digital assets (DAM)\",\n (parent, cmdCtx) => {\n registerAllCommands(parent, cmdCtx);\n // Hand-written ergonomic command on top of the generated\n // OpenAPI surface. Wraps upload.fluid.app/upload so users\n // can `fluid dam upload ./photo.jpg` instead of manually\n // coordinating the three-step ImageKit + backfill flow.\n registerUpload(parent, cmdCtx);\n },\n );\n // `dam` is the colloquial nickname for this domain — both\n // `fluid assets <cmd>` and `fluid dam <cmd>` route to the same\n // command tree.\n assets.alias(\"dam\");\n ctx.program.addCommand(assets);\n },\n};\n\nexport default plugin;\n"],"mappings":"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"}
|