@brightsideoy/kama 0.1.0-alpha.37 → 0.1.0-alpha.40
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/bin/cli.js +16 -8
- package/defaults/definitions/block-layouts/three-column.yaml +20 -0
- package/defaults/definitions/block-layouts/two-column.yaml +29 -0
- package/defaults/definitions/blocks/header.yaml +15 -0
- package/defaults/definitions/blocks/header_image.yaml +22 -0
- package/defaults/definitions/blocks/hero.yaml +27 -0
- package/defaults/definitions/blocks/image_card.yaml +53 -0
- package/defaults/definitions/blocks/text.yaml +16 -0
- package/defaults/definitions/channels/ecommerce.yaml +24 -0
- package/defaults/definitions/channels/website.yaml +32 -0
- package/defaults/definitions/field-sets/access.yaml +29 -0
- package/defaults/definitions/field-sets/channel-base.yaml +31 -0
- package/defaults/definitions/field-sets/comments.yaml +11 -0
- package/defaults/definitions/field-sets/content-block.yaml +46 -0
- package/defaults/definitions/field-sets/page-base.yaml +49 -0
- package/defaults/definitions/field-sets/page-meta.yaml +15 -0
- package/defaults/definitions/field-sets/page-social.yaml +80 -0
- package/defaults/definitions/field-sets/tree-base.yaml +31 -0
- package/defaults/definitions/field-sets/visibility.yaml +8 -0
- package/defaults/definitions/node-layouts/landing-page.yml +22 -0
- package/defaults/definitions/node-layouts/single-column.yml +38 -0
- package/defaults/definitions/node-layouts/three-column.yml +41 -0
- package/defaults/definitions/node-layouts/two-column.yml +40 -0
- package/defaults/definitions/nodes/address.yaml +32 -0
- package/defaults/definitions/nodes/article.yaml +41 -0
- package/defaults/definitions/nodes/event.yaml +40 -0
- package/defaults/definitions/nodes/external-link.yaml +26 -0
- package/defaults/definitions/nodes/page.yaml +63 -0
- package/defaults/definitions/nodes/person.yaml +35 -0
- package/defaults/definitions/nodes/product.yaml +79 -0
- package/defaults/definitions/trees/navigation.yaml +29 -0
- package/defaults/definitions/trees/social-links.yaml +9 -0
- package/definitions/_page.yaml +52 -0
- package/definitions/editor/default.ts +17 -0
- package/definitions/editor/header.ts +33 -0
- package/definitions/editor/minimal.ts +13 -0
- package/definitions/validators/iban.ts +12 -0
- package/definitions/validators/magic-word.ts +7 -0
- package/package.json +4 -1
- package/scripts/bundle-definitions.js +176 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// scripts/bundle-definitions.js
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import YAML from 'yaml';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
|
|
10
|
+
// 🎯 Package root is one directory up from scripts/
|
|
11
|
+
const packageRootDir = path.resolve(__dirname, '..');
|
|
12
|
+
|
|
13
|
+
// Look for definitions across package core AND consumer project overrides
|
|
14
|
+
function getDefinitionFiles(subDir) {
|
|
15
|
+
const fileMap = new Map();
|
|
16
|
+
|
|
17
|
+
const possibleDirs = [
|
|
18
|
+
// 1. Core package defaults (from inside node_modules or package source)
|
|
19
|
+
path.resolve(packageRootDir, "defaults/definitions", subDir),
|
|
20
|
+
path.resolve(packageRootDir, "definitions", subDir),
|
|
21
|
+
|
|
22
|
+
// 2. Fallbacks relative to node_modules if running from workspace root
|
|
23
|
+
path.resolve(process.cwd(), "node_modules/@brightsideoy/kama/defaults/definitions", subDir),
|
|
24
|
+
path.resolve(process.cwd(), "node_modules/@brightsideoy/kama/definitions", subDir),
|
|
25
|
+
|
|
26
|
+
// 3. Consumer project local overrides (highest priority — overwrites defaults)
|
|
27
|
+
path.resolve(process.cwd(), "defaults/definitions", subDir),
|
|
28
|
+
path.resolve(process.cwd(), "definitions", subDir),
|
|
29
|
+
path.resolve(process.cwd(), "schemas", subDir),
|
|
30
|
+
path.resolve(process.cwd(), "server/schemas", subDir),
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
for (const dirPath of possibleDirs) {
|
|
34
|
+
if (!fs.existsSync(dirPath)) continue;
|
|
35
|
+
|
|
36
|
+
const walkDir = (currentDir, relativePath = "") => {
|
|
37
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
const entryRelPath = path.join(relativePath, entry.name);
|
|
40
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
41
|
+
|
|
42
|
+
if (entry.isDirectory()) {
|
|
43
|
+
walkDir(fullPath, entryRelPath);
|
|
44
|
+
} else if (
|
|
45
|
+
entry.name.endsWith(".yaml") ||
|
|
46
|
+
entry.name.endsWith(".yml") ||
|
|
47
|
+
entry.name.endsWith(".json")
|
|
48
|
+
) {
|
|
49
|
+
// Overwrite earlier entries so local consumer files override package defaults
|
|
50
|
+
fileMap.set(entryRelPath, fullPath);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
walkDir(dirPath);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return Array.from(fileMap.entries()).map(([fileName, filePath]) => ({ fileName, filePath }));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function parseFile(filePath) {
|
|
62
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
63
|
+
return filePath.endsWith('.json') ? JSON.parse(content) : YAML.parse(content);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function loadDir(...subDirs) {
|
|
67
|
+
const res = {};
|
|
68
|
+
for (const subDir of subDirs) {
|
|
69
|
+
const files = getDefinitionFiles(subDir);
|
|
70
|
+
for (const { fileName, filePath } of files) {
|
|
71
|
+
const key = path.basename(fileName, path.extname(fileName));
|
|
72
|
+
try {
|
|
73
|
+
res[key] = parseFile(filePath);
|
|
74
|
+
} catch (e) {
|
|
75
|
+
console.warn(`Failed to parse ${filePath}:`, e);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return res;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function loadSingle(subDirAndFile) {
|
|
83
|
+
const files = getDefinitionFiles(path.dirname(subDirAndFile));
|
|
84
|
+
const targetBase = path.basename(subDirAndFile);
|
|
85
|
+
const matched = files.find(
|
|
86
|
+
f => path.basename(f.fileName) === targetBase ||
|
|
87
|
+
path.basename(f.fileName) === targetBase.replace(/\.yaml$/, '.yml') ||
|
|
88
|
+
path.basename(f.fileName) === targetBase.replace(/\.yaml$/, '.json')
|
|
89
|
+
);
|
|
90
|
+
if (!matched) return null;
|
|
91
|
+
try {
|
|
92
|
+
return parseFile(matched.filePath);
|
|
93
|
+
} catch (e) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 🎯 MAP DEFINITIONS
|
|
99
|
+
const rawBlocks = loadDir("blocks", "elements");
|
|
100
|
+
const rawBlockLayouts = loadDir("block-layouts");
|
|
101
|
+
const rawNodeLayouts = loadDir("node-layouts", "layouts");
|
|
102
|
+
|
|
103
|
+
const bundled = {
|
|
104
|
+
rawNodes: loadDir("nodes"),
|
|
105
|
+
rawTrees: loadDir("trees"),
|
|
106
|
+
rawChannels: loadDir("channels"),
|
|
107
|
+
rawBlocks,
|
|
108
|
+
rawElements: rawBlocks,
|
|
109
|
+
rawBlockLayouts,
|
|
110
|
+
rawNodeLayouts,
|
|
111
|
+
rawLayouts: { ...rawNodeLayouts, ...rawBlockLayouts },
|
|
112
|
+
rawFieldSets: loadDir("field-sets"),
|
|
113
|
+
rawTemplates: loadDir("templates"),
|
|
114
|
+
nodeTemplate: loadSingle("templates/node.yaml") || { fields: {} },
|
|
115
|
+
treeTemplate: loadSingle("templates/tree.yaml") || { fields: {} },
|
|
116
|
+
channelTemplate: loadSingle("channels/channel.yaml") || loadSingle("templates/channel.yaml") || { fields: {} },
|
|
117
|
+
userTemplate: loadSingle("users/user.yaml") || loadSingle("templates/user.yaml") || { fields: {} },
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const outputContent = `// Auto-generated pre-bundled definitions for Kama Core Engine
|
|
121
|
+
export const BUNDLED_DEFINITIONS = ${JSON.stringify(bundled, null, 2)};
|
|
122
|
+
`;
|
|
123
|
+
|
|
124
|
+
// 🎯 Write to BOTH package dist/server locations so imports resolve cleanly
|
|
125
|
+
const targetDirs = [
|
|
126
|
+
path.resolve(packageRootDir, 'server/db'),
|
|
127
|
+
path.resolve(process.cwd(), 'node_modules/@brightsideoy/kama/server/db'),
|
|
128
|
+
path.resolve(process.cwd(), 'node_modules/@brightsideoy/kama/dist'),
|
|
129
|
+
path.resolve(process.cwd(), 'server/db'),
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
for (const dir of targetDirs) {
|
|
133
|
+
if (fs.existsSync(dir)) {
|
|
134
|
+
const outputPath = path.resolve(dir, 'bundled-definitions.ts');
|
|
135
|
+
fs.writeFileSync(outputPath, outputContent, 'utf-8');
|
|
136
|
+
// Also write .js version for built packages
|
|
137
|
+
const jsOutputPath = path.resolve(dir, 'bundled-definitions.js');
|
|
138
|
+
fs.writeFileSync(jsOutputPath, `export const BUNDLED_DEFINITIONS = ${JSON.stringify(bundled, null, 2)};\n`, 'utf-8');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
console.log(`✅ Definitions bundled successfully:
|
|
143
|
+
• Nodes: ${Object.keys(bundled.rawNodes).length} (${Object.keys(bundled.rawNodes).join(', ')})
|
|
144
|
+
• Blocks: ${Object.keys(bundled.rawBlocks).length} (${Object.keys(bundled.rawBlocks).join(', ')})
|
|
145
|
+
• Channels: ${Object.keys(bundled.rawChannels).length} (${Object.keys(bundled.rawChannels).join(', ')})
|
|
146
|
+
• Trees: ${Object.keys(bundled.rawTrees).length} (${Object.keys(bundled.rawTrees).join(', ')})`);
|
|
147
|
+
|
|
148
|
+
// Auto-generate SQL Indexes
|
|
149
|
+
const indexQueries = new Set([
|
|
150
|
+
"-- Native Columns",
|
|
151
|
+
"CREATE INDEX IF NOT EXISTS idx_content_nodes_slug ON content_nodes (slug);",
|
|
152
|
+
"CREATE INDEX IF NOT EXISTS idx_content_nodes_contentType ON content_nodes (contentType);",
|
|
153
|
+
"CREATE INDEX IF NOT EXISTS idx_content_nodes_updatedAt ON content_nodes (updatedAt);\n",
|
|
154
|
+
"-- JSON Custom Fields"
|
|
155
|
+
]);
|
|
156
|
+
|
|
157
|
+
function extractIndexes(obj) {
|
|
158
|
+
if (typeof obj !== 'object' || obj === null) return;
|
|
159
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
160
|
+
if (typeof value === 'object' && value !== null) {
|
|
161
|
+
if (value.index === true && key !== "id" && key !== "slug" && key !== "contentType") {
|
|
162
|
+
indexQueries.add(`CREATE INDEX IF NOT EXISTS idx_content_nodes_${key} ON content_nodes (json_extract(dataJson, '$.${key}'));`);
|
|
163
|
+
}
|
|
164
|
+
extractIndexes(value);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
extractIndexes(bundled.rawNodes);
|
|
170
|
+
|
|
171
|
+
const sqlContent = Array.from(indexQueries).join('\n');
|
|
172
|
+
const schemaSqlPath = path.resolve(process.cwd(), 'schema.sql');
|
|
173
|
+
|
|
174
|
+
if (fs.existsSync(schemaSqlPath)) {
|
|
175
|
+
fs.appendFileSync(schemaSqlPath, '\n\n' + sqlContent + '\n', 'utf-8');
|
|
176
|
+
}
|