opacacms 0.2.0 → 0.3.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/README.md +31 -22
- package/dist/admin/auth-client.d.ts +39 -39
- package/dist/admin/index.d.ts +2 -2
- package/dist/admin/index.js +15 -10520
- package/dist/admin/plugin-client.d.ts +65 -0
- package/dist/admin/react.d.ts +2 -2
- package/dist/admin/react.js +34 -4
- package/dist/admin/stores/ui.d.ts +19 -4
- package/dist/admin/ui/components/PluginSettingsForm.d.ts +2 -2
- package/dist/admin/ui/components/custom-alert.d.ts +7 -0
- package/dist/admin/ui/components/{DetailSheet.d.ts → detail-sheet.d.ts} +1 -2
- package/dist/admin/ui/components/fields/FieldLabel.d.ts +1 -1
- package/dist/admin/ui/components/fields/RelationshipField.d.ts +1 -1
- package/dist/admin/ui/components/media/AssetManagerModal.d.ts +2 -2
- package/dist/admin/ui/components/plugin-iframe.d.ts +7 -0
- package/dist/admin/ui/components/ui/accordion.d.ts +17 -7
- package/dist/admin/ui/components/ui/alert-dialog.d.ts +16 -12
- package/dist/admin/ui/components/ui/button.d.ts +11 -7
- package/dist/admin/ui/components/ui/relationship.d.ts +1 -1
- package/dist/admin/ui/components/ui/sheet.d.ts +14 -27
- package/dist/admin/ui/components/ui/tooltip.d.ts +7 -0
- package/dist/admin/ui/components/versions-sheet.d.ts +4 -5
- package/dist/admin/ui/views/collection-list-view.d.ts +1 -1
- package/dist/admin/ui/views/dashboard-view.d.ts +1 -1
- package/dist/admin/ui/views/media-registry-view.d.ts +3 -3
- package/dist/admin/ui/views/settings-view.d.ts +2 -2
- package/dist/admin/vue.js +27 -4
- package/dist/admin/webcomponent.js +20 -2
- package/dist/admin.css +1 -1
- package/dist/auth/index.d.ts +43 -43
- package/dist/{chunk-7y1nbmw6.js → chunk-1bd7fz7n.js} +32 -2
- package/dist/chunk-1qm0m8r8.js +413 -0
- package/dist/chunk-2k3ysje3.js +31 -0
- package/dist/chunk-3j9zjfmn.js +376 -0
- package/dist/{chunk-byq8g0rd.js → chunk-48ywpd0a.js} +16 -22
- package/dist/{chunk-esrg9qj0.js → chunk-5422w4eq.js} +70 -54
- package/dist/chunk-56n342hs.js +95 -0
- package/dist/chunk-5b8r0v8c.js +47 -0
- package/dist/chunk-63yg00vx.js +263 -0
- package/dist/{chunk-8sqjbsgt.js → chunk-6bywt602.js} +26 -1
- package/dist/{chunk-v9z61v3g.js → chunk-6qs0g65f.js} +43 -3
- package/dist/chunk-7rr5p01g.js +581 -0
- package/dist/{chunk-51z3x7kq.js → chunk-a3qae86h.js} +1 -1
- package/dist/{chunk-3rdhbedb.js → chunk-adq2b75c.js} +2 -2
- package/dist/chunk-d0tb1xjw.js +93 -0
- package/dist/chunk-d7cgd6vn.js +318 -0
- package/dist/{chunk-0bq155dy.js → chunk-e0g6gn7n.js} +89 -100
- package/dist/chunk-ec4jhybj.js +1137 -0
- package/dist/chunk-fatyf6f7.js +221 -0
- package/dist/{chunk-526a3gqx.js → chunk-fnsf1dfm.js} +1 -1
- package/dist/chunk-g9bxb6h0.js +205 -0
- package/dist/chunk-gyaf5kgf.js +10 -0
- package/dist/{chunk-9kxpbcb1.js → chunk-h6dhexzr.js} +16 -7
- package/dist/{chunk-dykn5hr6.js → chunk-j8js1y0h.js} +31 -74
- package/dist/{chunk-t0zg026p.js → chunk-jq1drsen.js} +12 -1
- package/dist/{chunk-b3kr8w41.js → chunk-m24yqkeq.js} +38 -26
- package/dist/chunk-m5ems3hh.js +410 -0
- package/dist/{chunk-8scgdznr.js → chunk-m83ybzf8.js} +15 -18
- package/dist/chunk-majsbncm.js +98 -0
- package/dist/chunk-mp2gt9yh.js +237 -0
- package/dist/chunk-n1twhqmf.js +54 -0
- package/dist/{chunk-gmee4mdc.js → chunk-naqcqj8n.js} +92 -106
- package/dist/chunk-q5sb5dcr.js +15 -0
- package/dist/{chunk-d1asgtke.js → chunk-qhdsjek6.js} +90 -121
- package/dist/{chunk-0gtxnxmd.js → chunk-qsh2nqz3.js} +85 -105
- package/dist/chunk-r0ms5tk1.js +76 -0
- package/dist/chunk-rwqwsanx.js +75 -0
- package/dist/chunk-sqsfk9p4.js +700 -0
- package/dist/{chunk-5gvbp2qa.js → chunk-x7bnzswh.js} +25 -18
- package/dist/{chunk-kc4jfnv7.js → chunk-z3ffn2b7.js} +851 -324
- package/dist/cli/commands/dev.d.ts +8 -0
- package/dist/cli/commands/doctor.d.ts +8 -0
- package/dist/cli/commands/generate.d.ts +26 -0
- package/dist/cli/commands/init.d.ts +13 -1
- package/dist/cli/commands/migrate.d.ts +33 -0
- package/dist/cli/commands/plugin.d.ts +13 -0
- package/dist/cli/commands/seed.d.ts +21 -0
- package/dist/cli/{commands/migrate-commands.d.ts → core/migrations/migrate-logic.d.ts} +2 -2
- package/dist/cli/core/migrations/schema-diff-engine.d.ts +12 -0
- package/dist/cli/core/migrations/schema-diff.d.ts +11 -0
- package/dist/cli/{seeding.d.ts → core/seeding/auto-seed.d.ts} +7 -4
- package/dist/cli/core/seeding/seed-logic.d.ts +2 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.js +6 -170
- package/dist/client/RichText.d.ts +5 -0
- package/dist/client/rich-text-utils.d.ts +5 -0
- package/dist/client.js +3 -2
- package/dist/config.d.ts +3 -3
- package/dist/db/adapter.d.ts +2 -2
- package/dist/db/better-sqlite.d.ts +3 -3
- package/dist/db/better-sqlite.js +6 -5
- package/dist/db/bun-sqlite.d.ts +3 -3
- package/dist/db/bun-sqlite.js +6 -5
- package/dist/db/d1.d.ts +13 -7
- package/dist/db/d1.js +6 -5
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.js +10 -12
- package/dist/db/kysely/factory.d.ts +29 -0
- package/dist/db/kysely/plugins/audit-logging.d.ts +48 -0
- package/dist/db/kysely/plugins/auto-timestamps.d.ts +38 -0
- package/dist/db/kysely/plugins/cursor-pagination.d.ts +42 -0
- package/dist/db/kysely/plugins/deadlock-handler.d.ts +47 -0
- package/dist/db/kysely/plugins/draft-swapper.d.ts +33 -0
- package/dist/db/kysely/plugins/field-masking.d.ts +45 -0
- package/dist/db/kysely/plugins/fts-normalizer.d.ts +38 -0
- package/dist/db/kysely/plugins/i18n-fallback.d.ts +48 -0
- package/dist/db/kysely/plugins/id-generation.d.ts +42 -0
- package/dist/db/kysely/plugins/index.d.ts +16 -0
- package/dist/db/kysely/plugins/json-flattener.d.ts +38 -0
- package/dist/db/kysely/plugins/relationship-preloading.d.ts +39 -0
- package/dist/db/kysely/plugins/slug-generation.d.ts +37 -0
- package/dist/db/kysely/plugins/soft-delete.d.ts +42 -0
- package/dist/db/kysely/plugins/tree-resolver.d.ts +39 -0
- package/dist/db/kysely/plugins/virtual-field-resolver.d.ts +54 -0
- package/dist/db/kysely/plugins/zod-coercion.d.ts +34 -0
- package/dist/db/kysely/snapshot/snapshot-manager.d.ts +18 -0
- package/dist/db/postgres.d.ts +4 -4
- package/dist/db/postgres.js +6 -5
- package/dist/db/sqlite.d.ts +3 -3
- package/dist/db/sqlite.js +6 -5
- package/dist/index.d.ts +3 -0
- package/dist/index.js +161 -7
- package/dist/runtimes/bun.js +9 -6
- package/dist/runtimes/cloudflare-workers.d.ts +3 -1
- package/dist/runtimes/cloudflare-workers.js +36 -7
- package/dist/runtimes/next.js +8 -5
- package/dist/runtimes/node.js +9 -6
- package/dist/schema/collection.d.ts +116 -70
- package/dist/schema/compiler.d.ts +6 -0
- package/dist/schema/global.d.ts +38 -71
- package/dist/schema/index.d.ts +5 -4
- package/dist/schema/index.js +35 -550
- package/dist/schema/zod.d.ts +564 -0
- package/dist/server/admin-router.d.ts +1 -1
- package/dist/server/collection-router.d.ts +1 -1
- package/dist/server/graphql.d.ts +6 -0
- package/dist/server/handlers.d.ts +25 -7
- package/dist/server/middlewares/auth.d.ts +1 -1
- package/dist/server/plugins-loader.d.ts +1 -1
- package/dist/server/router.d.ts +2 -2
- package/dist/server/routers/admin.d.ts +1 -1
- package/dist/server/routers/auth.d.ts +1 -1
- package/dist/server/routers/collections.d.ts +4 -1
- package/dist/server/routers/plugins.d.ts +2 -2
- package/dist/server/setup-middlewares.d.ts +1 -1
- package/dist/server/system-router.d.ts +1 -1
- package/dist/server.js +11 -6
- package/dist/storage/adapters/cloudflare-r2.d.ts +11 -2
- package/dist/storage/index.js +39 -30
- package/dist/types.d.ts +255 -44
- package/dist/utils/context.d.ts +14 -0
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/string.d.ts +10 -0
- package/dist/utils/webhooks-engine.d.ts +24 -0
- package/dist/validation.d.ts +67 -1
- package/dist/validator.d.ts +1 -0
- package/package.json +36 -33
- package/src/cli/index.ts +117 -0
- package/dist/chunk-6qq3ne6b.js +0 -288
- package/dist/chunk-6v1fw7q7.js +0 -126
- package/dist/chunk-7a9kn0np.js +0 -116
- package/dist/chunk-bexcv7xe.js +0 -36
- package/dist/chunk-d3ffeqp9.js +0 -87
- package/dist/chunk-fj19qccp.js +0 -78
- package/dist/chunk-j53pz21t.js +0 -20
- package/dist/chunk-mkn49zmy.js +0 -102
- package/dist/chunk-qb6ztvw9.js +0 -17
- package/dist/chunk-r39em4yj.js +0 -29
- package/dist/chunk-rsf0tpy1.js +0 -8
- package/dist/chunk-srsac177.js +0 -85
- package/dist/chunk-swtcpvhf.js +0 -2442
- package/dist/chunk-twpvxfce.js +0 -64
- package/dist/chunk-ywm4t2gm.js +0 -19
- package/dist/cli/commands/plugin-sync.d.ts +0 -1
- package/dist/cli/commands/seed-command.d.ts +0 -2
- package/dist/plugins/ui-bridge.d.ts +0 -12
- package/dist/schema/fields/base.d.ts +0 -84
- package/dist/schema/fields/index.d.ts +0 -147
- package/dist/schema/infer.d.ts +0 -55
- /package/dist/admin/ui/components/{ColumnVisibilityToggle.d.ts → column-visibility-toggle.d.ts} +0 -0
- /package/dist/admin/ui/components/{DataDetailView.d.ts → data-detail-view.d.ts} +0 -0
- /package/dist/cli/{d1-mock.d.ts → core/mocks/d1-mock.d.ts} +0 -0
- /package/dist/cli/{r2-mock.d.ts → core/mocks/r2-mock.d.ts} +0 -0
- /package/dist/cli/{commands → core/plugins}/plugin-build.d.ts +0 -0
- /package/dist/cli/{commands → core/plugins}/plugin-init.d.ts +0 -0
- /package/dist/cli/{commands → core/types}/generate-types.d.ts +0 -0
- /package/dist/{schema/fields/validation.test.d.ts → cli/seeding.test.d.ts} +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface WebhookPayload {
|
|
2
|
+
event: string;
|
|
3
|
+
collection: string;
|
|
4
|
+
data: unknown;
|
|
5
|
+
timestamp: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Verifies an incoming webhook signature.
|
|
9
|
+
* Supports both string secrets (HMAC-SHA256) and custom verification functions.
|
|
10
|
+
*/
|
|
11
|
+
export declare function verifyWebhookSignature(req: Request, secretOrFn: string | ((req: Request) => boolean | Promise<boolean>), headerName?: string): Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* Dispatches an outgoing webhook with retries and exponential backoff.
|
|
14
|
+
*/
|
|
15
|
+
export declare function dispatchWebhook(args: {
|
|
16
|
+
url: string;
|
|
17
|
+
data: unknown;
|
|
18
|
+
event: string;
|
|
19
|
+
collection: string;
|
|
20
|
+
headers?: Record<string, string>;
|
|
21
|
+
retries?: number;
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
transform?: (data: any) => any;
|
|
24
|
+
}): Promise<void>;
|
package/dist/validation.d.ts
CHANGED
|
@@ -170,6 +170,14 @@ export declare const OpacaAuthConfigSchema: z.ZodObject<{
|
|
|
170
170
|
}, z.core.$strip>;
|
|
171
171
|
export declare const ApiConfigSchema: z.ZodObject<{
|
|
172
172
|
maxLimit: z.ZodOptional<z.ZodNumber>;
|
|
173
|
+
rest: z.ZodOptional<z.ZodObject<{
|
|
174
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
175
|
+
}, z.core.$strip>>;
|
|
176
|
+
graphql: z.ZodOptional<z.ZodObject<{
|
|
177
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
178
|
+
path: z.ZodOptional<z.ZodString>;
|
|
179
|
+
graphiql: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
180
|
+
}, z.core.$strip>>;
|
|
173
181
|
rateLimit: z.ZodOptional<z.ZodObject<{
|
|
174
182
|
windowMs: z.ZodOptional<z.ZodNumber>;
|
|
175
183
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
@@ -189,8 +197,58 @@ export declare const ApiConfigSchema: z.ZodObject<{
|
|
|
189
197
|
}, z.core.$strip>>;
|
|
190
198
|
}, z.core.$strip>;
|
|
191
199
|
export type ApiConfig = z.infer<typeof ApiConfigSchema>;
|
|
200
|
+
export declare const OpacaPluginSchema: z.ZodObject<{
|
|
201
|
+
name: z.ZodString;
|
|
202
|
+
label: z.ZodOptional<z.ZodString>;
|
|
203
|
+
description: z.ZodOptional<z.ZodString>;
|
|
204
|
+
version: z.ZodOptional<z.ZodString>;
|
|
205
|
+
author: z.ZodOptional<z.ZodString>;
|
|
206
|
+
homepage: z.ZodOptional<z.ZodString>;
|
|
207
|
+
icon: z.ZodOptional<z.ZodString>;
|
|
208
|
+
onInit: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
209
|
+
onRouterInit: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
210
|
+
onInitComplete: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
211
|
+
onRequest: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
212
|
+
onExport: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
213
|
+
onDestroy: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
214
|
+
adminAssets: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
215
|
+
configSchema: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodLazy<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>, z.ZodAny]>>;
|
|
216
|
+
adminUI: z.ZodOptional<z.ZodObject<{
|
|
217
|
+
type: z.ZodEnum<{
|
|
218
|
+
iframe: "iframe";
|
|
219
|
+
ssr: "ssr";
|
|
220
|
+
}>;
|
|
221
|
+
path: z.ZodString;
|
|
222
|
+
}, z.core.$strip>>;
|
|
223
|
+
settings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
224
|
+
}, z.core.$strip>;
|
|
225
|
+
export type OpacaPlugin = z.infer<typeof OpacaPluginSchema>;
|
|
192
226
|
export declare const OpacaConfigSchema: z.ZodObject<{
|
|
193
|
-
plugins: z.ZodOptional<z.ZodArray<z.
|
|
227
|
+
plugins: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
228
|
+
name: z.ZodString;
|
|
229
|
+
label: z.ZodOptional<z.ZodString>;
|
|
230
|
+
description: z.ZodOptional<z.ZodString>;
|
|
231
|
+
version: z.ZodOptional<z.ZodString>;
|
|
232
|
+
author: z.ZodOptional<z.ZodString>;
|
|
233
|
+
homepage: z.ZodOptional<z.ZodString>;
|
|
234
|
+
icon: z.ZodOptional<z.ZodString>;
|
|
235
|
+
onInit: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
236
|
+
onRouterInit: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
237
|
+
onInitComplete: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
238
|
+
onRequest: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
239
|
+
onExport: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
240
|
+
onDestroy: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
241
|
+
adminAssets: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
242
|
+
configSchema: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodLazy<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>, z.ZodAny]>>;
|
|
243
|
+
adminUI: z.ZodOptional<z.ZodObject<{
|
|
244
|
+
type: z.ZodEnum<{
|
|
245
|
+
iframe: "iframe";
|
|
246
|
+
ssr: "ssr";
|
|
247
|
+
}>;
|
|
248
|
+
path: z.ZodString;
|
|
249
|
+
}, z.core.$strip>>;
|
|
250
|
+
settings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
251
|
+
}, z.core.$strip>>>;
|
|
194
252
|
collections: z.ZodArray<z.ZodObject<{
|
|
195
253
|
slug: z.ZodString;
|
|
196
254
|
label: z.ZodOptional<z.ZodString>;
|
|
@@ -323,6 +381,14 @@ export declare const OpacaConfigSchema: z.ZodObject<{
|
|
|
323
381
|
}, z.core.$strip>>;
|
|
324
382
|
api: z.ZodOptional<z.ZodObject<{
|
|
325
383
|
maxLimit: z.ZodOptional<z.ZodNumber>;
|
|
384
|
+
rest: z.ZodOptional<z.ZodObject<{
|
|
385
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
386
|
+
}, z.core.$strip>>;
|
|
387
|
+
graphql: z.ZodOptional<z.ZodObject<{
|
|
388
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
389
|
+
path: z.ZodOptional<z.ZodString>;
|
|
390
|
+
graphiql: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
391
|
+
}, z.core.$strip>>;
|
|
326
392
|
rateLimit: z.ZodOptional<z.ZodObject<{
|
|
327
393
|
windowMs: z.ZodOptional<z.ZodNumber>;
|
|
328
394
|
limit: z.ZodOptional<z.ZodNumber>;
|
package/dist/validator.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export declare function generateSchemaForCollection(collection: {
|
|
|
4
4
|
fields: Field[];
|
|
5
5
|
versions?: any;
|
|
6
6
|
timestamps?: any;
|
|
7
|
+
schema?: any;
|
|
7
8
|
}, isUpdate?: boolean, forDocs?: boolean): z.ZodObject<{
|
|
8
9
|
[x: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
|
|
9
10
|
}, z.core.$strip>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opacacms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"build": "bun run ../../scripts/build.ts && tsc --emitDeclarationOnly",
|
|
6
6
|
"build:publish": "bun run ../../scripts/build.ts --publish && tsc --emitDeclarationOnly",
|
|
@@ -23,8 +23,9 @@
|
|
|
23
23
|
},
|
|
24
24
|
"module": "dist/index.js",
|
|
25
25
|
"type": "module",
|
|
26
|
+
"sideEffects": false,
|
|
26
27
|
"bin": {
|
|
27
|
-
"opacacms": "./
|
|
28
|
+
"opacacms": "./src/cli/index.ts"
|
|
28
29
|
},
|
|
29
30
|
"exports": {
|
|
30
31
|
"./styles.css": {
|
|
@@ -112,36 +113,16 @@
|
|
|
112
113
|
}
|
|
113
114
|
},
|
|
114
115
|
"devDependencies": {
|
|
115
|
-
"@cloudflare/workers-types": "^4.20260313.1",
|
|
116
|
-
"@faker-js/faker": "^10.3.0",
|
|
117
|
-
"@happy-dom/global-registrator": "^20.8.4",
|
|
118
|
-
"@hono/bun-transpiler": "^0.2.1",
|
|
119
|
-
"@hono/esbuild-transpiler": "^0.1.4",
|
|
120
|
-
"@testing-library/dom": "^10.4.1",
|
|
121
|
-
"@testing-library/react": "^16.3.2",
|
|
122
|
-
"@types/better-sqlite3": "^7.6.13",
|
|
123
|
-
"@types/bun": "latest",
|
|
124
|
-
"@types/react": "^19.2.14",
|
|
125
|
-
"@types/react-dom": "^19.2.3",
|
|
126
|
-
"bun-plugin-scss": "^1.0.0",
|
|
127
|
-
"dotenv": "^17.3.1",
|
|
128
|
-
"drizzle-kit": "^0.31.9",
|
|
129
|
-
"esbuild": "^0.27.4",
|
|
130
|
-
"esbuild-wasm": "^0.27.4",
|
|
131
|
-
"happy-dom": "^20.8.4",
|
|
132
|
-
"sass": "^1.98.0"
|
|
133
|
-
},
|
|
134
|
-
"peerDependencies": {
|
|
135
|
-
"react": "^19.2.4",
|
|
136
|
-
"react-dom": "^19.2.4",
|
|
137
|
-
"typescript": "^5.9.3"
|
|
138
|
-
},
|
|
139
|
-
"dependencies": {
|
|
140
116
|
"@aws-sdk/client-s3": "^3.1009.0",
|
|
141
117
|
"@aws-sdk/s3-request-presigner": "^3.1009.0",
|
|
142
118
|
"@better-auth/api-key": "^1.5.5",
|
|
143
119
|
"@better-auth/core": "^1.5.5",
|
|
120
|
+
"@cloudflare/workers-types": "^4.20260313.1",
|
|
121
|
+
"@faker-js/faker": "^10.3.0",
|
|
122
|
+
"@happy-dom/global-registrator": "^20.8.4",
|
|
144
123
|
"@hono-rate-limiter/cloudflare": "^0.2.2",
|
|
124
|
+
"@hono/bun-transpiler": "^0.2.1",
|
|
125
|
+
"@hono/esbuild-transpiler": "^0.1.4",
|
|
145
126
|
"@hono/node-server": "^1.19.11",
|
|
146
127
|
"@lexical/code": "^0.41.0",
|
|
147
128
|
"@lexical/history": "^0.41.0",
|
|
@@ -160,13 +141,18 @@
|
|
|
160
141
|
"@r2wc/react-to-web-component": "^2.1.1",
|
|
161
142
|
"@scalar/hono-api-reference": "^0.10.4",
|
|
162
143
|
"@tanstack/react-form": "^1.28.5",
|
|
163
|
-
"
|
|
144
|
+
"@testing-library/dom": "^10.4.1",
|
|
145
|
+
"@testing-library/react": "^16.3.2",
|
|
146
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
147
|
+
"@types/bun": "latest",
|
|
148
|
+
"@types/react": "^19.2.14",
|
|
149
|
+
"@types/react-dom": "^19.2.3",
|
|
164
150
|
"better-sqlite3": "^12.6.2",
|
|
165
|
-
"
|
|
166
|
-
"
|
|
167
|
-
"
|
|
168
|
-
"
|
|
169
|
-
"
|
|
151
|
+
"bun-plugin-scss": "^1.0.0",
|
|
152
|
+
"dotenv": "^17.3.1",
|
|
153
|
+
"esbuild": "^0.27.4",
|
|
154
|
+
"esbuild-wasm": "^0.27.4",
|
|
155
|
+
"happy-dom": "^20.8.4",
|
|
170
156
|
"kysely-bun-sqlite": "^0.4.0",
|
|
171
157
|
"kysely-d1": "^0.4.0",
|
|
172
158
|
"kysely-postgres-js": "^3.0.0",
|
|
@@ -174,6 +160,23 @@
|
|
|
174
160
|
"lucide-react": "^0.577.0",
|
|
175
161
|
"nanostores": "^1.1.1",
|
|
176
162
|
"postgres": "^3.4.8",
|
|
163
|
+
"sass": "^1.98.0"
|
|
164
|
+
},
|
|
165
|
+
"peerDependencies": {
|
|
166
|
+
"react": "^19.2.4",
|
|
167
|
+
"react-dom": "^19.2.4",
|
|
168
|
+
"typescript": "^5.9.3"
|
|
169
|
+
},
|
|
170
|
+
"dependencies": {
|
|
171
|
+
"@hono/graphql-server": "^0.7.0",
|
|
172
|
+
"better-auth": "^1.5.5",
|
|
173
|
+
"class-variance-authority": "^0.7.1",
|
|
174
|
+
"graphql": "^16.13.1",
|
|
175
|
+
"hono": "^4.12.7",
|
|
176
|
+
"hono-rate-limiter": "^0.5.3",
|
|
177
|
+
"ky": "^1.14.3",
|
|
178
|
+
"kysely": "^0.28.11",
|
|
179
|
+
"radix-ui": "^1.4.3",
|
|
177
180
|
"zod": "^4.3.6",
|
|
178
181
|
"zod-to-json-schema": "^3.25.1"
|
|
179
182
|
},
|
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { defineCommand, runMain } from "citty";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Loads and validates the OpacaCMS configuration from a file.
|
|
9
|
+
*/
|
|
10
|
+
export async function loadConfig(configPath: string) {
|
|
11
|
+
if (!fs.existsSync(configPath)) {
|
|
12
|
+
throw new Error(`Config file not found at ${configPath}`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const configUrl = pathToFileURL(configPath).href;
|
|
16
|
+
const mod = await import(configUrl);
|
|
17
|
+
|
|
18
|
+
if (!mod.default) {
|
|
19
|
+
throw new Error(`The configuration file at ${configPath} must have a 'default' export.`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const namedExports = Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule");
|
|
23
|
+
if (namedExports.length > 0) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`Named exports are not allowed in the configuration file. Found: ${namedExports.join(", ")}.`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let opaca = mod.default;
|
|
30
|
+
|
|
31
|
+
if (typeof opaca === "function") {
|
|
32
|
+
const { createD1Mock } = await import("./core/mocks/d1-mock.js");
|
|
33
|
+
const { createR2Mock } = await import("./core/mocks/r2-mock.js");
|
|
34
|
+
|
|
35
|
+
const mockDb = createD1Mock();
|
|
36
|
+
const mockBucket = createR2Mock();
|
|
37
|
+
const mockSecureBucket = createR2Mock();
|
|
38
|
+
|
|
39
|
+
opaca = await opaca(
|
|
40
|
+
{
|
|
41
|
+
DB: mockDb,
|
|
42
|
+
BUCKET: mockBucket,
|
|
43
|
+
SECURE_BUCKET: mockSecureBucket,
|
|
44
|
+
OPACA_SECRET: "cli-secret",
|
|
45
|
+
},
|
|
46
|
+
{ url: "http://localhost:3000" },
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (opaca?.fetch) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
"Default export is a Hono application. The CLI requires the configuration object.",
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!opaca.db) {
|
|
57
|
+
throw new Error("No database adapter found in config");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return opaca;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Tries to find the Opaca config file automatically.
|
|
65
|
+
*/
|
|
66
|
+
export function resolveConfigPath(explicitPath?: string): string {
|
|
67
|
+
let configPath = explicitPath ? resolve(process.cwd(), explicitPath) : "";
|
|
68
|
+
if (!configPath) {
|
|
69
|
+
const defaults = [
|
|
70
|
+
"opaca.config.ts",
|
|
71
|
+
"opaca.config.js",
|
|
72
|
+
"opacacms.config.ts",
|
|
73
|
+
"opacacms.config.js",
|
|
74
|
+
"src/opaca.config.ts",
|
|
75
|
+
"src/opacacms.config.js",
|
|
76
|
+
];
|
|
77
|
+
for (const d of defaults) {
|
|
78
|
+
if (fs.existsSync(resolve(process.cwd(), d))) {
|
|
79
|
+
configPath = resolve(process.cwd(), d);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!configPath || !fs.existsSync(configPath)) {
|
|
86
|
+
throw new Error("Config file not found. Use -c or --config to specify path.");
|
|
87
|
+
}
|
|
88
|
+
return configPath;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const mainCommand = defineCommand({
|
|
92
|
+
meta: {
|
|
93
|
+
name: "opacacms",
|
|
94
|
+
version: "0.1.0",
|
|
95
|
+
description: "OpacaCMS CLI - The Headless CMS that doesn't get in your way.",
|
|
96
|
+
},
|
|
97
|
+
args: {
|
|
98
|
+
config: {
|
|
99
|
+
type: "string",
|
|
100
|
+
alias: "c",
|
|
101
|
+
description: "Path to the OpacaCMS configuration file",
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
subCommands: {
|
|
105
|
+
init: () => import("./commands/init.js").then((m) => m.default),
|
|
106
|
+
migrate: () => import("./commands/migrate.js").then((m) => m.default),
|
|
107
|
+
seed: () => import("./commands/seed.js").then((m) => m.default),
|
|
108
|
+
generate: () => import("./commands/generate.js").then((m) => m.default),
|
|
109
|
+
plugin: () => import("./commands/plugin.js").then((m) => m.default),
|
|
110
|
+
doctor: () => import("./commands/doctor.js").then((m) => m.default),
|
|
111
|
+
dev: () => import("./commands/dev.js").then((m) => m.default),
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (import.meta.main) {
|
|
116
|
+
runMain(mainCommand);
|
|
117
|
+
}
|
package/dist/chunk-6qq3ne6b.js
DELETED
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
flattenFields,
|
|
3
|
-
mapFieldToPostgresType,
|
|
4
|
-
mapFieldToSQLiteType,
|
|
5
|
-
toSnakeCase
|
|
6
|
-
} from "./chunk-qxt9vge8.js";
|
|
7
|
-
import"./chunk-8sqjbsgt.js";
|
|
8
|
-
|
|
9
|
-
// src/db/kysely/migration-generator.ts
|
|
10
|
-
function generateMigrationCode(collections, globals = [], dialect) {
|
|
11
|
-
const allSchemas = [...collections, ...globals];
|
|
12
|
-
const mapType = dialect === "postgres" ? mapFieldToPostgresType : mapFieldToSQLiteType;
|
|
13
|
-
const tsType = dialect === "postgres" ? "timestamp with time zone" : "text";
|
|
14
|
-
let upCode = "";
|
|
15
|
-
let downCode = "";
|
|
16
|
-
for (const collection of allSchemas) {
|
|
17
|
-
const slug = collection.slug;
|
|
18
|
-
const flattenedFields = flattenFields(collection.fields);
|
|
19
|
-
upCode += ` await db.schema.createTable('${slug}')
|
|
20
|
-
`;
|
|
21
|
-
upCode += ` .addColumn('id', 'text', (col) => col.primaryKey())
|
|
22
|
-
`;
|
|
23
|
-
for (const field of flattenedFields) {
|
|
24
|
-
if (field.type === "relationship" && "hasMany" in field && field.hasMany)
|
|
25
|
-
continue;
|
|
26
|
-
const colName = toSnakeCase(field.name);
|
|
27
|
-
if (colName === "id")
|
|
28
|
-
continue;
|
|
29
|
-
const colType = mapType(field);
|
|
30
|
-
const constraints = [];
|
|
31
|
-
if (field.required)
|
|
32
|
-
constraints.push("notNull()");
|
|
33
|
-
if (field.unique)
|
|
34
|
-
constraints.push("unique()");
|
|
35
|
-
if (field.defaultValue !== undefined) {
|
|
36
|
-
let val = field.defaultValue;
|
|
37
|
-
if (typeof val === "string") {
|
|
38
|
-
val = `'${val}'`;
|
|
39
|
-
} else if (typeof val === "boolean") {
|
|
40
|
-
val = dialect === "sqlite" || dialect === "d1" ? val ? 1 : 0 : val;
|
|
41
|
-
}
|
|
42
|
-
constraints.push(`defaultTo(${val})`);
|
|
43
|
-
}
|
|
44
|
-
const constraintChain = constraints.length > 0 ? `.${constraints.join(".")}` : "";
|
|
45
|
-
upCode += ` .addColumn('${colName}', '${colType}', (col) => col${constraintChain})
|
|
46
|
-
`;
|
|
47
|
-
}
|
|
48
|
-
const ts = collection.timestamps !== false;
|
|
49
|
-
if (ts) {
|
|
50
|
-
const config = typeof collection.timestamps === "object" ? collection.timestamps : {};
|
|
51
|
-
const createdField = toSnakeCase(config.createdAt || "createdAt");
|
|
52
|
-
const updatedField = toSnakeCase(config.updatedAt || "updatedAt");
|
|
53
|
-
upCode += ` .addColumn('${createdField}', '${tsType}', (col) => col.defaultTo(sql\`CURRENT_TIMESTAMP\`))
|
|
54
|
-
`;
|
|
55
|
-
upCode += ` .addColumn('${updatedField}', '${tsType}', (col) => col.defaultTo(sql\`CURRENT_TIMESTAMP\`))
|
|
56
|
-
`;
|
|
57
|
-
}
|
|
58
|
-
upCode += ` .execute();
|
|
59
|
-
|
|
60
|
-
`;
|
|
61
|
-
downCode = ` await db.schema.dropTable('${slug}').execute();
|
|
62
|
-
` + downCode;
|
|
63
|
-
if ("versions" in collection && collection.versions) {
|
|
64
|
-
const versionsTable = `${toSnakeCase(slug)}_versions`;
|
|
65
|
-
upCode += ` await db.schema.createTable('${versionsTable}')
|
|
66
|
-
`;
|
|
67
|
-
upCode += ` .addColumn('id', 'text', (col) => col.primaryKey())
|
|
68
|
-
`;
|
|
69
|
-
upCode += ` .addColumn('_parent_id', 'text', (col) => col.notNull())
|
|
70
|
-
`;
|
|
71
|
-
upCode += ` .addColumn('_version_data', '${dialect === "postgres" ? "jsonb" : "text"}', (col) => col.notNull())
|
|
72
|
-
`;
|
|
73
|
-
upCode += ` .addColumn('_status', 'text')
|
|
74
|
-
`;
|
|
75
|
-
upCode += ` .addColumn('created_at', '${tsType}', (col) => col.defaultTo(sql\`CURRENT_TIMESTAMP\`))
|
|
76
|
-
`;
|
|
77
|
-
upCode += ` .execute();
|
|
78
|
-
|
|
79
|
-
`;
|
|
80
|
-
downCode = ` await db.schema.dropTable('${versionsTable}').execute();
|
|
81
|
-
` + downCode;
|
|
82
|
-
}
|
|
83
|
-
for (const field of flattenedFields) {
|
|
84
|
-
if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
|
|
85
|
-
const colName = toSnakeCase(field.name);
|
|
86
|
-
const joinTableName = `${slug}_${colName}_relations`.toLowerCase();
|
|
87
|
-
upCode += ` await db.schema.createTable('${joinTableName}')
|
|
88
|
-
`;
|
|
89
|
-
upCode += ` .addColumn('id', 'text', (col) => col.primaryKey())
|
|
90
|
-
`;
|
|
91
|
-
upCode += ` .addColumn('source_id', 'text', (col) => col.notNull())
|
|
92
|
-
`;
|
|
93
|
-
upCode += ` .addColumn('target_id', 'text', (col) => col.notNull())
|
|
94
|
-
`;
|
|
95
|
-
upCode += ` .addColumn('order', 'integer', (col) => col.defaultTo(0))
|
|
96
|
-
`;
|
|
97
|
-
upCode += ` .execute();
|
|
98
|
-
|
|
99
|
-
`;
|
|
100
|
-
downCode = ` await db.schema.dropTable('${joinTableName}').execute();
|
|
101
|
-
` + downCode;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
for (const field of collection.fields) {
|
|
105
|
-
if (field.type === "blocks" && field.blocks && Array.isArray(field.blocks)) {
|
|
106
|
-
for (const block of field.blocks) {
|
|
107
|
-
const blockName = toSnakeCase(field.name);
|
|
108
|
-
const blockTableName = `${slug}_${blockName}_${block.slug}`.toLowerCase();
|
|
109
|
-
upCode += ` await db.schema.createTable('${blockTableName}')
|
|
110
|
-
`;
|
|
111
|
-
upCode += ` .addColumn('id', 'text', (col) => col.primaryKey())
|
|
112
|
-
`;
|
|
113
|
-
upCode += ` .addColumn('_parent_id', 'text', (col) => col.notNull())
|
|
114
|
-
`;
|
|
115
|
-
upCode += ` .addColumn('_order', 'integer', (col) => col.defaultTo(0))
|
|
116
|
-
`;
|
|
117
|
-
upCode += ` .addColumn('block_type', 'text', (col) => col.notNull())
|
|
118
|
-
`;
|
|
119
|
-
const blockFlattened = flattenFields(block.fields);
|
|
120
|
-
for (const bField of blockFlattened) {
|
|
121
|
-
const bColName = toSnakeCase(bField.name);
|
|
122
|
-
if (bColName === "id")
|
|
123
|
-
continue;
|
|
124
|
-
const bColType = mapType(bField);
|
|
125
|
-
const bConstraints = [];
|
|
126
|
-
if (bField.required)
|
|
127
|
-
bConstraints.push("notNull()");
|
|
128
|
-
if (bField.unique)
|
|
129
|
-
bConstraints.push("unique()");
|
|
130
|
-
if (bField.defaultValue !== undefined) {
|
|
131
|
-
let bVal = bField.defaultValue;
|
|
132
|
-
if (typeof bVal === "string")
|
|
133
|
-
bVal = `'${bVal}'`;
|
|
134
|
-
else if (typeof bVal === "boolean")
|
|
135
|
-
bVal = dialect === "sqlite" || dialect === "d1" ? bVal ? 1 : 0 : bVal;
|
|
136
|
-
bConstraints.push(`defaultTo(${bVal})`);
|
|
137
|
-
}
|
|
138
|
-
const bConstraintChain = bConstraints.length > 0 ? `.${bConstraints.join(".")}` : "";
|
|
139
|
-
upCode += ` .addColumn('${bColName}', '${bColType}', (col) => col${bConstraintChain})
|
|
140
|
-
`;
|
|
141
|
-
}
|
|
142
|
-
upCode += ` .addColumn('created_at', '${tsType}', (col) => col.defaultTo(sql\`CURRENT_TIMESTAMP\`))
|
|
143
|
-
`;
|
|
144
|
-
upCode += ` .addColumn('updated_at', '${tsType}', (col) => col.defaultTo(sql\`CURRENT_TIMESTAMP\`))
|
|
145
|
-
`;
|
|
146
|
-
upCode += ` .execute();
|
|
147
|
-
|
|
148
|
-
`;
|
|
149
|
-
downCode = ` await db.schema.dropTable('${blockTableName}').execute();
|
|
150
|
-
` + downCode;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return `import { type OpacaMigrationDb, sql } from 'opacacms/db';
|
|
156
|
-
|
|
157
|
-
export async function up(db: OpacaMigrationDb): Promise<void> {
|
|
158
|
-
${upCode}}
|
|
159
|
-
|
|
160
|
-
export async function down(db: OpacaMigrationDb): Promise<void> {
|
|
161
|
-
${downCode}}
|
|
162
|
-
`;
|
|
163
|
-
}
|
|
164
|
-
function generateSQLCode(collections, globals = []) {
|
|
165
|
-
const allSchemas = [...collections, ...globals];
|
|
166
|
-
let sql = `-- OpacaCMS Auto-generated SQL Migration
|
|
167
|
-
|
|
168
|
-
`;
|
|
169
|
-
for (const collection of allSchemas) {
|
|
170
|
-
const slug = collection.slug;
|
|
171
|
-
const flattenedFields = flattenFields(collection.fields);
|
|
172
|
-
sql += `CREATE TABLE IF NOT EXISTS "${slug}" (
|
|
173
|
-
`;
|
|
174
|
-
sql += ` "id" TEXT PRIMARY KEY`;
|
|
175
|
-
for (const field of flattenedFields) {
|
|
176
|
-
if (field.type === "relationship" && "hasMany" in field && field.hasMany)
|
|
177
|
-
continue;
|
|
178
|
-
const colName = toSnakeCase(field.name);
|
|
179
|
-
if (colName === "id")
|
|
180
|
-
continue;
|
|
181
|
-
const colType = mapFieldToSQLiteType(field);
|
|
182
|
-
sql += `,
|
|
183
|
-
"${colName}" ${colType.toUpperCase()}`;
|
|
184
|
-
if (field.required)
|
|
185
|
-
sql += " NOT NULL";
|
|
186
|
-
if (field.unique)
|
|
187
|
-
sql += " UNIQUE";
|
|
188
|
-
if (field.defaultValue !== undefined) {
|
|
189
|
-
let val = field.defaultValue;
|
|
190
|
-
if (typeof val === "string")
|
|
191
|
-
val = `'${val}'`;
|
|
192
|
-
else if (typeof val === "boolean")
|
|
193
|
-
val = val ? 1 : 0;
|
|
194
|
-
sql += ` DEFAULT ${val}`;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
const ts = collection.timestamps !== false;
|
|
198
|
-
if (ts) {
|
|
199
|
-
const config = typeof collection.timestamps === "object" ? collection.timestamps : {};
|
|
200
|
-
const createdField = toSnakeCase(config.createdAt || "createdAt");
|
|
201
|
-
const updatedField = toSnakeCase(config.updatedAt || "updatedAt");
|
|
202
|
-
sql += `,
|
|
203
|
-
"${createdField}" TEXT DEFAULT CURRENT_TIMESTAMP`;
|
|
204
|
-
sql += `,
|
|
205
|
-
"${updatedField}" TEXT DEFAULT CURRENT_TIMESTAMP`;
|
|
206
|
-
}
|
|
207
|
-
sql += `
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
`;
|
|
211
|
-
if ("versions" in collection && collection.versions) {
|
|
212
|
-
const versionsTable = `${toSnakeCase(slug)}_versions`;
|
|
213
|
-
sql += `CREATE TABLE IF NOT EXISTS "${versionsTable}" (
|
|
214
|
-
`;
|
|
215
|
-
sql += ` "id" TEXT PRIMARY KEY,
|
|
216
|
-
`;
|
|
217
|
-
sql += ` "_parent_id" TEXT NOT NULL,
|
|
218
|
-
`;
|
|
219
|
-
sql += ` "_version_data" TEXT NOT NULL,
|
|
220
|
-
`;
|
|
221
|
-
sql += ` "_status" TEXT,
|
|
222
|
-
`;
|
|
223
|
-
sql += ` "created_at" TEXT DEFAULT CURRENT_TIMESTAMP
|
|
224
|
-
`;
|
|
225
|
-
sql += `);
|
|
226
|
-
|
|
227
|
-
`;
|
|
228
|
-
}
|
|
229
|
-
for (const field of flattenedFields) {
|
|
230
|
-
if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
|
|
231
|
-
const colName = toSnakeCase(field.name);
|
|
232
|
-
const joinTableName = `${slug}_${colName}_relations`.toLowerCase();
|
|
233
|
-
sql += `CREATE TABLE IF NOT EXISTS "${joinTableName}" (
|
|
234
|
-
`;
|
|
235
|
-
sql += ` "id" TEXT PRIMARY KEY,
|
|
236
|
-
`;
|
|
237
|
-
sql += ` "source_id" TEXT NOT NULL,
|
|
238
|
-
`;
|
|
239
|
-
sql += ` "target_id" TEXT NOT NULL,
|
|
240
|
-
`;
|
|
241
|
-
sql += ` "order" INTEGER DEFAULT 0
|
|
242
|
-
`;
|
|
243
|
-
sql += `);
|
|
244
|
-
|
|
245
|
-
`;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
for (const field of collection.fields) {
|
|
249
|
-
if (field.type === "blocks" && field.blocks && Array.isArray(field.blocks)) {
|
|
250
|
-
for (const block of field.blocks) {
|
|
251
|
-
const blockName = toSnakeCase(field.name);
|
|
252
|
-
const blockTableName = `${slug}_${blockName}_${block.slug}`.toLowerCase();
|
|
253
|
-
sql += `CREATE TABLE IF NOT EXISTS "${blockTableName}" (
|
|
254
|
-
`;
|
|
255
|
-
sql += ` "id" TEXT PRIMARY KEY,
|
|
256
|
-
`;
|
|
257
|
-
sql += ` "_parent_id" TEXT NOT NULL,
|
|
258
|
-
`;
|
|
259
|
-
sql += ` "_order" INTEGER DEFAULT 0,
|
|
260
|
-
`;
|
|
261
|
-
sql += ` "block_type" TEXT NOT NULL`;
|
|
262
|
-
const blockFlattened = flattenFields(block.fields);
|
|
263
|
-
for (const bField of blockFlattened) {
|
|
264
|
-
const bColName = toSnakeCase(bField.name);
|
|
265
|
-
if (bColName === "id")
|
|
266
|
-
continue;
|
|
267
|
-
const bColType = mapFieldToSQLiteType(bField);
|
|
268
|
-
sql += `,
|
|
269
|
-
"${bColName}" ${bColType.toUpperCase()}`;
|
|
270
|
-
}
|
|
271
|
-
sql += `,
|
|
272
|
-
"created_at" TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
273
|
-
`;
|
|
274
|
-
sql += ` "updated_at" TEXT DEFAULT CURRENT_TIMESTAMP
|
|
275
|
-
`;
|
|
276
|
-
sql += `);
|
|
277
|
-
|
|
278
|
-
`;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
return sql;
|
|
284
|
-
}
|
|
285
|
-
export {
|
|
286
|
-
generateSQLCode,
|
|
287
|
-
generateMigrationCode
|
|
288
|
-
};
|