@brightsideoy/kama 1.0.0-alpha.2 → 1.0.0-alpha.20

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 (125) hide show
  1. package/bin/cli.js +604 -364
  2. package/content/definitions/block-kama-forms.yaml +5 -0
  3. package/content/definitions/blocks/button.yaml +15 -5
  4. package/content/definitions/blocks/node-list.yaml +75 -0
  5. package/content/definitions/field-sets/channel-base.yaml +7 -0
  6. package/content/definitions/nodes/article.yaml +17 -1
  7. package/content/definitions/taxonomies/categories.yaml +5 -2
  8. package/content/definitions/taxonomies/tags.yaml +5 -2
  9. package/content/forms/contact.yaml +44 -0
  10. package/content/forms/subscription.yaml +32 -0
  11. package/dist/assets/AssetEditor-D5j7pwcK.css +1 -0
  12. package/dist/assets/AssetEditor-Dt1zCR7_.js +1 -0
  13. package/dist/assets/CmsBadge-BNsgxyyB.css +1 -0
  14. package/dist/assets/CmsBadge-D0Ob9qPU.js +1 -0
  15. package/dist/assets/CmsButton-BQ85-YXn.css +1 -0
  16. package/dist/assets/CmsButton-CbOfxvjr.js +1 -0
  17. package/dist/assets/CmsDataRow--H4iI_u_.js +1 -0
  18. package/dist/assets/CmsDataRow-CYNxfVaZ.css +1 -0
  19. package/dist/assets/CmsHelp-BO_vWABq.css +1 -0
  20. package/dist/assets/CmsHelp-DyPJLGGi.js +1 -0
  21. package/dist/assets/CmsImagePreview-CujwG8r_.css +1 -0
  22. package/dist/assets/CmsImagePreview-DuHPBzml.js +1 -0
  23. package/dist/assets/CmsPaneResizer-B62ZqsnE.js +1 -0
  24. package/dist/assets/CmsPaneResizer-Dkidd4pI.css +1 -0
  25. package/dist/assets/CmsPublisher-CugEqTD8.css +1 -0
  26. package/dist/assets/CmsPublisher-DNLwjirk.js +3 -0
  27. package/dist/assets/CmsUserCenter-Ac0GywlR.css +1 -0
  28. package/dist/assets/CmsUserCenter-D3XDzKDC.js +1 -0
  29. package/dist/assets/EditorSplitPreview-BzKh4wFB.css +1 -0
  30. package/dist/assets/EditorSplitPreview-Cp2x0O_P.js +1 -0
  31. package/dist/assets/NodeContextMenu-BYeWzmQ5.css +1 -0
  32. package/dist/assets/NodeContextMenu-C_HWBGeb.js +1 -0
  33. package/dist/assets/NodeEditor-CiXQKXK1.js +147 -0
  34. package/dist/assets/NodeEditor-pZI3gu4a.css +1 -0
  35. package/dist/assets/StatusPill-CbeW5SMT.js +1 -0
  36. package/dist/assets/StatusPill-Dlm6uvGe.css +1 -0
  37. package/dist/assets/TrashWorkspace-DgIg1v6t.js +1 -0
  38. package/dist/assets/TrashWorkspace-DtMgxg13.css +1 -0
  39. package/dist/assets/_plugin-vue_export-helper-CQxWhVtr.js +5 -0
  40. package/dist/assets/circle-check-A-QeFqt3.js +1 -0
  41. package/dist/assets/database-hg5SqKLG.js +1 -0
  42. package/dist/assets/folder-tree-BWYot72H.js +1 -0
  43. package/dist/assets/globe-BraoljaN.js +1 -0
  44. package/dist/assets/history-pqIbKK9u.js +1 -0
  45. package/dist/assets/index-DQ6_RmCI.js +14 -0
  46. package/dist/assets/index-DcKiaRjI.css +1 -0
  47. package/dist/assets/layers-B6RgfpPR.js +1 -0
  48. package/dist/assets/loader-circle-BoUkhDjq.js +1 -0
  49. package/dist/assets/monitor-CrpvInqG.js +1 -0
  50. package/dist/assets/panel-left-close-CVFakVaA.js +1 -0
  51. package/dist/assets/plus-FQRsZBoJ.js +1 -0
  52. package/dist/assets/rotate-ccw-CWE4pOjs.js +1 -0
  53. package/dist/assets/save-Ctv8vW9H.js +1 -0
  54. package/dist/assets/schema-helpers-DvficKko.js +1 -0
  55. package/dist/assets/send-F-mJeL54.js +1 -0
  56. package/dist/assets/smartphone-EPce6VdP.js +1 -0
  57. package/dist/assets/trash-2-CAUF1KtI.js +1 -0
  58. package/dist/assets/useLocalStorage-C805uplI.js +1 -0
  59. package/dist/assets/useNodes-D2-VxsxR.js +1 -0
  60. package/dist/assets/user-IFlT6mYq.js +1 -0
  61. package/dist/build-seed.js +495 -0
  62. package/dist/{dist-Dy7-HUEG.js → dist-D_Q1y4Kh.js} +2314 -1180
  63. package/dist/index.html +34 -2
  64. package/dist/index.js +2298 -1158
  65. package/dist/schema-compiler.js +5 -5
  66. package/documentation/EXTENSIONS.md +204 -0
  67. package/extension-registry.js +5 -0
  68. package/package.json +9 -2
  69. package/schema.sql +34 -1
  70. package/templates/astro-starter/old_src/components/blocks/BlockRenderer.astro +143 -0
  71. package/templates/astro-starter/old_src/components/blocks/ColumnLayout.astro +67 -0
  72. package/templates/astro-starter/old_src/components/blocks/HeaderImage.astro +126 -0
  73. package/templates/astro-starter/old_src/components/blocks/Hero.astro +218 -0
  74. package/templates/astro-starter/old_src/components/blocks/HtmlBlock.astro +25 -0
  75. package/templates/astro-starter/old_src/components/blocks/ImageBlock.astro +91 -0
  76. package/templates/astro-starter/old_src/components/blocks/NodeList.astro +274 -0
  77. package/templates/astro-starter/old_src/components/blocks/TextBlock.astro +15 -0
  78. package/templates/astro-starter/old_src/components/global/Breadcrumb.astro +108 -0
  79. package/templates/astro-starter/old_src/components/global/Footer.astro +50 -0
  80. package/templates/astro-starter/old_src/components/global/Header.astro +171 -0
  81. package/templates/astro-starter/old_src/components/global/MetaHead.astro +266 -0
  82. package/templates/astro-starter/old_src/components/global/NavigationMenu.astro +413 -0
  83. package/templates/astro-starter/old_src/components/ui/KamaImage.astro +180 -0
  84. package/templates/astro-starter/old_src/layouts/SkeletonLayout.astro +56 -0
  85. package/templates/astro-starter/old_src/layouts/StandardLayout.astro +63 -0
  86. package/templates/astro-starter/old_src/lib/cms.ts +219 -0
  87. package/templates/astro-starter/old_src/lib/media/kama-image-service.ts +67 -0
  88. package/templates/astro-starter/old_src/lib/media/media-proxy.ts +148 -0
  89. package/templates/astro-starter/old_src/lib/media/media-url.ts +112 -0
  90. package/templates/astro-starter/old_src/middleware.ts +536 -0
  91. package/templates/astro-starter/old_src/pages/404.astro +46 -0
  92. package/templates/astro-starter/old_src/pages/[...slug].astro +311 -0
  93. package/templates/astro-starter/old_src/pages/api/load-nodes.ts +68 -0
  94. package/templates/astro-starter/old_src/pages/api/partials/node-cards.astro +101 -0
  95. package/templates/astro-starter/old_src/pages/llms-full.txt.ts +171 -0
  96. package/templates/astro-starter/old_src/pages/llms.txt.ts +113 -0
  97. package/templates/astro-starter/old_src/pages/media/[...path].ts +14 -0
  98. package/templates/astro-starter/old_src/pages/partials/footer.astro +69 -0
  99. package/templates/astro-starter/old_src/pages/partials/nav.astro +141 -0
  100. package/templates/astro-starter/old_src/styles/standard-theme.css +157 -0
  101. package/templates/astro-starter/old_src/utils/tiptap.ts +113 -0
  102. package/templates/astro-starter/src/components/blocks/BlockRenderer.astro +9 -0
  103. package/templates/astro-starter/src/components/blocks/Form.astro +143 -0
  104. package/templates/astro-starter/src/components/blocks/HeaderImage.astro +6 -12
  105. package/templates/astro-starter/src/components/blocks/ImageBlock.astro +5 -6
  106. package/templates/astro-starter/src/components/blocks/NodeList.astro +274 -0
  107. package/templates/astro-starter/src/components/global/Breadcrumb.astro +50 -9
  108. package/templates/astro-starter/src/components/global/Footer.astro +7 -46
  109. package/templates/astro-starter/src/components/global/Header.astro +10 -16
  110. package/templates/astro-starter/src/components/global/NavigationMenu.astro +57 -46
  111. package/templates/astro-starter/src/components/ui/KamaImage.astro +13 -5
  112. package/templates/astro-starter/src/layouts/StandardLayout.astro +4 -3
  113. package/templates/astro-starter/src/lib/cms.ts +33 -11
  114. package/templates/astro-starter/src/lib/media/kama-image-service.ts +15 -4
  115. package/templates/astro-starter/src/lib/media/media-proxy.ts +22 -3
  116. package/templates/astro-starter/src/lib/media/media-url.ts +17 -3
  117. package/templates/astro-starter/src/middleware.ts +158 -100
  118. package/templates/astro-starter/src/pages/[...slug].astro +77 -3
  119. package/templates/astro-starter/src/pages/api/load-nodes.ts +68 -0
  120. package/templates/astro-starter/src/pages/api/partials/node-cards.astro +101 -0
  121. package/templates/kama-worker/index.js +38 -15
  122. package/templates/kama-worker/server.js +13 -5
  123. package/templates/kama-worker/setup-local-db.mjs +17 -0
  124. package/dist/assets/index-F2rfUymo.css +0 -1
  125. package/dist/assets/index-lXxH3VFK.js +0 -164
@@ -0,0 +1,101 @@
1
+ ---
2
+ // src/pages/api/partials/node-cards.astro
3
+ export const partial = true; // Tells Astro not to inject DOCTYPE or <head> tags
4
+
5
+ import KamaImage from "@/components/ui/KamaImage.astro";
6
+
7
+ const { request, locals } = Astro;
8
+ const url = new URL(request.url);
9
+ const searchParams = url.searchParams;
10
+
11
+ // 1. Get Environment Variables securely via middleware
12
+ const cfEnv = (locals as any).safeEnv || {};
13
+ const cmsWorker = cfEnv.CMS_WORKER;
14
+ const apiUrl =
15
+ cfEnv.PUBLIC_API_URL ||
16
+ import.meta.env.PUBLIC_API_URL ||
17
+ "http://localhost:8787";
18
+ const secret = cfEnv.FRONTEND_API_SECRET || import.meta.env.FRONTEND_API_SECRET;
19
+
20
+ // 2. Construct the actual backend URL
21
+ const cleanApiUrl = apiUrl.replace(/\/$/, "");
22
+ const backendUrl = `${cleanApiUrl}/api/v1/nodes?${searchParams.toString()}`;
23
+
24
+ // 3. Prepare the secure headers
25
+ const reqHeaders: Record<string, string> = { Accept: "application/json" };
26
+ if (secret) reqHeaders["Authorization"] = `Bearer ${secret}`;
27
+
28
+ const backendReq = new Request(backendUrl, {
29
+ method: "GET",
30
+ headers: reqHeaders,
31
+ });
32
+
33
+ // 4. Fetch securely using Service Binding
34
+ let response;
35
+ if (cmsWorker && typeof cmsWorker.fetch === "function") {
36
+ response = await cmsWorker.fetch(backendReq);
37
+ } else {
38
+ response = await fetch(backendReq);
39
+ }
40
+
41
+ let itemsArray: any[] = [];
42
+ let limit = 12;
43
+ let consumedRows = 0;
44
+
45
+ if (response.ok) {
46
+ const data = await response.json();
47
+ itemsArray = Array.isArray(data)
48
+ ? data
49
+ : data.items || data.nodes || data.data || [];
50
+ limit = data.limit || 12;
51
+ consumedRows =
52
+ data.rawCount !== undefined ? data.rawCount : itemsArray.length;
53
+ }
54
+
55
+ // 5. Send pagination data back to the frontend script via custom HTTP Headers
56
+ Astro.response.headers.set("X-Consumed-Rows", consumedRows.toString());
57
+ Astro.response.headers.set("X-Limit", limit.toString());
58
+ Astro.response.headers.set(
59
+ "Cache-Control",
60
+ "public, max-age=0, s-maxage=60, stale-while-revalidate=120",
61
+ );
62
+ ---
63
+
64
+ {
65
+ itemsArray.map((item: any) => {
66
+ const dateStr = item.createdAt
67
+ ? new Date(item.createdAt).toLocaleDateString("en-GB", {
68
+ day: "numeric",
69
+ month: "short",
70
+ year: "numeric",
71
+ })
72
+ : "";
73
+
74
+ return (
75
+ <article class="node-card">
76
+ <a href={`/${item.slug}`} class="node-card-link">
77
+ {item.image ? (
78
+ <KamaImage
79
+ image={item.image}
80
+ sizes="(max-width: 639px) 100vw, (max-width: 1023px) 50vw, 33vw"
81
+ desktopWidths={[320, 640, 768, 1024]}
82
+ idealWidth={429}
83
+ loading="lazy"
84
+ />
85
+ ) : (
86
+ <div class="image-placeholder" />
87
+ )}
88
+ <div class="node-card-content">
89
+ <h3 class="node-card-title">{item.title}</h3>
90
+ {dateStr && (
91
+ <time datetime={item.createdAt} class="node-card-date">
92
+ {dateStr}
93
+ </time>
94
+ )}
95
+ {item.excerpt && <p class="node-card-excerpt">{item.excerpt}</p>}
96
+ </div>
97
+ </a>
98
+ </article>
99
+ );
100
+ })
101
+ }
@@ -1,19 +1,42 @@
1
+ // templates/kama-worker/index.js
2
+ import { Hono } from 'hono';
1
3
  import kamaWorker from '@brightsideoy/kama';
2
4
  import * as localBundle from './bundled-definitions.js';
5
+ import { activeExtensions } from './extension-registry.js';
3
6
 
4
- export default {
5
- async fetch(request, env, ctx) {
6
- const schemas = localBundle.BUNDLED_DEFINITIONS || localBundle.default || localBundle;
7
- const customEnv = { ...env, BUNDLED_DEFINITIONS: schemas, KAMA_RUNTIME: 'cloudflare' };
8
-
9
- if (kamaWorker && typeof kamaWorker.fetch === 'function') {
10
- return kamaWorker.fetch(request, customEnv, ctx);
11
- }
12
-
13
- if (kamaWorker && kamaWorker.app && typeof kamaWorker.app.fetch === 'function') {
14
- return kamaWorker.app.fetch(request, customEnv, ctx);
15
- }
16
-
17
- return new Response('Kama Engine Worker Ready', { status: 200 });
7
+ const app = new Hono();
8
+
9
+ // 1. 🎯 Mount Extension Routes Natively
10
+ for (const ext of activeExtensions) {
11
+ if (ext.routes?.public) {
12
+ app.route(`/api/v1/ext/${ext.id}`, ext.routes.public);
13
+ }
14
+ if (ext.routes?.admin) {
15
+ app.route(`/api/admin/ext/${ext.id}`, ext.routes.admin);
16
+ }
17
+ }
18
+
19
+ // 2. 🎯 Mount Precompiled Core CMS (Fallback catch-all)
20
+ app.all('*', async (c) => {
21
+ const schemas = localBundle.BUNDLED_DEFINITIONS || localBundle.default || localBundle;
22
+
23
+ // Inject the extensions array so the UI and core can read it (e.g. for dynamic menus)
24
+ const customEnv = {
25
+ ...c.env,
26
+ BUNDLED_DEFINITIONS: schemas,
27
+ KAMA_EXTENSIONS: activeExtensions,
28
+ KAMA_RUNTIME: 'cloudflare'
29
+ };
30
+
31
+ if (kamaWorker && typeof kamaWorker.fetch === 'function') {
32
+ return kamaWorker.fetch(c.req.raw, customEnv, c.executionCtx);
33
+ }
34
+
35
+ if (kamaWorker && kamaWorker.app && typeof kamaWorker.app.fetch === 'function') {
36
+ return kamaWorker.app.fetch(c.req.raw, customEnv, c.executionCtx);
18
37
  }
19
- };
38
+
39
+ return new Response('KAMA • ENGINE Ready', { status: 200 });
40
+ });
41
+
42
+ export default app;
@@ -3,6 +3,7 @@ import { serveStatic } from '@hono/node-server/serve-static';
3
3
  import { Hono } from 'hono';
4
4
  import kamaApp from '@brightsideoy/kama';
5
5
  import * as localBundle from './bundled-definitions.js';
6
+ import { activeExtensions } from './extension-registry.js'; // 🎯 1. Import the auto-generated registry
6
7
  import dotenv from 'dotenv';
7
8
  import { readFileSync, existsSync, statSync } from 'node:fs';
8
9
  import { join } from 'node:path';
@@ -18,7 +19,7 @@ const possiblePaths = [
18
19
  const distPath = possiblePaths.find(p => existsSync(p));
19
20
 
20
21
  if (!distPath) {
21
- console.warn('⚠️ Could not locate @brightsideoy/kama/dist folder. Admin UI will not load.');
22
+ console.warn('\x1b[33m ⚠\x1b[0m \x1b[2mCould not locate @brightsideoy/kama/dist folder. Admin UI will not load.\x1b[0m');
22
23
  }
23
24
 
24
25
  const app = new Hono();
@@ -32,7 +33,9 @@ async function getCustomEnv(c) {
32
33
  if (existsSync(bundlePath)) {
33
34
  const mtime = statSync(bundlePath).mtimeMs;
34
35
  if (mtime > lastModified) {
35
- if (lastModified !== 0) console.log('🔄 Hot-reloading fresh schema definitions!');
36
+ if (lastModified !== 0) {
37
+ console.log('\x1b[36m ⟳\x1b[0m \x1b[2mHot-reloading schema definitions\x1b[0m');
38
+ }
36
39
  const mod = await import(`${pathToFileURL(bundlePath).href}?t=${mtime}`);
37
40
  cachedSchemas = mod.BUNDLED_DEFINITIONS || mod.default || mod;
38
41
  lastModified = mtime;
@@ -44,6 +47,7 @@ async function getCustomEnv(c) {
44
47
  ...process.env,
45
48
  ...(c.env || {}),
46
49
  BUNDLED_DEFINITIONS: cachedSchemas,
50
+ KAMA_EXTENSIONS: activeExtensions, // 🎯 2. Pass extensions dynamically into the Core
47
51
  KAMA_RUNTIME: (c.env && c.env.DB) ? 'cloudflare' : 'node'
48
52
  };
49
53
  }
@@ -91,8 +95,12 @@ export default app;
91
95
  if (typeof process !== 'undefined' && process.argv && process.argv[1] && process.argv[1].endsWith('server.js')) {
92
96
  const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 8787;
93
97
  serve({ fetch: app.fetch, port }, (info) => {
94
- console.log(`\n🔥 KAMA CMS Node Server is running!`);
95
- console.log(`┃ Local http://localhost:${info.port}/`);
96
- if (distPath) console.log(`┃ Admin UI Serving from: ${distPath}\n`);
98
+ console.log(`\n \x1b[36m\x1b[1mKAMA • ENGINE\x1b[0m`);
99
+ console.log(` \x1b[2m│\x1b[0m`);
100
+ console.log(` \x1b[2m│\x1b[0m Local \x1b[32mhttp://localhost:${info.port}/\x1b[0m`);
101
+ if (distPath) {
102
+ console.log(` \x1b[2m│\x1b[0m Admin UI \x1b[2mServing from local dist\x1b[0m`);
103
+ }
104
+ console.log(` \x1b[2m│\x1b[0m\n`);
97
105
  });
98
106
  }
@@ -0,0 +1,17 @@
1
+ import { readdir, readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { createClient } from '@libsql/client';
4
+
5
+ const mode = process.argv[2] || 'schema';
6
+ const databasePath = process.env.DB_PATH || './kama.db';
7
+ const client = createClient({ url: `file:${databasePath}` });
8
+
9
+ try {
10
+ const files = mode === 'seed'
11
+ ? (await readdir('.')).filter(file => /^seed.*\.sql$/.test(file)).sort()
12
+ : ['../node_modules/@brightsideoy/kama/schema.sql'];
13
+ if (files.length === 0) throw new Error('No generated seed SQL files found.');
14
+ for (const file of files) await client.executeMultiple(await readFile(join(process.cwd(), file), 'utf8'));
15
+ } finally {
16
+ await client.close();
17
+ }