opacacms 0.2.1 → 0.3.1

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.
Files changed (185) hide show
  1. package/README.md +31 -22
  2. package/dist/admin/auth-client.d.ts +39 -39
  3. package/dist/admin/index.d.ts +2 -2
  4. package/dist/admin/index.js +15 -10520
  5. package/dist/admin/plugin-client.d.ts +65 -0
  6. package/dist/admin/react.d.ts +2 -2
  7. package/dist/admin/react.js +34 -4
  8. package/dist/admin/stores/ui.d.ts +19 -4
  9. package/dist/admin/ui/components/PluginSettingsForm.d.ts +2 -2
  10. package/dist/admin/ui/components/custom-alert.d.ts +7 -0
  11. package/dist/admin/ui/components/{DetailSheet.d.ts → detail-sheet.d.ts} +1 -2
  12. package/dist/admin/ui/components/fields/FieldLabel.d.ts +1 -1
  13. package/dist/admin/ui/components/fields/RelationshipField.d.ts +1 -1
  14. package/dist/admin/ui/components/media/AssetManagerModal.d.ts +2 -2
  15. package/dist/admin/ui/components/plugin-iframe.d.ts +7 -0
  16. package/dist/admin/ui/components/ui/accordion.d.ts +17 -7
  17. package/dist/admin/ui/components/ui/alert-dialog.d.ts +16 -12
  18. package/dist/admin/ui/components/ui/button.d.ts +11 -7
  19. package/dist/admin/ui/components/ui/relationship.d.ts +1 -1
  20. package/dist/admin/ui/components/ui/sheet.d.ts +14 -27
  21. package/dist/admin/ui/components/ui/tooltip.d.ts +7 -0
  22. package/dist/admin/ui/components/versions-sheet.d.ts +4 -5
  23. package/dist/admin/ui/views/collection-list-view.d.ts +1 -1
  24. package/dist/admin/ui/views/dashboard-view.d.ts +1 -1
  25. package/dist/admin/ui/views/media-registry-view.d.ts +3 -3
  26. package/dist/admin/ui/views/settings-view.d.ts +2 -2
  27. package/dist/admin/vue.js +27 -4
  28. package/dist/admin/webcomponent.js +66 -16
  29. package/dist/admin.css +1 -1
  30. package/dist/auth/index.d.ts +43 -43
  31. package/dist/{chunk-7y1nbmw6.js → chunk-1bd7fz7n.js} +32 -2
  32. package/dist/chunk-1qm0m8r8.js +413 -0
  33. package/dist/chunk-2k3ysje3.js +31 -0
  34. package/dist/{chunk-jdfw4v3r.js → chunk-3j9zjfmn.js} +95 -30
  35. package/dist/{chunk-byq8g0rd.js → chunk-48ywpd0a.js} +16 -22
  36. package/dist/{chunk-tfnaf41w.js → chunk-5422w4eq.js} +41 -25
  37. package/dist/chunk-56n342hs.js +95 -0
  38. package/dist/chunk-5b8r0v8c.js +47 -0
  39. package/dist/chunk-63yg00vx.js +263 -0
  40. package/dist/{chunk-8sqjbsgt.js → chunk-6bywt602.js} +26 -1
  41. package/dist/{chunk-v9z61v3g.js → chunk-6qs0g65f.js} +43 -3
  42. package/dist/chunk-7rr5p01g.js +581 -0
  43. package/dist/{chunk-2es275xs.js → chunk-941zxavt.js} +867 -322
  44. package/dist/{chunk-51z3x7kq.js → chunk-a3qae86h.js} +1 -1
  45. package/dist/{chunk-3rdhbedb.js → chunk-adq2b75c.js} +2 -2
  46. package/dist/chunk-d0tb1xjw.js +93 -0
  47. package/dist/chunk-d7cgd6vn.js +318 -0
  48. package/dist/{chunk-6d1vdfwa.js → chunk-e0g6gn7n.js} +54 -75
  49. package/dist/chunk-ec4jhybj.js +1137 -0
  50. package/dist/chunk-fatyf6f7.js +221 -0
  51. package/dist/{chunk-526a3gqx.js → chunk-fnsf1dfm.js} +1 -1
  52. package/dist/chunk-g9bxb6h0.js +205 -0
  53. package/dist/chunk-gyaf5kgf.js +10 -0
  54. package/dist/{chunk-9kxpbcb1.js → chunk-h6dhexzr.js} +16 -7
  55. package/dist/{chunk-dykn5hr6.js → chunk-j8js1y0h.js} +31 -74
  56. package/dist/{chunk-t0zg026p.js → chunk-jq1drsen.js} +12 -1
  57. package/dist/{chunk-b3kr8w41.js → chunk-m24yqkeq.js} +38 -26
  58. package/dist/chunk-m5ems3hh.js +410 -0
  59. package/dist/{chunk-8scgdznr.js → chunk-m83ybzf8.js} +15 -18
  60. package/dist/chunk-majsbncm.js +98 -0
  61. package/dist/chunk-mp2gt9yh.js +237 -0
  62. package/dist/chunk-n1twhqmf.js +54 -0
  63. package/dist/{chunk-bygjkgrx.js → chunk-naqcqj8n.js} +57 -80
  64. package/dist/chunk-q5sb5dcr.js +15 -0
  65. package/dist/{chunk-06ks4ggh.js → chunk-qhdsjek6.js} +49 -89
  66. package/dist/{chunk-n133qpsm.js → chunk-qsh2nqz3.js} +50 -81
  67. package/dist/chunk-r0ms5tk1.js +76 -0
  68. package/dist/chunk-rwqwsanx.js +75 -0
  69. package/dist/chunk-sqsfk9p4.js +700 -0
  70. package/dist/{chunk-5gvbp2qa.js → chunk-x7bnzswh.js} +25 -18
  71. package/dist/cli/commands/dev.d.ts +8 -0
  72. package/dist/cli/commands/doctor.d.ts +8 -0
  73. package/dist/cli/commands/generate.d.ts +26 -0
  74. package/dist/cli/commands/init.d.ts +13 -1
  75. package/dist/cli/commands/migrate.d.ts +33 -0
  76. package/dist/cli/commands/plugin.d.ts +13 -0
  77. package/dist/cli/commands/seed.d.ts +21 -0
  78. package/dist/cli/{commands/migrate-commands.d.ts → core/migrations/migrate-logic.d.ts} +2 -2
  79. package/dist/cli/core/migrations/schema-diff-engine.d.ts +12 -0
  80. package/dist/cli/core/migrations/schema-diff.d.ts +11 -0
  81. package/dist/cli/{seeding.d.ts → core/seeding/auto-seed.d.ts} +7 -4
  82. package/dist/cli/core/seeding/seed-logic.d.ts +2 -0
  83. package/dist/cli/index.d.ts +4 -0
  84. package/dist/cli/index.js +6 -170
  85. package/dist/client/RichText.d.ts +5 -0
  86. package/dist/client/rich-text-utils.d.ts +5 -0
  87. package/dist/client.js +3 -2
  88. package/dist/config.d.ts +3 -3
  89. package/dist/db/better-sqlite.d.ts +2 -3
  90. package/dist/db/better-sqlite.js +6 -5
  91. package/dist/db/bun-sqlite.d.ts +2 -3
  92. package/dist/db/bun-sqlite.js +6 -5
  93. package/dist/db/d1.d.ts +13 -7
  94. package/dist/db/d1.js +6 -5
  95. package/dist/db/index.d.ts +2 -2
  96. package/dist/db/index.js +10 -12
  97. package/dist/db/kysely/factory.d.ts +29 -0
  98. package/dist/db/kysely/plugins/audit-logging.d.ts +48 -0
  99. package/dist/db/kysely/plugins/auto-timestamps.d.ts +38 -0
  100. package/dist/db/kysely/plugins/cursor-pagination.d.ts +42 -0
  101. package/dist/db/kysely/plugins/deadlock-handler.d.ts +47 -0
  102. package/dist/db/kysely/plugins/draft-swapper.d.ts +33 -0
  103. package/dist/db/kysely/plugins/field-masking.d.ts +45 -0
  104. package/dist/db/kysely/plugins/fts-normalizer.d.ts +38 -0
  105. package/dist/db/kysely/plugins/i18n-fallback.d.ts +48 -0
  106. package/dist/db/kysely/plugins/id-generation.d.ts +42 -0
  107. package/dist/db/kysely/plugins/index.d.ts +16 -0
  108. package/dist/db/kysely/plugins/json-flattener.d.ts +38 -0
  109. package/dist/db/kysely/plugins/relationship-preloading.d.ts +39 -0
  110. package/dist/db/kysely/plugins/slug-generation.d.ts +37 -0
  111. package/dist/db/kysely/plugins/soft-delete.d.ts +42 -0
  112. package/dist/db/kysely/plugins/tree-resolver.d.ts +39 -0
  113. package/dist/db/kysely/plugins/virtual-field-resolver.d.ts +54 -0
  114. package/dist/db/kysely/plugins/zod-coercion.d.ts +34 -0
  115. package/dist/db/kysely/snapshot/snapshot-manager.d.ts +18 -0
  116. package/dist/db/postgres.d.ts +2 -2
  117. package/dist/db/postgres.js +6 -5
  118. package/dist/db/sqlite.d.ts +2 -3
  119. package/dist/db/sqlite.js +6 -5
  120. package/dist/index.d.ts +3 -0
  121. package/dist/index.js +161 -7
  122. package/dist/runtimes/bun.js +9 -6
  123. package/dist/runtimes/cloudflare-workers.d.ts +3 -1
  124. package/dist/runtimes/cloudflare-workers.js +36 -7
  125. package/dist/runtimes/next.js +8 -5
  126. package/dist/runtimes/node.js +9 -6
  127. package/dist/schema/collection.d.ts +116 -70
  128. package/dist/schema/compiler.d.ts +6 -0
  129. package/dist/schema/global.d.ts +38 -71
  130. package/dist/schema/index.d.ts +5 -4
  131. package/dist/schema/index.js +35 -550
  132. package/dist/schema/zod.d.ts +564 -0
  133. package/dist/server/admin-router.d.ts +1 -1
  134. package/dist/server/collection-router.d.ts +1 -1
  135. package/dist/server/graphql.d.ts +6 -0
  136. package/dist/server/handlers.d.ts +25 -7
  137. package/dist/server/middlewares/auth.d.ts +1 -1
  138. package/dist/server/plugins-loader.d.ts +1 -1
  139. package/dist/server/router.d.ts +2 -2
  140. package/dist/server/routers/admin.d.ts +1 -1
  141. package/dist/server/routers/auth.d.ts +1 -1
  142. package/dist/server/routers/collections.d.ts +4 -1
  143. package/dist/server/routers/plugins.d.ts +2 -2
  144. package/dist/server/setup-middlewares.d.ts +1 -1
  145. package/dist/server/system-router.d.ts +1 -1
  146. package/dist/server.js +11 -6
  147. package/dist/storage/adapters/cloudflare-r2.d.ts +11 -2
  148. package/dist/storage/index.js +5 -5
  149. package/dist/types.d.ts +253 -42
  150. package/dist/utils/context.d.ts +14 -0
  151. package/dist/utils/logger.d.ts +2 -0
  152. package/dist/utils/string.d.ts +10 -0
  153. package/dist/utils/webhooks-engine.d.ts +24 -0
  154. package/dist/validation.d.ts +67 -1
  155. package/dist/validator.d.ts +1 -0
  156. package/package.json +50 -11
  157. package/src/cli/index.ts +117 -0
  158. package/dist/chunk-6qq3ne6b.js +0 -288
  159. package/dist/chunk-6v1fw7q7.js +0 -126
  160. package/dist/chunk-7a9kn0np.js +0 -116
  161. package/dist/chunk-bexcv7xe.js +0 -36
  162. package/dist/chunk-d3ffeqp9.js +0 -87
  163. package/dist/chunk-fj19qccp.js +0 -78
  164. package/dist/chunk-g1jb60xd.js +0 -17
  165. package/dist/chunk-j53pz21t.js +0 -20
  166. package/dist/chunk-mkn49zmy.js +0 -102
  167. package/dist/chunk-r39em4yj.js +0 -29
  168. package/dist/chunk-rsf0tpy1.js +0 -8
  169. package/dist/chunk-srsac177.js +0 -85
  170. package/dist/chunk-twpvxfce.js +0 -64
  171. package/dist/chunk-ywm4t2gm.js +0 -19
  172. package/dist/cli/commands/plugin-sync.d.ts +0 -1
  173. package/dist/cli/commands/seed-command.d.ts +0 -2
  174. package/dist/plugins/ui-bridge.d.ts +0 -12
  175. package/dist/schema/fields/base.d.ts +0 -84
  176. package/dist/schema/fields/index.d.ts +0 -147
  177. package/dist/schema/infer.d.ts +0 -55
  178. /package/dist/admin/ui/components/{ColumnVisibilityToggle.d.ts → column-visibility-toggle.d.ts} +0 -0
  179. /package/dist/admin/ui/components/{DataDetailView.d.ts → data-detail-view.d.ts} +0 -0
  180. /package/dist/cli/{d1-mock.d.ts → core/mocks/d1-mock.d.ts} +0 -0
  181. /package/dist/cli/{r2-mock.d.ts → core/mocks/r2-mock.d.ts} +0 -0
  182. /package/dist/cli/{commands → core/plugins}/plugin-build.d.ts +0 -0
  183. /package/dist/cli/{commands → core/plugins}/plugin-init.d.ts +0 -0
  184. /package/dist/cli/{commands → core/types}/generate-types.d.ts +0 -0
  185. /package/dist/{schema/fields/validation.test.d.ts → cli/seeding.test.d.ts} +0 -0
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  notify
3
- } from "./chunk-8scgdznr.js";
3
+ } from "./chunk-m83ybzf8.js";
4
+ import"./chunk-6bywt602.js";
4
5
 
5
6
  // src/admin/stores/auth.ts
6
7
  import { atom, computed } from "nanostores";
@@ -9,24 +10,6 @@ import { atom, computed } from "nanostores";
9
10
  import { createAuthClient } from "better-auth/client";
10
11
  import { adminClient } from "better-auth/client/plugins";
11
12
  var client = null;
12
- var currentURL = null;
13
- var configureAuth = (serverUrl) => {
14
- if (!serverUrl || !serverUrl.startsWith("http"))
15
- return;
16
- const url = serverUrl;
17
- const baseURL = url.replace(/\/$/, "") + "/api/auth";
18
- if (client && currentURL === baseURL)
19
- return;
20
- currentURL = baseURL;
21
- client = createAuthClient({
22
- baseURL,
23
- autoRefresh: true,
24
- fetchOptions: {
25
- credentials: "include"
26
- },
27
- plugins: [adminClient()]
28
- });
29
- };
30
13
  var authClient = new Proxy({}, {
31
14
  get(_, prop) {
32
15
  if (!client) {
@@ -62,7 +45,11 @@ async function login(data) {
62
45
  if (res.error) {
63
46
  throw new Error(res.error.message || "Invalid credentials");
64
47
  }
65
- await syncSession();
48
+ if (res.data) {
49
+ $session.set(res.data);
50
+ } else {
51
+ await syncSession();
52
+ }
66
53
  notify("Logged in successfully", "success");
67
54
  return res;
68
55
  } catch (error) {
@@ -84,5 +71,12 @@ async function logout() {
84
71
  $isAuthPending.set(false);
85
72
  }
86
73
  }
87
-
88
- export { configureAuth, authClient, $session, $isAuthPending, $user, $isAuthenticated, syncSession, login, logout };
74
+ export {
75
+ syncSession,
76
+ logout,
77
+ login,
78
+ $user,
79
+ $session,
80
+ $isAuthenticated,
81
+ $isAuthPending
82
+ };
@@ -3,20 +3,23 @@ import {
3
3
  flattenPayload,
4
4
  pushSchema,
5
5
  unflattenRow
6
- } from "./chunk-dykn5hr6.js";
6
+ } from "./chunk-j8js1y0h.js";
7
7
  import {
8
8
  BaseDatabaseAdapter
9
9
  } from "./chunk-s8mqwnm1.js";
10
+ import {
11
+ requestContext
12
+ } from "./chunk-q5sb5dcr.js";
10
13
  import {
11
14
  getRelationalFields,
12
15
  toSnakeCase
13
16
  } from "./chunk-qxt9vge8.js";
14
17
  import {
15
18
  logger
16
- } from "./chunk-t0zg026p.js";
19
+ } from "./chunk-jq1drsen.js";
17
20
  import {
18
21
  __require
19
- } from "./chunk-8sqjbsgt.js";
22
+ } from "./chunk-6bywt602.js";
20
23
 
21
24
  // src/db/postgres.ts
22
25
  import fs from "node:fs/promises";
@@ -24,7 +27,6 @@ import path from "node:path";
24
27
  import {
25
28
  CompiledQuery,
26
29
  FileMigrationProvider,
27
- Kysely,
28
30
  Migrator,
29
31
  PostgresDialect
30
32
  } from "kysely";
@@ -69,7 +71,8 @@ class PostgresAdapter extends BaseDatabaseAdapter {
69
71
  ssl: this.config.ssl
70
72
  });
71
73
  }
72
- this._db = new Kysely({
74
+ const { createOpacaKysely } = await import("./chunk-sqsfk9p4.js");
75
+ this._db = createOpacaKysely({
73
76
  dialect: new PostgresDialect({
74
77
  pool: {
75
78
  connect: async () => {
@@ -82,7 +85,12 @@ class PostgresAdapter extends BaseDatabaseAdapter {
82
85
  end: async () => {},
83
86
  on: () => {}
84
87
  }
85
- })
88
+ }),
89
+ config: {
90
+ collections: this._collections,
91
+ globals: this._globals,
92
+ db: { name: "postgres" }
93
+ }
86
94
  });
87
95
  }
88
96
  async disconnect() {
@@ -130,15 +138,6 @@ class PostgresAdapter extends BaseDatabaseAdapter {
130
138
  delete flatData[key];
131
139
  }
132
140
  }
133
- if (!flatData.id)
134
- flatData.id = crypto.randomUUID();
135
- const now = new Date().toISOString();
136
- const createdKey = toSnakeCase("createdAt");
137
- const updatedKey = toSnakeCase("updatedAt");
138
- if (!flatData[createdKey])
139
- flatData[createdKey] = now;
140
- if (!flatData[updatedKey])
141
- flatData[updatedKey] = now;
142
141
  await tx.insertInto(tableName).values(flatData).execute();
143
142
  for (const [key, values] of Object.entries(hasManyData)) {
144
143
  const joinTableName = `${tableName}_${toSnakeCase(key)}_relations`.toLowerCase();
@@ -185,7 +184,7 @@ class PostgresAdapter extends BaseDatabaseAdapter {
185
184
  const unflattened = unflattenRow(row);
186
185
  const colDef = this._collections.find((c) => c.slug === collection);
187
186
  if (colDef) {
188
- const { getRelationalFields: getRelationalFields2, toSnakeCase: toSnakeCase2 } = await import("./chunk-526a3gqx.js");
187
+ const { getRelationalFields: getRelationalFields2, toSnakeCase: toSnakeCase2 } = await import("./chunk-fnsf1dfm.js");
189
188
  const relationalFields = getRelationalFields2(colDef.fields);
190
189
  for (const field of relationalFields) {
191
190
  if (!field.name)
@@ -241,9 +240,17 @@ class PostgresAdapter extends BaseDatabaseAdapter {
241
240
  const page = options?.page || 1;
242
241
  const limit = options?.limit || 10;
243
242
  const offset = (page - 1) * limit;
243
+ const cursorColumn = options?.cursorColumn || "id";
244
244
  const total = await this.count(collection, query);
245
245
  const tableName = toSnakeCase(collection);
246
- let qb = this.db.selectFrom(tableName).selectAll().limit(limit).offset(offset);
246
+ let qb = this.db.selectFrom(tableName).selectAll().limit(limit);
247
+ if (options?.after) {
248
+ qb = qb.where(cursorColumn, ">", options.after);
249
+ } else if (options?.before) {
250
+ qb = qb.where(cursorColumn, "<", options.before);
251
+ } else {
252
+ qb = qb.offset(offset);
253
+ }
247
254
  if (query && Object.keys(query).length > 0) {
248
255
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
249
256
  }
@@ -253,11 +260,13 @@ class PostgresAdapter extends BaseDatabaseAdapter {
253
260
  qb = qb.orderBy(col, dir === "desc" ? "desc" : "asc");
254
261
  }
255
262
  } else {
256
- qb = qb.orderBy("created_at", "desc");
263
+ qb = qb.orderBy(cursorColumn, "desc");
257
264
  }
258
265
  const rows = await qb.execute();
259
266
  if (rows.length === 0) {
260
267
  const totalPages2 = Math.ceil(total / limit);
268
+ const afterAnchor = options?.after;
269
+ const beforeAnchor = options?.before;
261
270
  return {
262
271
  docs: [],
263
272
  totalDocs: total,
@@ -265,10 +274,12 @@ class PostgresAdapter extends BaseDatabaseAdapter {
265
274
  totalPages: totalPages2,
266
275
  page,
267
276
  pagingCounter: offset + 1,
268
- hasNextPage: page * limit < total,
269
- hasPrevPage: page > 1,
270
- prevPage: page > 1 ? page - 1 : null,
271
- nextPage: page < totalPages2 ? page + 1 : null
277
+ hasNextPage: false,
278
+ hasPrevPage: !!afterAnchor || page > 1,
279
+ prevPage: null,
280
+ nextPage: null,
281
+ nextCursor: null,
282
+ prevCursor: afterAnchor ? afterAnchor : null
272
283
  };
273
284
  }
274
285
  const rowIds = rows.map((r) => r.id);
@@ -346,9 +357,11 @@ class PostgresAdapter extends BaseDatabaseAdapter {
346
357
  page,
347
358
  pagingCounter: offset + 1,
348
359
  hasNextPage: page * limit < total,
349
- hasPrevPage: page > 1,
360
+ hasPrevPage: page > 1 || !!options?.after || !!options?.before,
350
361
  prevPage: page > 1 ? page - 1 : null,
351
- nextPage: page < totalPages ? page + 1 : null
362
+ nextPage: page < totalPages ? page + 1 : null,
363
+ nextCursor: docs.length > 0 ? docs[docs.length - 1][cursorColumn] : null,
364
+ prevCursor: docs.length > 0 && (page > 1 || !!options?.after || !!options?.before) ? docs[0][cursorColumn] : null
352
365
  };
353
366
  }
354
367
  async update(collection, query, data) {
@@ -362,6 +375,9 @@ class PostgresAdapter extends BaseDatabaseAdapter {
362
375
  const current = await this.findOne(collection, normalizedQuery, tx);
363
376
  if (!current)
364
377
  throw new Error("Document not found");
378
+ const store = requestContext.getStore();
379
+ if (store)
380
+ store.previousData = current;
365
381
  const colDef = this._collections.find((c) => c.slug === collection);
366
382
  const jsonFields = colDef?.fields.filter((f) => f.name && (["richtext", "json", "file"].includes(f.type) || f.localized)).map((f) => f.name) || [];
367
383
  const flatData = flattenPayload(data, "", jsonFields);
@@ -568,7 +584,7 @@ class PostgresAdapter extends BaseDatabaseAdapter {
568
584
  }
569
585
  }
570
586
  async migrate(collections, globals = []) {
571
- const { getSystemCollections } = await import("./chunk-3rdhbedb.js");
587
+ const { getSystemCollections } = await import("./chunk-adq2b75c.js");
572
588
  this._collections = [...getSystemCollections(), ...collections];
573
589
  this._globals = globals;
574
590
  if (this.push && this._db) {
@@ -0,0 +1,95 @@
1
+ import {
2
+ require_picocolors
3
+ } from "./chunk-rwqwsanx.js";
4
+ import {
5
+ Gt,
6
+ R,
7
+ Vt,
8
+ Wt,
9
+ be
10
+ } from "./chunk-ec4jhybj.js";
11
+ import {
12
+ loadConfig,
13
+ resolveConfigPath
14
+ } from "./chunk-majsbncm.js";
15
+ import {
16
+ defineCommand
17
+ } from "./chunk-1qm0m8r8.js";
18
+ import {
19
+ __toESM
20
+ } from "./chunk-6bywt602.js";
21
+
22
+ // src/cli/commands/doctor.ts
23
+ import fs from "node:fs";
24
+ var import_picocolors = __toESM(require_picocolors(), 1);
25
+ var doctor_default = defineCommand({
26
+ meta: {
27
+ name: "doctor",
28
+ description: "Diagnose your OpacaCMS project configuration and database connection"
29
+ },
30
+ args: {
31
+ config: {
32
+ type: "string",
33
+ alias: "c",
34
+ description: "Path to the OpacaCMS configuration file"
35
+ }
36
+ },
37
+ async run({ args }) {
38
+ console.log();
39
+ Wt(import_picocolors.default.bgMagenta(import_picocolors.default.white(" OpacaCMS Doctor ")));
40
+ const s = be();
41
+ s.start("Locating configuration file...");
42
+ let configPath;
43
+ try {
44
+ configPath = resolveConfigPath(args.config);
45
+ s.stop(`Config found at ${import_picocolors.default.green(configPath)}`);
46
+ } catch (err) {
47
+ s.stop(import_picocolors.default.red("Config file not found."));
48
+ R.error("Could not find opacacms.config.ts or similar.");
49
+ Gt(import_picocolors.default.red("Diagnosis failed."));
50
+ process.exit(1);
51
+ }
52
+ s.start("Loading configuration...");
53
+ let opaca;
54
+ try {
55
+ opaca = await loadConfig(configPath);
56
+ s.stop(`Configuration loaded successfully. App Name: ${import_picocolors.default.cyan(opaca.appName || "Unknown")}`);
57
+ } catch (err) {
58
+ s.stop(import_picocolors.default.red("Failed to load configuration."));
59
+ R.error(err.message);
60
+ Gt(import_picocolors.default.red("Diagnosis failed."));
61
+ process.exit(1);
62
+ }
63
+ s.start("Verifying database connection...");
64
+ try {
65
+ if (!opaca.db)
66
+ throw new Error("No database configured in config.db");
67
+ const tables = await opaca.db.kysely.introspection.getTables();
68
+ s.stop(`Database connected successfully. Found ${import_picocolors.default.green(tables.length)} tables.`);
69
+ } catch (err) {
70
+ s.stop(import_picocolors.default.red("Database connection failed."));
71
+ R.error(err.message);
72
+ }
73
+ s.start("Checking dependencies...");
74
+ try {
75
+ const pkgPath = `${process.cwd()}/package.json`;
76
+ if (fs.existsSync(pkgPath)) {
77
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
78
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
79
+ if (!deps.opacacms) {
80
+ R.warn(import_picocolors.default.yellow("opacacms is missing from package.json"));
81
+ }
82
+ s.stop(`Dependencies checked.`);
83
+ } else {
84
+ s.stop(import_picocolors.default.yellow("package.json not found."));
85
+ }
86
+ } catch (err) {
87
+ s.stop(import_picocolors.default.red("Error checking dependencies."));
88
+ }
89
+ Vt(`Everything seems to be in order! Run \`opacacms dev\` to start.`, "Diagnosis Complete");
90
+ Gt("Doctor out.");
91
+ }
92
+ });
93
+ export {
94
+ doctor_default as default
95
+ };
@@ -0,0 +1,47 @@
1
+ // src/utils/string.ts
2
+ function sanitizeGraphQLName(name) {
3
+ return name.replace(/[^_a-zA-Z0-9]/g, "_");
4
+ }
5
+ function getRandomMigrationName() {
6
+ const adjectives = [
7
+ "vibrant",
8
+ "snarky",
9
+ "brave",
10
+ "swift",
11
+ "silent",
12
+ "funky",
13
+ "mystic",
14
+ "loyal",
15
+ "nimble",
16
+ "eager",
17
+ "wild",
18
+ "chill",
19
+ "golden",
20
+ "magic",
21
+ "smart",
22
+ "fierce"
23
+ ];
24
+ const nouns = [
25
+ "vulture",
26
+ "badger",
27
+ "falcon",
28
+ "otter",
29
+ "lynx",
30
+ "panda",
31
+ "fox",
32
+ "lemur",
33
+ "cobra",
34
+ "whale",
35
+ "eagle",
36
+ "tiger",
37
+ "koala",
38
+ "bison",
39
+ "raven",
40
+ "shark"
41
+ ];
42
+ const adj = adjectives[Math.floor(Math.random() * adjectives.length)];
43
+ const noun = nouns[Math.floor(Math.random() * nouns.length)];
44
+ return `${adj}_${noun}`;
45
+ }
46
+
47
+ export { sanitizeGraphQLName, getRandomMigrationName };
@@ -0,0 +1,263 @@
1
+ import {
2
+ require_picocolors
3
+ } from "./chunk-rwqwsanx.js";
4
+ import {
5
+ Ct,
6
+ Gt,
7
+ Nt,
8
+ R,
9
+ Wt,
10
+ Zt,
11
+ be
12
+ } from "./chunk-ec4jhybj.js";
13
+ import {
14
+ defineCommand
15
+ } from "./chunk-1qm0m8r8.js";
16
+ import {
17
+ logger
18
+ } from "./chunk-jq1drsen.js";
19
+ import {
20
+ __require,
21
+ __toESM
22
+ } from "./chunk-6bywt602.js";
23
+
24
+ // src/cli/commands/plugin.ts
25
+ var import_picocolors = __toESM(require_picocolors(), 1);
26
+
27
+ // src/cli/core/plugins/plugin-build.ts
28
+ import fs from "node:fs";
29
+ import path from "node:path";
30
+ async function pluginBuildCommand(projectRoot) {
31
+ const srcDir = path.resolve(projectRoot, "src");
32
+ const distDir = path.resolve(projectRoot, "dist");
33
+ if (!fs.existsSync(srcDir)) {
34
+ logger.error(`No 'src' directory found in ${projectRoot}.`);
35
+ process.exit(1);
36
+ }
37
+ const entryFiles = ["index.tsx", "index.ts", "plugin.tsx", "plugin.ts"];
38
+ let mainEntry = "";
39
+ for (const file of entryFiles) {
40
+ const fullPath = path.join(srcDir, file);
41
+ if (fs.existsSync(fullPath)) {
42
+ mainEntry = fullPath;
43
+ break;
44
+ }
45
+ }
46
+ if (!mainEntry) {
47
+ logger.error(`Could not find a main entry file in ${srcDir}`);
48
+ process.exit(1);
49
+ }
50
+ logger.info(`Building plugin entry: ${path.basename(mainEntry)}...`);
51
+ if (!fs.existsSync(distDir)) {
52
+ fs.mkdirSync(distDir, { recursive: true });
53
+ }
54
+ const buildResult = await Bun.build({
55
+ entrypoints: [mainEntry],
56
+ outdir: distDir,
57
+ target: "node",
58
+ format: "esm",
59
+ external: [
60
+ "opacacms",
61
+ "opacacms/types",
62
+ "opacacms/plugins",
63
+ "opacacms/schema",
64
+ "hono",
65
+ "zod",
66
+ "react",
67
+ "react-dom"
68
+ ]
69
+ });
70
+ if (!buildResult.success) {
71
+ logger.error("Plugin build failed.");
72
+ for (const msg of buildResult.logs) {
73
+ console.error(msg);
74
+ }
75
+ process.exit(1);
76
+ }
77
+ try {
78
+ logger.info("Generating type declarations...");
79
+ const { execSync } = await import("node:child_process");
80
+ execSync("bunx tsc --emitDeclarationOnly --outDir dist", {
81
+ cwd: projectRoot,
82
+ stdio: "ignore"
83
+ });
84
+ logger.success("Types generated.");
85
+ } catch (err) {
86
+ logger.warn("Failed to generate types. Make sure typescript is installed.");
87
+ }
88
+ logger.success(`Plugin built successfully in ${distDir}!`);
89
+ }
90
+
91
+ // src/cli/core/plugins/plugin-init.ts
92
+ import fs2 from "node:fs";
93
+ import path2 from "node:path";
94
+ async function pluginInitCommand(pluginName) {
95
+ if (!pluginName) {
96
+ logger.error("Please provide a plugin name. Usage: opacacms plugin:init <plugin_name>");
97
+ process.exit(1);
98
+ }
99
+ const targetDir = path2.resolve(process.cwd(), pluginName);
100
+ if (fs2.existsSync(targetDir)) {
101
+ logger.error(`Directory ${targetDir} already exists.`);
102
+ process.exit(1);
103
+ }
104
+ logger.info(`Initializing new plugin in ${targetDir}...`);
105
+ fs2.mkdirSync(targetDir, { recursive: true });
106
+ fs2.mkdirSync(path2.join(targetDir, "src"), { recursive: true });
107
+ const packageJson = {
108
+ name: pluginName,
109
+ version: "1.0.0",
110
+ description: "An OpacaCMS plugin",
111
+ main: "dist/index.js",
112
+ types: "dist/index.d.ts",
113
+ scripts: {
114
+ build: "opacacms plugin:build",
115
+ dev: "bun run build --watch"
116
+ },
117
+ peerDependencies: {
118
+ opacacms: "workspace:*"
119
+ },
120
+ devDependencies: {
121
+ typescript: "^5.0.0",
122
+ "@types/node": "^20.0.0"
123
+ }
124
+ };
125
+ fs2.writeFileSync(path2.join(targetDir, "package.json"), JSON.stringify(packageJson, null, 2), "utf-8");
126
+ const tsconfig = {
127
+ compilerOptions: {
128
+ target: "ESNext",
129
+ module: "ESNext",
130
+ moduleResolution: "bundler",
131
+ strict: true,
132
+ esModuleInterop: true,
133
+ skipLibCheck: true,
134
+ forceConsistentCasingInFileNames: true,
135
+ outDir: "./dist",
136
+ declaration: true,
137
+ jsx: "react"
138
+ },
139
+ include: ["src/**/*"]
140
+ };
141
+ fs2.writeFileSync(path2.join(targetDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2), "utf-8");
142
+ const indexTsx = `import type { OpacaPlugin, OpacaPluginContext } from 'opacacms/types';
143
+ import { definePlugin } from 'opacacms/plugins';
144
+
145
+ export const myPlugin = (): OpacaPlugin => definePlugin({
146
+ name: '${pluginName}',
147
+ label: 'My Custom Plugin',
148
+ description: 'A great new plugin for OpacaCMS.',
149
+ version: '1.0.0',
150
+ icon: 'Box',
151
+
152
+ onInit: (ctx: OpacaPluginContext) => {
153
+ ctx.logger.info('[${pluginName}] Plugin initialized!');
154
+ },
155
+
156
+ onRouterInit: (app) => {
157
+ app.get('/admin/plugins/${pluginName}/view', (c) => {
158
+ return c.html(\`
159
+ <!DOCTYPE html>
160
+ <html>
161
+ <head>
162
+ <meta charset="UTF-8">
163
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
164
+ <style>
165
+ body {
166
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
167
+ padding: 2rem;
168
+ line-height: 1.5;
169
+ color: #334155;
170
+ }
171
+ .card {
172
+ background: white;
173
+ border: 1px solid #e2e8f0;
174
+ border-radius: 0.5rem;
175
+ padding: 1.5rem;
176
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
177
+ }
178
+ h2 { margin-top: 0; color: #1e293b; }
179
+ </style>
180
+ </head>
181
+ <body>
182
+ <div class="card">
183
+ <h2>Welcome to ${pluginName} Dashboard!</h2>
184
+ <p>This UI is rendered directly from your plugin's backend using <strong>SSR</strong>.</p>
185
+ <p>You can use Hono's <code>c.html()</code> or even React SSR with <code>@hono/react-renderer</code>.</p>
186
+ </div>
187
+ </body>
188
+ </html>
189
+ \`);
190
+ });
191
+ },
192
+
193
+ adminUI: {
194
+ type: 'ssr',
195
+ path: '/admin/plugins/${pluginName}/view',
196
+ }
197
+ });
198
+ `;
199
+ fs2.writeFileSync(path2.join(targetDir, "src", "index.tsx"), indexTsx, "utf-8");
200
+ logger.success(`Plugin ${pluginName} initialized successfully!`);
201
+ logger.info(`Next steps:
202
+ cd ${pluginName}
203
+ bun install
204
+ bun run build`);
205
+ }
206
+
207
+ // src/cli/commands/plugin.ts
208
+ var plugin_default = defineCommand({
209
+ meta: {
210
+ name: "plugin",
211
+ description: "Manage OpacaCMS plugins"
212
+ },
213
+ args: {
214
+ action: {
215
+ type: "positional",
216
+ description: "Action to perform: init, build",
217
+ required: true
218
+ },
219
+ name: {
220
+ type: "positional",
221
+ description: "Name of the plugin (for init)",
222
+ required: false
223
+ }
224
+ },
225
+ async run({ args }) {
226
+ if (args.action === "init") {
227
+ let name = args.name;
228
+ if (!name) {
229
+ const response = await Zt({
230
+ message: "What is the name of your plugin?",
231
+ placeholder: "my-opaca-plugin",
232
+ defaultValue: "my-opaca-plugin"
233
+ });
234
+ if (Ct(response)) {
235
+ Nt("Operation cancelled.");
236
+ process.exit(0);
237
+ }
238
+ name = response;
239
+ }
240
+ Wt(import_picocolors.default.bgBlue(import_picocolors.default.white(" OpacaCMS Plugin Init ")));
241
+ const s = be();
242
+ s.start(`Scaffolding plugin ${name}...`);
243
+ await pluginInitCommand(name);
244
+ s.stop(`Plugin ${name} scaffolded!`);
245
+ Gt(`Run cd ${name} && bun install to get started.`);
246
+ return;
247
+ }
248
+ if (args.action === "build") {
249
+ Wt(import_picocolors.default.bgMagenta(import_picocolors.default.white(" OpacaCMS Plugin Build ")));
250
+ const s = be();
251
+ s.start(`Building plugin in ${process.cwd()}...`);
252
+ await pluginBuildCommand(process.cwd());
253
+ s.stop(`Plugin built successfully!`);
254
+ Gt(`Ready for distribution.`);
255
+ return;
256
+ }
257
+ R.error(`Unknown plugin action: ${args.action}`);
258
+ process.exit(1);
259
+ }
260
+ });
261
+ export {
262
+ plugin_default as default
263
+ };
@@ -1,4 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
2
4
  var __defProp = Object.defineProperty;
3
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
6
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -6,6 +8,28 @@ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  function __accessProp(key) {
7
9
  return this[key];
8
10
  }
11
+ var __toESMCache_node;
12
+ var __toESMCache_esm;
13
+ var __toESM = (mod, isNodeMode, target) => {
14
+ var canCache = mod != null && typeof mod === "object";
15
+ if (canCache) {
16
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
17
+ var cached = cache.get(mod);
18
+ if (cached)
19
+ return cached;
20
+ }
21
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
22
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
23
+ for (let key of __getOwnPropNames(mod))
24
+ if (!__hasOwnProp.call(to, key))
25
+ __defProp(to, key, {
26
+ get: __accessProp.bind(mod, key),
27
+ enumerable: true
28
+ });
29
+ if (canCache)
30
+ cache.set(mod, to);
31
+ return to;
32
+ };
9
33
  var __toCommonJS = (from) => {
10
34
  var entry = (__moduleCache ??= new WeakMap).get(from), desc;
11
35
  if (entry)
@@ -23,6 +47,7 @@ var __toCommonJS = (from) => {
23
47
  return entry;
24
48
  };
25
49
  var __moduleCache;
50
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
26
51
  var __returnValue = (v) => v;
27
52
  function __exportSetter(name, newValue) {
28
53
  this[name] = __returnValue.bind(null, newValue);
@@ -39,4 +64,4 @@ var __export = (target, all) => {
39
64
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
40
65
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
41
66
 
42
- export { __toCommonJS, __export, __esm, __require };
67
+ export { __toESM, __toCommonJS, __commonJS, __export, __esm, __require };