@ollie-shop/cli 1.6.0 → 1.7.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.
- package/.turbo/turbo-build.log +3 -3
- package/CHANGELOG.md +10 -0
- package/dist/index.js +120 -10
- package/package.json +1 -1
- package/src/commands/component-cmd.ts +88 -2
- package/src/commands/deploy-cmd.ts +2 -1
- package/src/commands/help.tsx +2 -2
- package/src/core/component.ts +51 -1
- package/src/core/schema.ts +18 -0
- package/src/utils/bundle.ts +22 -6
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @ollie-shop/cli@1.
|
|
2
|
+
> @ollie-shop/cli@1.7.0 build /home/runner/work/ollie-shop/ollie-shop/packages/cli
|
|
3
3
|
> tsup
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.tsx
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
[34mCLI[39m Target: node22
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
|
-
[32mESM[39m [1mdist/index.js [22m[
|
|
13
|
-
[32mESM[39m ⚡️ Build success in
|
|
12
|
+
[32mESM[39m [1mdist/index.js [22m[32m115.94 KB[39m
|
|
13
|
+
[32mESM[39m ⚡️ Build success in 278ms
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @ollie-shop/cli
|
|
2
2
|
|
|
3
|
+
## 1.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3d5d259: Add a `component update` command so custom component props (and name, slot, active, version) can be changed after creation directly from the CLI. Previously the CLI could only `create` and `list` components, forcing prop edits through the Studio UI. Supports partial updates via flags (`--id`, `--name`, `--slot`, `--active`, `--props`, `--version-id`) or a full `--data` JSON payload, mirroring the existing `business-rule update` command.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 616e0ea: Fix `deploy --function-id` looking for the function source under `components/`. The deploy bundler was hardcoded to `components/<name>` and always emitted a component-style `index.tsx` (`export { default }`), so function deploys failed with `Component "<name>" not found in components/` — or bundled the wrong entry point. It now resolves function sources from `functions/<name>` and emits a function-style `index.ts` (`export { handler }`) that the builder's `build_function` step expects.
|
|
12
|
+
|
|
3
13
|
## 1.6.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/dist/index.js
CHANGED
|
@@ -47,8 +47,8 @@ function HelpCommand() {
|
|
|
47
47
|
/* @__PURE__ */ jsx(Text, { children: "Create or list versions" })
|
|
48
48
|
] }),
|
|
49
49
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
50
|
-
/* @__PURE__ */ jsx(Box, { width: 24, children: /* @__PURE__ */ jsx(Text, { color: "green", children: "component create|list" }) }),
|
|
51
|
-
/* @__PURE__ */ jsx(Text, { children: "Create or list components" })
|
|
50
|
+
/* @__PURE__ */ jsx(Box, { width: 24, children: /* @__PURE__ */ jsx(Text, { color: "green", children: "component create|update|list" }) }),
|
|
51
|
+
/* @__PURE__ */ jsx(Text, { children: "Create, update or list components" })
|
|
52
52
|
] }),
|
|
53
53
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
54
54
|
/* @__PURE__ */ jsx(Box, { width: 24, children: /* @__PURE__ */ jsx(Text, { color: "green", children: "function create|list" }) }),
|
|
@@ -520,12 +520,19 @@ import path3 from "path";
|
|
|
520
520
|
import { PassThrough } from "stream";
|
|
521
521
|
import archiver from "archiver";
|
|
522
522
|
async function createComponentBundle(options) {
|
|
523
|
-
const {
|
|
524
|
-
|
|
523
|
+
const {
|
|
524
|
+
cwd = process.cwd(),
|
|
525
|
+
componentName,
|
|
526
|
+
resourceType = "component"
|
|
527
|
+
} = options;
|
|
528
|
+
const sourceDir = resourceType === "function" ? "functions" : "components";
|
|
529
|
+
const componentDir = path3.join(cwd, sourceDir, componentName);
|
|
525
530
|
try {
|
|
526
531
|
await fs3.access(componentDir);
|
|
527
532
|
} catch {
|
|
528
|
-
throw new Error(
|
|
533
|
+
throw new Error(
|
|
534
|
+
`${resourceType === "function" ? "Function" : "Component"} "${componentName}" not found in ${sourceDir}/`
|
|
535
|
+
);
|
|
529
536
|
}
|
|
530
537
|
const packageJsonPath = path3.join(cwd, "package.json");
|
|
531
538
|
try {
|
|
@@ -541,9 +548,15 @@ async function createComponentBundle(options) {
|
|
|
541
548
|
archive.on("error", (err) => {
|
|
542
549
|
output.destroy(err);
|
|
543
550
|
});
|
|
544
|
-
|
|
551
|
+
if (resourceType === "function") {
|
|
552
|
+
const entryPoint = `export { handler } from './functions/${componentName}';
|
|
553
|
+
`;
|
|
554
|
+
archive.append(entryPoint, { name: "index.ts" });
|
|
555
|
+
} else {
|
|
556
|
+
const entryPoint = `export { default } from './components/${componentName}';
|
|
545
557
|
`;
|
|
546
|
-
|
|
558
|
+
archive.append(entryPoint, { name: "index.tsx" });
|
|
559
|
+
}
|
|
547
560
|
archive.file(packageJsonPath, { name: "package.json" });
|
|
548
561
|
const entries = await fs3.readdir(cwd, { withFileTypes: true });
|
|
549
562
|
for (const entry of entries) {
|
|
@@ -1737,7 +1750,7 @@ function App({ command, args }) {
|
|
|
1737
1750
|
}
|
|
1738
1751
|
}
|
|
1739
1752
|
function VersionCommand() {
|
|
1740
|
-
const version = "1.
|
|
1753
|
+
const version = "1.7.0" ? "1.7.0" : "unknown";
|
|
1741
1754
|
return /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsxs4(Text4, { children: [
|
|
1742
1755
|
"ollieshop v",
|
|
1743
1756
|
version
|
|
@@ -2263,6 +2276,14 @@ var componentCreateSchema = z2.object({
|
|
|
2263
2276
|
active: z2.boolean().default(true).describe("Whether component is active"),
|
|
2264
2277
|
props: z2.record(z2.unknown()).nullable().default(null).describe("Default component props as JSON object")
|
|
2265
2278
|
});
|
|
2279
|
+
var componentUpdateSchema = z2.object({
|
|
2280
|
+
id: z2.string().uuid().describe("Component UUID to update"),
|
|
2281
|
+
versionId: z2.string().uuid().optional().describe("Move component to a different version UUID"),
|
|
2282
|
+
name: z2.string().min(1).optional().describe("Component name"),
|
|
2283
|
+
slot: z2.string().min(1).optional().describe("Target slot"),
|
|
2284
|
+
active: z2.boolean().optional().describe("Whether component is active"),
|
|
2285
|
+
props: z2.record(z2.unknown()).nullable().optional().describe("Component props as JSON object (null clears them)")
|
|
2286
|
+
});
|
|
2266
2287
|
var componentListSchema = z2.object({
|
|
2267
2288
|
storeId: z2.string().uuid().describe("Store UUID"),
|
|
2268
2289
|
versionId: z2.string().uuid().optional().describe("Optional version UUID to filter by")
|
|
@@ -2294,6 +2315,7 @@ var schemas = {
|
|
|
2294
2315
|
},
|
|
2295
2316
|
component: {
|
|
2296
2317
|
create: componentCreateSchema,
|
|
2318
|
+
update: componentUpdateSchema,
|
|
2297
2319
|
list: componentListSchema
|
|
2298
2320
|
},
|
|
2299
2321
|
function: {
|
|
@@ -2350,6 +2372,32 @@ async function createComponent(client, input) {
|
|
|
2350
2372
|
}
|
|
2351
2373
|
return { data: { id: data.id } };
|
|
2352
2374
|
}
|
|
2375
|
+
async function updateComponent(client, id, input) {
|
|
2376
|
+
const parsed2 = componentUpdateSchema.safeParse({ id, ...input });
|
|
2377
|
+
if (!parsed2.success) {
|
|
2378
|
+
return {
|
|
2379
|
+
error: { message: parsed2.error.issues.map((i) => i.message).join("; ") }
|
|
2380
|
+
};
|
|
2381
|
+
}
|
|
2382
|
+
const updatePayload = {};
|
|
2383
|
+
if (input.name !== void 0) updatePayload.name = input.name;
|
|
2384
|
+
if (input.slot !== void 0) updatePayload.slot = input.slot;
|
|
2385
|
+
if (input.active !== void 0) updatePayload.active = input.active;
|
|
2386
|
+
if (input.versionId !== void 0) updatePayload.version_id = input.versionId;
|
|
2387
|
+
if (input.props !== void 0) updatePayload.props = input.props;
|
|
2388
|
+
if (Object.keys(updatePayload).length === 0) {
|
|
2389
|
+
return {
|
|
2390
|
+
error: {
|
|
2391
|
+
message: "No fields to update. Provide at least one of: --name, --slot, --active, --props, --version-id."
|
|
2392
|
+
}
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
const { data, error } = await client.from("components").update(updatePayload).eq("id", id).select("id").single();
|
|
2396
|
+
if (error) {
|
|
2397
|
+
return { error: { message: error.message } };
|
|
2398
|
+
}
|
|
2399
|
+
return { data: { id: data.id } };
|
|
2400
|
+
}
|
|
2353
2401
|
async function listComponents(client, storeId, versionId) {
|
|
2354
2402
|
let query = client.from("components").select(
|
|
2355
2403
|
"id, name, slot, active, version_id, props, created_at, versions!inner(id, name)"
|
|
@@ -2368,9 +2416,10 @@ async function listComponents(client, storeId, versionId) {
|
|
|
2368
2416
|
async function componentCommand(parsed2) {
|
|
2369
2417
|
const sub = parsed2.subcommand;
|
|
2370
2418
|
if (sub === "create") return componentCreateCommand(parsed2);
|
|
2419
|
+
if (sub === "update") return componentUpdateCommand(parsed2);
|
|
2371
2420
|
if (sub === "list" || sub === "ls") return componentListCommand(parsed2);
|
|
2372
2421
|
console.error(
|
|
2373
|
-
`Unknown component subcommand: ${sub}. Use: component create | component list`
|
|
2422
|
+
`Unknown component subcommand: ${sub}. Use: component create | component update | component list`
|
|
2374
2423
|
);
|
|
2375
2424
|
process.exit(1);
|
|
2376
2425
|
}
|
|
@@ -2421,6 +2470,66 @@ async function componentCreateCommand(parsed2) {
|
|
|
2421
2470
|
process.exit(1);
|
|
2422
2471
|
}
|
|
2423
2472
|
}
|
|
2473
|
+
async function componentUpdateCommand(parsed2) {
|
|
2474
|
+
const format = detectOutputFormat(parsed2.global.output);
|
|
2475
|
+
try {
|
|
2476
|
+
let id;
|
|
2477
|
+
let input;
|
|
2478
|
+
if (parsed2.global.data) {
|
|
2479
|
+
const raw = JSON.parse(parsed2.global.data);
|
|
2480
|
+
id = validateUuid(validateRequired(raw.id, "id"), "id");
|
|
2481
|
+
input = {
|
|
2482
|
+
versionId: raw.versionId !== void 0 ? validateUuid(raw.versionId, "versionId") : void 0,
|
|
2483
|
+
name: raw.name,
|
|
2484
|
+
slot: raw.slot,
|
|
2485
|
+
active: typeof raw.active === "boolean" ? raw.active : void 0,
|
|
2486
|
+
props: raw.props
|
|
2487
|
+
};
|
|
2488
|
+
} else {
|
|
2489
|
+
id = validateUuid(
|
|
2490
|
+
validateRequired(getFlag(parsed2.flags, "id"), "id"),
|
|
2491
|
+
"id"
|
|
2492
|
+
);
|
|
2493
|
+
const versionId = getFlag(parsed2.flags, "version-id");
|
|
2494
|
+
if (versionId) validateUuid(versionId, "version-id");
|
|
2495
|
+
const activeRaw = parsed2.flags.active;
|
|
2496
|
+
let active;
|
|
2497
|
+
if (activeRaw === "true" || activeRaw === true) {
|
|
2498
|
+
active = true;
|
|
2499
|
+
} else if (activeRaw === "false") {
|
|
2500
|
+
active = false;
|
|
2501
|
+
}
|
|
2502
|
+
const propsRaw = getFlag(parsed2.flags, "props");
|
|
2503
|
+
input = {
|
|
2504
|
+
versionId,
|
|
2505
|
+
name: getFlag(parsed2.flags, "name", "n"),
|
|
2506
|
+
slot: getFlag(parsed2.flags, "slot", "s"),
|
|
2507
|
+
active,
|
|
2508
|
+
props: propsRaw ? JSON.parse(propsRaw) : void 0
|
|
2509
|
+
};
|
|
2510
|
+
}
|
|
2511
|
+
if (parsed2.global.dryRun) {
|
|
2512
|
+
outputDryRun(
|
|
2513
|
+
"component.update",
|
|
2514
|
+
{ id, ...input },
|
|
2515
|
+
format
|
|
2516
|
+
);
|
|
2517
|
+
return;
|
|
2518
|
+
}
|
|
2519
|
+
const client = await getAuthenticatedClient();
|
|
2520
|
+
const result = await updateComponent(client, id, input);
|
|
2521
|
+
outputResult(result, format, parsed2.global.fields);
|
|
2522
|
+
if (result.error) process.exit(1);
|
|
2523
|
+
} catch (err) {
|
|
2524
|
+
outputResult(
|
|
2525
|
+
{
|
|
2526
|
+
error: { message: err instanceof Error ? err.message : String(err) }
|
|
2527
|
+
},
|
|
2528
|
+
format
|
|
2529
|
+
);
|
|
2530
|
+
process.exit(1);
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2424
2533
|
async function componentListCommand(parsed2) {
|
|
2425
2534
|
const format = detectOutputFormat(parsed2.global.output);
|
|
2426
2535
|
try {
|
|
@@ -2588,7 +2697,8 @@ async function deployCommand(parsed2) {
|
|
|
2588
2697
|
}
|
|
2589
2698
|
const stream = await createComponentBundle({
|
|
2590
2699
|
componentName,
|
|
2591
|
-
cwd: process.cwd()
|
|
2700
|
+
cwd: process.cwd(),
|
|
2701
|
+
resourceType
|
|
2592
2702
|
});
|
|
2593
2703
|
const chunks = [];
|
|
2594
2704
|
for await (const chunk of stream) {
|
package/package.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createComponent,
|
|
3
|
+
listComponents,
|
|
4
|
+
updateComponent,
|
|
5
|
+
} from "../core/component.js";
|
|
2
6
|
import {
|
|
3
7
|
detectOutputFormat,
|
|
4
8
|
outputDryRun,
|
|
@@ -11,10 +15,11 @@ import { validateRequired, validateUuid } from "../utils/validate.js";
|
|
|
11
15
|
export async function componentCommand(parsed: ParsedArgs): Promise<void> {
|
|
12
16
|
const sub = parsed.subcommand;
|
|
13
17
|
if (sub === "create") return componentCreateCommand(parsed);
|
|
18
|
+
if (sub === "update") return componentUpdateCommand(parsed);
|
|
14
19
|
if (sub === "list" || sub === "ls") return componentListCommand(parsed);
|
|
15
20
|
|
|
16
21
|
console.error(
|
|
17
|
-
`Unknown component subcommand: ${sub}. Use: component create | component list`,
|
|
22
|
+
`Unknown component subcommand: ${sub}. Use: component create | component update | component list`,
|
|
18
23
|
);
|
|
19
24
|
process.exit(1);
|
|
20
25
|
}
|
|
@@ -79,6 +84,87 @@ async function componentCreateCommand(parsed: ParsedArgs): Promise<void> {
|
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
|
|
87
|
+
async function componentUpdateCommand(parsed: ParsedArgs): Promise<void> {
|
|
88
|
+
const format = detectOutputFormat(parsed.global.output);
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
let id: string;
|
|
92
|
+
let input: {
|
|
93
|
+
versionId?: string;
|
|
94
|
+
name?: string;
|
|
95
|
+
slot?: string;
|
|
96
|
+
active?: boolean;
|
|
97
|
+
props?: Record<string, unknown> | null;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
if (parsed.global.data) {
|
|
101
|
+
const raw = JSON.parse(parsed.global.data);
|
|
102
|
+
id = validateUuid(validateRequired(raw.id, "id"), "id");
|
|
103
|
+
input = {
|
|
104
|
+
versionId:
|
|
105
|
+
raw.versionId !== undefined
|
|
106
|
+
? validateUuid(raw.versionId, "versionId")
|
|
107
|
+
: undefined,
|
|
108
|
+
name: raw.name,
|
|
109
|
+
slot: raw.slot,
|
|
110
|
+
active: typeof raw.active === "boolean" ? raw.active : undefined,
|
|
111
|
+
props: raw.props,
|
|
112
|
+
};
|
|
113
|
+
} else {
|
|
114
|
+
id = validateUuid(
|
|
115
|
+
validateRequired(getFlag(parsed.flags, "id"), "id"),
|
|
116
|
+
"id",
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
const versionId = getFlag(parsed.flags, "version-id");
|
|
120
|
+
if (versionId) validateUuid(versionId, "version-id");
|
|
121
|
+
|
|
122
|
+
const activeRaw = parsed.flags.active;
|
|
123
|
+
let active: boolean | undefined;
|
|
124
|
+
if (activeRaw === "true" || activeRaw === true) {
|
|
125
|
+
active = true;
|
|
126
|
+
} else if (activeRaw === "false") {
|
|
127
|
+
active = false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const propsRaw = getFlag(parsed.flags, "props");
|
|
131
|
+
|
|
132
|
+
input = {
|
|
133
|
+
versionId,
|
|
134
|
+
name: getFlag(parsed.flags, "name", "n"),
|
|
135
|
+
slot: getFlag(parsed.flags, "slot", "s"),
|
|
136
|
+
active,
|
|
137
|
+
props: propsRaw
|
|
138
|
+
? (JSON.parse(propsRaw) as Record<string, unknown> | null)
|
|
139
|
+
: undefined,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (parsed.global.dryRun) {
|
|
144
|
+
outputDryRun(
|
|
145
|
+
"component.update",
|
|
146
|
+
{ id, ...input } as Record<string, unknown>,
|
|
147
|
+
format,
|
|
148
|
+
);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const client = await getAuthenticatedClient();
|
|
153
|
+
const result = await updateComponent(client, id, input);
|
|
154
|
+
|
|
155
|
+
outputResult(result, format, parsed.global.fields);
|
|
156
|
+
if (result.error) process.exit(1);
|
|
157
|
+
} catch (err) {
|
|
158
|
+
outputResult(
|
|
159
|
+
{
|
|
160
|
+
error: { message: err instanceof Error ? err.message : String(err) },
|
|
161
|
+
},
|
|
162
|
+
format,
|
|
163
|
+
);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
82
168
|
async function componentListCommand(parsed: ParsedArgs): Promise<void> {
|
|
83
169
|
const format = detectOutputFormat(parsed.global.output);
|
|
84
170
|
|
|
@@ -61,10 +61,11 @@ export async function deployCommand(parsed: ParsedArgs): Promise<void> {
|
|
|
61
61
|
timeout = Number(getFlag(parsed.flags, "timeout") ?? "300");
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
// Bundle the
|
|
64
|
+
// Bundle the resource
|
|
65
65
|
const stream = await createComponentBundle({
|
|
66
66
|
componentName,
|
|
67
67
|
cwd: process.cwd(),
|
|
68
|
+
resourceType,
|
|
68
69
|
});
|
|
69
70
|
|
|
70
71
|
// Collect the zip buffer
|
package/src/commands/help.tsx
CHANGED
|
@@ -57,9 +57,9 @@ export function HelpCommand() {
|
|
|
57
57
|
</Box>
|
|
58
58
|
<Box>
|
|
59
59
|
<Box width={24}>
|
|
60
|
-
<Text color="green">component create|list</Text>
|
|
60
|
+
<Text color="green">component create|update|list</Text>
|
|
61
61
|
</Box>
|
|
62
|
-
<Text>Create or list components</Text>
|
|
62
|
+
<Text>Create, update or list components</Text>
|
|
63
63
|
</Box>
|
|
64
64
|
<Box>
|
|
65
65
|
<Box width={24}>
|
package/src/core/component.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
-
import { componentCreateSchema } from "./schema.js";
|
|
2
|
+
import { componentCreateSchema, componentUpdateSchema } from "./schema.js";
|
|
3
3
|
|
|
4
4
|
export interface CreateComponentInput {
|
|
5
5
|
versionId: string;
|
|
@@ -9,6 +9,14 @@ export interface CreateComponentInput {
|
|
|
9
9
|
props?: Record<string, unknown> | null;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
export interface UpdateComponentInput {
|
|
13
|
+
versionId?: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
slot?: string;
|
|
16
|
+
active?: boolean;
|
|
17
|
+
props?: Record<string, unknown> | null;
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
export interface ComponentRecord {
|
|
13
21
|
id: string;
|
|
14
22
|
name: string;
|
|
@@ -50,6 +58,48 @@ export async function createComponent(
|
|
|
50
58
|
return { data: { id: data.id } };
|
|
51
59
|
}
|
|
52
60
|
|
|
61
|
+
export async function updateComponent(
|
|
62
|
+
client: SupabaseClient,
|
|
63
|
+
id: string,
|
|
64
|
+
input: UpdateComponentInput,
|
|
65
|
+
): Promise<{ data?: { id: string }; error?: { message: string } }> {
|
|
66
|
+
const parsed = componentUpdateSchema.safeParse({ id, ...input });
|
|
67
|
+
if (!parsed.success) {
|
|
68
|
+
return {
|
|
69
|
+
error: { message: parsed.error.issues.map((i) => i.message).join("; ") },
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const updatePayload: Record<string, unknown> = {};
|
|
74
|
+
if (input.name !== undefined) updatePayload.name = input.name;
|
|
75
|
+
if (input.slot !== undefined) updatePayload.slot = input.slot;
|
|
76
|
+
if (input.active !== undefined) updatePayload.active = input.active;
|
|
77
|
+
if (input.versionId !== undefined) updatePayload.version_id = input.versionId;
|
|
78
|
+
if (input.props !== undefined) updatePayload.props = input.props;
|
|
79
|
+
|
|
80
|
+
if (Object.keys(updatePayload).length === 0) {
|
|
81
|
+
return {
|
|
82
|
+
error: {
|
|
83
|
+
message:
|
|
84
|
+
"No fields to update. Provide at least one of: --name, --slot, --active, --props, --version-id.",
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const { data, error } = await client
|
|
90
|
+
.from("components")
|
|
91
|
+
.update(updatePayload)
|
|
92
|
+
.eq("id", id)
|
|
93
|
+
.select("id")
|
|
94
|
+
.single();
|
|
95
|
+
|
|
96
|
+
if (error) {
|
|
97
|
+
return { error: { message: error.message } };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return { data: { id: data.id } };
|
|
101
|
+
}
|
|
102
|
+
|
|
53
103
|
export async function listComponents(
|
|
54
104
|
client: SupabaseClient,
|
|
55
105
|
storeId: string,
|
package/src/core/schema.ts
CHANGED
|
@@ -52,6 +52,23 @@ export const componentCreateSchema = z.object({
|
|
|
52
52
|
.describe("Default component props as JSON object"),
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
+
export const componentUpdateSchema = z.object({
|
|
56
|
+
id: z.string().uuid().describe("Component UUID to update"),
|
|
57
|
+
versionId: z
|
|
58
|
+
.string()
|
|
59
|
+
.uuid()
|
|
60
|
+
.optional()
|
|
61
|
+
.describe("Move component to a different version UUID"),
|
|
62
|
+
name: z.string().min(1).optional().describe("Component name"),
|
|
63
|
+
slot: z.string().min(1).optional().describe("Target slot"),
|
|
64
|
+
active: z.boolean().optional().describe("Whether component is active"),
|
|
65
|
+
props: z
|
|
66
|
+
.record(z.unknown())
|
|
67
|
+
.nullable()
|
|
68
|
+
.optional()
|
|
69
|
+
.describe("Component props as JSON object (null clears them)"),
|
|
70
|
+
});
|
|
71
|
+
|
|
55
72
|
export const componentListSchema = z.object({
|
|
56
73
|
storeId: z.string().uuid().describe("Store UUID"),
|
|
57
74
|
versionId: z
|
|
@@ -109,6 +126,7 @@ const schemas: Record<string, SchemaMap> = {
|
|
|
109
126
|
},
|
|
110
127
|
component: {
|
|
111
128
|
create: componentCreateSchema,
|
|
129
|
+
update: componentUpdateSchema,
|
|
112
130
|
list: componentListSchema,
|
|
113
131
|
},
|
|
114
132
|
function: {
|
package/src/utils/bundle.ts
CHANGED
|
@@ -5,11 +5,15 @@ import archiver from "archiver";
|
|
|
5
5
|
|
|
6
6
|
// TODO: Implement .ollieignore file support for custom exclusions
|
|
7
7
|
|
|
8
|
+
export type BundleResourceType = "component" | "function";
|
|
9
|
+
|
|
8
10
|
export interface BundleOptions {
|
|
9
11
|
/** Project root directory */
|
|
10
12
|
cwd?: string;
|
|
11
13
|
/** Component name (folder name in components/) */
|
|
12
14
|
componentName: string;
|
|
15
|
+
/** Resource type — decides the source folder and entry point shape */
|
|
16
|
+
resourceType?: BundleResourceType;
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
export interface BundleResult {
|
|
@@ -33,14 +37,21 @@ export interface BundleResult {
|
|
|
33
37
|
export async function createComponentBundle(
|
|
34
38
|
options: BundleOptions,
|
|
35
39
|
): Promise<PassThrough> {
|
|
36
|
-
const {
|
|
40
|
+
const {
|
|
41
|
+
cwd = process.cwd(),
|
|
42
|
+
componentName,
|
|
43
|
+
resourceType = "component",
|
|
44
|
+
} = options;
|
|
45
|
+
|
|
46
|
+
const sourceDir = resourceType === "function" ? "functions" : "components";
|
|
37
47
|
|
|
38
|
-
|
|
39
|
-
const componentDir = path.join(cwd, "components", componentName);
|
|
48
|
+
const componentDir = path.join(cwd, sourceDir, componentName);
|
|
40
49
|
try {
|
|
41
50
|
await fs.access(componentDir);
|
|
42
51
|
} catch {
|
|
43
|
-
throw new Error(
|
|
52
|
+
throw new Error(
|
|
53
|
+
`${resourceType === "function" ? "Function" : "Component"} "${componentName}" not found in ${sourceDir}/`,
|
|
54
|
+
);
|
|
44
55
|
}
|
|
45
56
|
|
|
46
57
|
// Verify package.json exists
|
|
@@ -67,8 +78,13 @@ export async function createComponentBundle(
|
|
|
67
78
|
});
|
|
68
79
|
|
|
69
80
|
// Add synthetic entry point
|
|
70
|
-
|
|
71
|
-
|
|
81
|
+
if (resourceType === "function") {
|
|
82
|
+
const entryPoint = `export { handler } from './functions/${componentName}';\n`;
|
|
83
|
+
archive.append(entryPoint, { name: "index.ts" });
|
|
84
|
+
} else {
|
|
85
|
+
const entryPoint = `export { default } from './components/${componentName}';\n`;
|
|
86
|
+
archive.append(entryPoint, { name: "index.tsx" });
|
|
87
|
+
}
|
|
72
88
|
|
|
73
89
|
// Add package.json
|
|
74
90
|
archive.file(packageJsonPath, { name: "package.json" });
|