@dani-builder/strapi-plugin-builder 0.1.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/bin/sync.js +320 -0
- package/dist/server/src/bootstrap.d.ts +6 -0
- package/dist/server/src/bootstrap.d.ts.map +1 -0
- package/dist/server/src/bootstrap.js +8 -0
- package/dist/server/src/bootstrap.js.map +1 -0
- package/dist/server/src/components/blocks/bento-grid.json +29 -0
- package/dist/server/src/components/blocks/content.json +23 -0
- package/dist/server/src/components/blocks/cta.json +37 -0
- package/dist/server/src/components/blocks/faq.json +20 -0
- package/dist/server/src/components/blocks/features.json +32 -0
- package/dist/server/src/components/blocks/hero.json +42 -0
- package/dist/server/src/components/blocks/highlights.json +32 -0
- package/dist/server/src/components/blocks/inquiry-form.json +18 -0
- package/dist/server/src/components/blocks/logo-cloud.json +27 -0
- package/dist/server/src/components/blocks/pricing.json +27 -0
- package/dist/server/src/components/blocks/slider.json +27 -0
- package/dist/server/src/components/blocks/stats.json +32 -0
- package/dist/server/src/components/blocks/team.json +27 -0
- package/dist/server/src/components/blocks/testimonials.json +32 -0
- package/dist/server/src/components/elements/footer.json +36 -0
- package/dist/server/src/components/elements/section.json +41 -0
- package/dist/server/src/components/shared/analytics-setting.json +26 -0
- package/dist/server/src/components/shared/bento-item.json +42 -0
- package/dist/server/src/components/shared/brand-colors.json +17 -0
- package/dist/server/src/components/shared/chatbot-setting.json +25 -0
- package/dist/server/src/components/shared/feature-item.json +28 -0
- package/dist/server/src/components/shared/highlight-item.json +27 -0
- package/dist/server/src/components/shared/link.json +27 -0
- package/dist/server/src/components/shared/logo-item.json +24 -0
- package/dist/server/src/components/shared/navigation-group.json +21 -0
- package/dist/server/src/components/shared/pricing-tier.json +36 -0
- package/dist/server/src/components/shared/seo.json +39 -0
- package/dist/server/src/components/shared/site-verification.json +22 -0
- package/dist/server/src/components/shared/slider-item.json +27 -0
- package/dist/server/src/components/shared/stat-item.json +20 -0
- package/dist/server/src/components/shared/team-member.json +30 -0
- package/dist/server/src/components/shared/testimonial-item.json +35 -0
- package/dist/server/src/controllers/global.d.ts +12 -0
- package/dist/server/src/controllers/global.d.ts.map +1 -0
- package/dist/server/src/controllers/global.js +22 -0
- package/dist/server/src/controllers/global.js.map +1 -0
- package/dist/server/src/controllers/index.d.ts +3 -0
- package/dist/server/src/controllers/index.d.ts.map +1 -0
- package/dist/server/src/controllers/index.js +13 -0
- package/dist/server/src/controllers/index.js.map +1 -0
- package/dist/server/src/controllers/page.d.ts +17 -0
- package/dist/server/src/controllers/page.d.ts.map +1 -0
- package/dist/server/src/controllers/page.js +37 -0
- package/dist/server/src/controllers/page.js.map +1 -0
- package/dist/server/src/index.d.ts +3 -0
- package/dist/server/src/index.d.ts.map +1 -0
- package/dist/server/src/index.js +19 -0
- package/dist/server/src/index.js.map +1 -0
- package/dist/server/src/register.d.ts +11 -0
- package/dist/server/src/register.d.ts.map +1 -0
- package/dist/server/src/register.js +48 -0
- package/dist/server/src/register.js.map +1 -0
- package/dist/server/src/routes/content-api.d.ts +14 -0
- package/dist/server/src/routes/content-api.d.ts.map +1 -0
- package/dist/server/src/routes/content-api.js +35 -0
- package/dist/server/src/routes/content-api.js.map +1 -0
- package/dist/server/src/routes/index.d.ts +16 -0
- package/dist/server/src/routes/index.d.ts.map +1 -0
- package/dist/server/src/routes/index.js +10 -0
- package/dist/server/src/routes/index.js.map +1 -0
- package/dist/server/src/services/index.d.ts +3 -0
- package/dist/server/src/services/index.d.ts.map +1 -0
- package/dist/server/src/services/index.js +11 -0
- package/dist/server/src/services/index.js.map +1 -0
- package/dist/server/src/services/populate.d.ts +75 -0
- package/dist/server/src/services/populate.d.ts.map +1 -0
- package/dist/server/src/services/populate.js +252 -0
- package/dist/server/src/services/populate.js.map +1 -0
- package/package.json +55 -0
- package/schemas/api/article/content-types/article/schema.json +102 -0
- package/schemas/api/author/content-types/author/schema.json +44 -0
- package/schemas/api/category/content-types/category/schema.json +43 -0
- package/schemas/api/faq/content-types/faq/schema.json +36 -0
- package/schemas/api/global/content-types/global/schema.json +64 -0
- package/schemas/api/inquiry/content-types/inquiry/schema.json +31 -0
- package/schemas/api/navigation/content-types/navigation/schema.json +52 -0
- package/schemas/api/page/content-types/page/schema.json +62 -0
- package/schemas/api/series/content-types/series/schema.json +44 -0
- package/schemas/api/site-setting/content-types/site-setting/schema.json +35 -0
- package/schemas/api/tag/content-types/tag/schema.json +44 -0
- package/schemas/manifest.json +16 -0
- package/strapi-server.js +3 -0
package/bin/sync.js
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const crypto = require('crypto');
|
|
8
|
+
|
|
9
|
+
// ─── Helpers ──────────────────────────────────────────────
|
|
10
|
+
|
|
11
|
+
function hash(content) {
|
|
12
|
+
return crypto.createHash('sha256').update(content).digest('hex').slice(0, 16);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function ensureDir(dir) {
|
|
16
|
+
if (!fs.existsSync(dir)) {
|
|
17
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function parseArgs(argv) {
|
|
22
|
+
const args = argv.slice(2);
|
|
23
|
+
const opts = {
|
|
24
|
+
command: null,
|
|
25
|
+
dryRun: false,
|
|
26
|
+
force: false,
|
|
27
|
+
only: null,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
for (let i = 0; i < args.length; i++) {
|
|
31
|
+
const arg = args[i];
|
|
32
|
+
if (arg === '--dry-run') {
|
|
33
|
+
opts.dryRun = true;
|
|
34
|
+
} else if (arg === '--force') {
|
|
35
|
+
opts.force = true;
|
|
36
|
+
} else if (arg === '--only' && args[i + 1]) {
|
|
37
|
+
opts.only = args[++i].split(',').map((s) => s.trim());
|
|
38
|
+
} else if (!arg.startsWith('-')) {
|
|
39
|
+
opts.command = arg;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return opts;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ─── Colors (minimal, no dependency) ─────────────────────
|
|
47
|
+
|
|
48
|
+
const c = {
|
|
49
|
+
green: (s) => `\x1b[32m${s}\x1b[0m`,
|
|
50
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
51
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
52
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
53
|
+
dim: (s) => `\x1b[2m${s}\x1b[0m`,
|
|
54
|
+
bold: (s) => `\x1b[1m${s}\x1b[0m`,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// ─── Strapi Boilerplate Generation ───────────────────────
|
|
58
|
+
|
|
59
|
+
function generateBoilerplate(ctName, uid, targetApiDir, opts) {
|
|
60
|
+
const files = [
|
|
61
|
+
{
|
|
62
|
+
rel: `routes/${ctName}.ts`,
|
|
63
|
+
content: `import { factories } from '@strapi/strapi';\nexport default factories.createCoreRouter('${uid}');\n`,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
rel: `controllers/${ctName}.ts`,
|
|
67
|
+
content: `import { factories } from '@strapi/strapi';\nexport default factories.createCoreController('${uid}');\n`,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
rel: `services/${ctName}.ts`,
|
|
71
|
+
content: `import { factories } from '@strapi/strapi';\nexport default factories.createCoreService('${uid}');\n`,
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
const created = [];
|
|
76
|
+
for (const file of files) {
|
|
77
|
+
const filePath = path.join(targetApiDir, file.rel);
|
|
78
|
+
if (!fs.existsSync(filePath)) {
|
|
79
|
+
if (!opts.dryRun) {
|
|
80
|
+
ensureDir(path.dirname(filePath));
|
|
81
|
+
fs.writeFileSync(filePath, file.content, 'utf-8');
|
|
82
|
+
}
|
|
83
|
+
created.push(file.rel);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return created;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function extractUid(schemaPath) {
|
|
90
|
+
try {
|
|
91
|
+
const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));
|
|
92
|
+
const info = schema.info || {};
|
|
93
|
+
const singularName = info.singularName;
|
|
94
|
+
if (singularName) {
|
|
95
|
+
return `api::${singularName}.${singularName}`;
|
|
96
|
+
}
|
|
97
|
+
} catch {
|
|
98
|
+
// fallback below
|
|
99
|
+
}
|
|
100
|
+
// Fallback: derive from path (api/{name}/content-types/{name}/schema.json)
|
|
101
|
+
const parts = schemaPath.split(path.sep);
|
|
102
|
+
const apiIdx = parts.indexOf('api');
|
|
103
|
+
if (apiIdx >= 0 && parts[apiIdx + 1]) {
|
|
104
|
+
const name = parts[apiIdx + 1];
|
|
105
|
+
return `api::${name}.${name}`;
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ─── Sync Logic ──────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
function findProjectRoot() {
|
|
113
|
+
let dir = process.cwd();
|
|
114
|
+
while (dir !== path.dirname(dir)) {
|
|
115
|
+
if (fs.existsSync(path.join(dir, 'package.json'))) {
|
|
116
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8'));
|
|
117
|
+
// Look for Strapi project indicators
|
|
118
|
+
if (
|
|
119
|
+
pkg.dependencies?.['@strapi/strapi'] ||
|
|
120
|
+
pkg.devDependencies?.['@strapi/strapi'] ||
|
|
121
|
+
fs.existsSync(path.join(dir, 'config', 'database.js')) ||
|
|
122
|
+
fs.existsSync(path.join(dir, 'config', 'database.ts'))
|
|
123
|
+
) {
|
|
124
|
+
return dir;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
dir = path.dirname(dir);
|
|
128
|
+
}
|
|
129
|
+
return process.cwd();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function findPluginSchemasDir() {
|
|
133
|
+
// When installed as a dependency, schemas/ is at the package root
|
|
134
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
135
|
+
const schemasDir = path.join(packageRoot, 'schemas');
|
|
136
|
+
if (fs.existsSync(schemasDir)) {
|
|
137
|
+
return schemasDir;
|
|
138
|
+
}
|
|
139
|
+
throw new Error('Could not find plugin schemas directory');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function sync(opts) {
|
|
143
|
+
const projectRoot = findProjectRoot();
|
|
144
|
+
const schemasDir = findPluginSchemasDir();
|
|
145
|
+
const manifestPath = path.join(schemasDir, 'manifest.json');
|
|
146
|
+
const localManifestPath = path.join(projectRoot, '.daniworks-sync-manifest.json');
|
|
147
|
+
|
|
148
|
+
if (!fs.existsSync(manifestPath)) {
|
|
149
|
+
console.error(c.red('Error: manifest.json not found in plugin schemas directory'));
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
154
|
+
const localManifest = fs.existsSync(localManifestPath)
|
|
155
|
+
? JSON.parse(fs.readFileSync(localManifestPath, 'utf-8'))
|
|
156
|
+
: { version: '0.0.0', schemas: {} };
|
|
157
|
+
|
|
158
|
+
const srcDir = path.join(projectRoot, 'src');
|
|
159
|
+
const results = { synced: [], skipped: [], created: [], boilerplate: [] };
|
|
160
|
+
|
|
161
|
+
console.log('');
|
|
162
|
+
console.log(c.bold(` @dani-builder/strapi-plugin-builder sync v${manifest.version}`));
|
|
163
|
+
console.log(c.dim(` Project: ${projectRoot}`));
|
|
164
|
+
console.log(c.dim(` Schemas: ${schemasDir}`));
|
|
165
|
+
if (opts.dryRun) {
|
|
166
|
+
console.log(c.yellow(' Mode: DRY RUN (no files will be modified)'));
|
|
167
|
+
}
|
|
168
|
+
console.log('');
|
|
169
|
+
|
|
170
|
+
for (const [relativePath, sourceHash] of Object.entries(manifest.schemas)) {
|
|
171
|
+
const ctName = relativePath.split('/')[1]; // e.g. "page"
|
|
172
|
+
|
|
173
|
+
// Filter by --only
|
|
174
|
+
if (opts.only && !opts.only.includes(ctName)) {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const sourcePath = path.join(schemasDir, relativePath);
|
|
179
|
+
const targetPath = path.join(srcDir, relativePath);
|
|
180
|
+
|
|
181
|
+
if (!fs.existsSync(sourcePath)) {
|
|
182
|
+
console.log(c.red(` ✗ ${relativePath} — source file missing`));
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const sourceContent = fs.readFileSync(sourcePath, 'utf-8');
|
|
187
|
+
|
|
188
|
+
// Check if target already exists
|
|
189
|
+
if (fs.existsSync(targetPath)) {
|
|
190
|
+
const targetContent = fs.readFileSync(targetPath, 'utf-8');
|
|
191
|
+
const targetHash = hash(targetContent);
|
|
192
|
+
|
|
193
|
+
// Compare against the last synced version (from local manifest)
|
|
194
|
+
const lastSyncedHash = localManifest.schemas[relativePath];
|
|
195
|
+
|
|
196
|
+
if (lastSyncedHash && targetHash !== lastSyncedHash && !opts.force) {
|
|
197
|
+
// Local modification detected
|
|
198
|
+
console.log(
|
|
199
|
+
c.yellow(` ⚠ ${relativePath}`) + c.dim(' — local modifications detected, skipping')
|
|
200
|
+
);
|
|
201
|
+
console.log(c.dim(` Use --force to overwrite`));
|
|
202
|
+
results.skipped.push(relativePath);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (targetHash === sourceHash) {
|
|
207
|
+
// Already up to date
|
|
208
|
+
console.log(c.dim(` ✓ ${relativePath} — already up to date`));
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Update needed
|
|
213
|
+
if (!opts.dryRun) {
|
|
214
|
+
fs.writeFileSync(targetPath, sourceContent, 'utf-8');
|
|
215
|
+
}
|
|
216
|
+
console.log(c.green(` ↑ ${relativePath}`) + c.dim(' — updated'));
|
|
217
|
+
results.synced.push(relativePath);
|
|
218
|
+
} else {
|
|
219
|
+
// New file
|
|
220
|
+
if (!opts.dryRun) {
|
|
221
|
+
ensureDir(path.dirname(targetPath));
|
|
222
|
+
fs.writeFileSync(targetPath, sourceContent, 'utf-8');
|
|
223
|
+
}
|
|
224
|
+
console.log(c.cyan(` + ${relativePath}`) + c.dim(' — created'));
|
|
225
|
+
results.created.push(relativePath);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Generate boilerplate (routes/controllers/services) for each CT
|
|
230
|
+
const processedCts = new Set();
|
|
231
|
+
for (const relativePath of Object.keys(manifest.schemas)) {
|
|
232
|
+
const ctName = relativePath.split('/')[1];
|
|
233
|
+
if (processedCts.has(ctName)) continue;
|
|
234
|
+
if (opts.only && !opts.only.includes(ctName)) continue;
|
|
235
|
+
processedCts.add(ctName);
|
|
236
|
+
|
|
237
|
+
const targetApiDir = path.join(srcDir, 'api', ctName);
|
|
238
|
+
const schemaFile = path.join(targetApiDir, 'content-types', ctName, 'schema.json');
|
|
239
|
+
const uid = extractUid(schemaFile);
|
|
240
|
+
if (!uid) continue;
|
|
241
|
+
|
|
242
|
+
const created = generateBoilerplate(ctName, uid, targetApiDir, opts);
|
|
243
|
+
for (const file of created) {
|
|
244
|
+
console.log(c.cyan(` + api/${ctName}/${file}`) + c.dim(' — generated'));
|
|
245
|
+
results.boilerplate.push(`api/${ctName}/${file}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Update local manifest (unless dry run)
|
|
250
|
+
if (!opts.dryRun) {
|
|
251
|
+
const newLocalManifest = {
|
|
252
|
+
version: manifest.version,
|
|
253
|
+
schemas: { ...manifest.schemas },
|
|
254
|
+
};
|
|
255
|
+
fs.writeFileSync(localManifestPath, JSON.stringify(newLocalManifest, null, 2) + '\n');
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Summary
|
|
259
|
+
console.log('');
|
|
260
|
+
console.log(c.bold(' Summary:'));
|
|
261
|
+
console.log(` Created: ${c.cyan(results.created.length)}`);
|
|
262
|
+
console.log(` Updated: ${c.green(results.synced.length)}`);
|
|
263
|
+
console.log(` Skipped: ${c.yellow(results.skipped.length)}`);
|
|
264
|
+
console.log(` Boilerplate: ${c.cyan(results.boilerplate.length)}`);
|
|
265
|
+
console.log('');
|
|
266
|
+
|
|
267
|
+
if (opts.dryRun) {
|
|
268
|
+
console.log(c.yellow(' This was a dry run. No files were modified.'));
|
|
269
|
+
console.log(c.dim(' Run without --dry-run to apply changes.'));
|
|
270
|
+
console.log('');
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ─── Help ────────────────────────────────────────────────
|
|
275
|
+
|
|
276
|
+
function showHelp() {
|
|
277
|
+
console.log(`
|
|
278
|
+
${c.bold('@dani-builder/strapi-plugin-builder')} — Content Type sync CLI
|
|
279
|
+
|
|
280
|
+
${c.bold('Usage:')}
|
|
281
|
+
npx @dani-builder/strapi-plugin-builder sync [options]
|
|
282
|
+
|
|
283
|
+
${c.bold('Commands:')}
|
|
284
|
+
sync Synchronize content type schemas to your Strapi project
|
|
285
|
+
|
|
286
|
+
${c.bold('Options:')}
|
|
287
|
+
--dry-run Show what would change without modifying files
|
|
288
|
+
--force Overwrite local modifications
|
|
289
|
+
--only <names> Sync only specific content types (comma-separated)
|
|
290
|
+
Example: --only page,article,global
|
|
291
|
+
|
|
292
|
+
${c.bold('Examples:')}
|
|
293
|
+
npx @dani-builder/strapi-plugin-builder sync
|
|
294
|
+
npx @dani-builder/strapi-plugin-builder sync --dry-run
|
|
295
|
+
npx @dani-builder/strapi-plugin-builder sync --force
|
|
296
|
+
npx @dani-builder/strapi-plugin-builder sync --only page,global
|
|
297
|
+
`);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// ─── Main ────────────────────────────────────────────────
|
|
301
|
+
|
|
302
|
+
function main() {
|
|
303
|
+
const opts = parseArgs(process.argv);
|
|
304
|
+
|
|
305
|
+
if (!opts.command || opts.command === 'help' || opts.command === '--help') {
|
|
306
|
+
showHelp();
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (opts.command === 'sync') {
|
|
311
|
+
sync(opts);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
console.error(c.red(`Unknown command: ${opts.command}`));
|
|
316
|
+
showHelp();
|
|
317
|
+
process.exit(1);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
main();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../server/src/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE3C,QAAA,MAAM,SAAS,GAAI,YAAY;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;CAAE,SAGrD,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const bootstrap = ({ strapi }) => {
|
|
4
|
+
// Initialize populate service with core block definitions
|
|
5
|
+
strapi.plugin('builder').service('populate').buildBlocksPopulate();
|
|
6
|
+
};
|
|
7
|
+
exports.default = bootstrap;
|
|
8
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../../server/src/bootstrap.ts"],"names":[],"mappings":";;AAEA,MAAM,SAAS,GAAG,CAAC,EAAE,MAAM,EAA2B,EAAE,EAAE;IACxD,0DAA0D;IAC1D,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,mBAAmB,EAAE,CAAC;AACrE,CAAC,CAAC;AAEF,kBAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "components_blocks_bento_grids",
|
|
3
|
+
"info": {
|
|
4
|
+
"displayName": "Bento Grid",
|
|
5
|
+
"icon": "grid",
|
|
6
|
+
"description": "Asymmetric grid layout with per-item span control"
|
|
7
|
+
},
|
|
8
|
+
"attributes": {
|
|
9
|
+
"name": {
|
|
10
|
+
"type": "string"
|
|
11
|
+
},
|
|
12
|
+
"section": {
|
|
13
|
+
"type": "component",
|
|
14
|
+
"component": "elements.section",
|
|
15
|
+
"repeatable": false
|
|
16
|
+
},
|
|
17
|
+
"columns": {
|
|
18
|
+
"type": "integer",
|
|
19
|
+
"min": 2,
|
|
20
|
+
"max": 4,
|
|
21
|
+
"default": 3
|
|
22
|
+
},
|
|
23
|
+
"items": {
|
|
24
|
+
"type": "component",
|
|
25
|
+
"component": "shared.bento-item",
|
|
26
|
+
"repeatable": true
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "components_blocks_contents",
|
|
3
|
+
"info": {
|
|
4
|
+
"displayName": "Content",
|
|
5
|
+
"icon": "feather",
|
|
6
|
+
"description": "Rich text content block using Strapi Blocks editor"
|
|
7
|
+
},
|
|
8
|
+
"attributes": {
|
|
9
|
+
"section": {
|
|
10
|
+
"type": "component",
|
|
11
|
+
"component": "elements.section",
|
|
12
|
+
"repeatable": false
|
|
13
|
+
},
|
|
14
|
+
"variant": {
|
|
15
|
+
"type": "enumeration",
|
|
16
|
+
"enum": ["prose", "wide", "full-width"]
|
|
17
|
+
},
|
|
18
|
+
"body": {
|
|
19
|
+
"type": "blocks",
|
|
20
|
+
"required": true
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "components_blocks_ctas",
|
|
3
|
+
"info": {
|
|
4
|
+
"displayName": "CTA",
|
|
5
|
+
"icon": "cursor",
|
|
6
|
+
"description": "Call-to-Action block with media and action links"
|
|
7
|
+
},
|
|
8
|
+
"attributes": {
|
|
9
|
+
"section": {
|
|
10
|
+
"type": "component",
|
|
11
|
+
"component": "elements.section",
|
|
12
|
+
"repeatable": false
|
|
13
|
+
},
|
|
14
|
+
"variant": {
|
|
15
|
+
"type": "enumeration",
|
|
16
|
+
"enum": ["inline-spread", "inline-centered", "inline-stacked", "card-stacked", "card-centered", "card-horizontal"]
|
|
17
|
+
},
|
|
18
|
+
"ctaMedia": {
|
|
19
|
+
"type": "media",
|
|
20
|
+
"multiple": false,
|
|
21
|
+
"allowedTypes": ["images", "videos"]
|
|
22
|
+
},
|
|
23
|
+
"ctaText": {
|
|
24
|
+
"type": "text"
|
|
25
|
+
},
|
|
26
|
+
"ctaLink": {
|
|
27
|
+
"type": "component",
|
|
28
|
+
"component": "shared.link",
|
|
29
|
+
"repeatable": false
|
|
30
|
+
},
|
|
31
|
+
"secondaryLink": {
|
|
32
|
+
"type": "component",
|
|
33
|
+
"component": "shared.link",
|
|
34
|
+
"repeatable": false
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "components_blocks_faqs",
|
|
3
|
+
"info": {
|
|
4
|
+
"displayName": "FAQ",
|
|
5
|
+
"icon": "question",
|
|
6
|
+
"description": "FAQ list block linked to FAQ content type via relation"
|
|
7
|
+
},
|
|
8
|
+
"attributes": {
|
|
9
|
+
"section": {
|
|
10
|
+
"type": "component",
|
|
11
|
+
"component": "elements.section",
|
|
12
|
+
"repeatable": false
|
|
13
|
+
},
|
|
14
|
+
"items": {
|
|
15
|
+
"type": "relation",
|
|
16
|
+
"relation": "oneToMany",
|
|
17
|
+
"target": "api::faq.faq"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "components_blocks_features",
|
|
3
|
+
"info": {
|
|
4
|
+
"displayName": "Features",
|
|
5
|
+
"icon": "apps",
|
|
6
|
+
"description": "Feature/service showcase with icon+text items"
|
|
7
|
+
},
|
|
8
|
+
"attributes": {
|
|
9
|
+
"name": {
|
|
10
|
+
"type": "string"
|
|
11
|
+
},
|
|
12
|
+
"variant": {
|
|
13
|
+
"type": "enumeration",
|
|
14
|
+
"enum": ["simple-grid", "dual-column", "media-aside", "media-aside-compact"]
|
|
15
|
+
},
|
|
16
|
+
"section": {
|
|
17
|
+
"type": "component",
|
|
18
|
+
"component": "elements.section",
|
|
19
|
+
"repeatable": false
|
|
20
|
+
},
|
|
21
|
+
"media": {
|
|
22
|
+
"type": "media",
|
|
23
|
+
"multiple": false,
|
|
24
|
+
"allowedTypes": ["images"]
|
|
25
|
+
},
|
|
26
|
+
"items": {
|
|
27
|
+
"type": "component",
|
|
28
|
+
"component": "shared.feature-item",
|
|
29
|
+
"repeatable": true
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "components_blocks_heroes",
|
|
3
|
+
"info": {
|
|
4
|
+
"displayName": "Hero",
|
|
5
|
+
"icon": "picture",
|
|
6
|
+
"description": "Hero banner with media, CTA links, and layout variants"
|
|
7
|
+
},
|
|
8
|
+
"attributes": {
|
|
9
|
+
"variant": {
|
|
10
|
+
"type": "enumeration",
|
|
11
|
+
"enum": ["side-by-side", "media-extending", "fullscreen-media", "stacked-media"]
|
|
12
|
+
},
|
|
13
|
+
"section": {
|
|
14
|
+
"type": "component",
|
|
15
|
+
"component": "elements.section",
|
|
16
|
+
"repeatable": false
|
|
17
|
+
},
|
|
18
|
+
"heroMedia": {
|
|
19
|
+
"type": "media",
|
|
20
|
+
"multiple": false,
|
|
21
|
+
"allowedTypes": ["images", "videos"]
|
|
22
|
+
},
|
|
23
|
+
"ctaText": {
|
|
24
|
+
"type": "text"
|
|
25
|
+
},
|
|
26
|
+
"ctaLink": {
|
|
27
|
+
"type": "component",
|
|
28
|
+
"component": "shared.link",
|
|
29
|
+
"repeatable": false
|
|
30
|
+
},
|
|
31
|
+
"secondaryLink": {
|
|
32
|
+
"type": "component",
|
|
33
|
+
"component": "shared.link",
|
|
34
|
+
"repeatable": false
|
|
35
|
+
},
|
|
36
|
+
"headerMode": {
|
|
37
|
+
"type": "enumeration",
|
|
38
|
+
"enum": ["none", "transparent-black", "transparent-white"],
|
|
39
|
+
"default": "none"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "components_blocks_highlights",
|
|
3
|
+
"info": {
|
|
4
|
+
"displayName": "Highlights",
|
|
5
|
+
"icon": "star",
|
|
6
|
+
"description": "Highlight/feature showcase with media+text items"
|
|
7
|
+
},
|
|
8
|
+
"attributes": {
|
|
9
|
+
"name": {
|
|
10
|
+
"type": "string"
|
|
11
|
+
},
|
|
12
|
+
"variant": {
|
|
13
|
+
"type": "enumeration",
|
|
14
|
+
"enum": ["dual-column", "triple-column", "alternating"]
|
|
15
|
+
},
|
|
16
|
+
"media": {
|
|
17
|
+
"type": "media",
|
|
18
|
+
"multiple": false,
|
|
19
|
+
"allowedTypes": ["images", "videos"]
|
|
20
|
+
},
|
|
21
|
+
"section": {
|
|
22
|
+
"type": "component",
|
|
23
|
+
"component": "elements.section",
|
|
24
|
+
"repeatable": false
|
|
25
|
+
},
|
|
26
|
+
"items": {
|
|
27
|
+
"type": "component",
|
|
28
|
+
"component": "shared.highlight-item",
|
|
29
|
+
"repeatable": true
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "components_blocks_inquiry_forms",
|
|
3
|
+
"info": {
|
|
4
|
+
"displayName": "Inquiry Form",
|
|
5
|
+
"icon": "envelop",
|
|
6
|
+
"description": "Contact form block that submits to Inquiry content type"
|
|
7
|
+
},
|
|
8
|
+
"attributes": {
|
|
9
|
+
"section": {
|
|
10
|
+
"type": "component",
|
|
11
|
+
"component": "elements.section",
|
|
12
|
+
"repeatable": false
|
|
13
|
+
},
|
|
14
|
+
"successMessage": {
|
|
15
|
+
"type": "text"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "components_blocks_logo_clouds",
|
|
3
|
+
"info": {
|
|
4
|
+
"displayName": "Logo Cloud",
|
|
5
|
+
"icon": "picture",
|
|
6
|
+
"description": "Client/partner logo showcase block"
|
|
7
|
+
},
|
|
8
|
+
"attributes": {
|
|
9
|
+
"name": {
|
|
10
|
+
"type": "string"
|
|
11
|
+
},
|
|
12
|
+
"variant": {
|
|
13
|
+
"type": "enumeration",
|
|
14
|
+
"enum": ["inline", "grid", "split"]
|
|
15
|
+
},
|
|
16
|
+
"section": {
|
|
17
|
+
"type": "component",
|
|
18
|
+
"component": "elements.section",
|
|
19
|
+
"repeatable": false
|
|
20
|
+
},
|
|
21
|
+
"items": {
|
|
22
|
+
"type": "component",
|
|
23
|
+
"component": "shared.logo-item",
|
|
24
|
+
"repeatable": true
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "components_blocks_pricings",
|
|
3
|
+
"info": {
|
|
4
|
+
"displayName": "Pricing",
|
|
5
|
+
"icon": "priceTag",
|
|
6
|
+
"description": "Pricing plans/tiers comparison block"
|
|
7
|
+
},
|
|
8
|
+
"attributes": {
|
|
9
|
+
"name": {
|
|
10
|
+
"type": "string"
|
|
11
|
+
},
|
|
12
|
+
"variant": {
|
|
13
|
+
"type": "enumeration",
|
|
14
|
+
"enum": ["two-column", "three-column", "single", "with-comparison"]
|
|
15
|
+
},
|
|
16
|
+
"section": {
|
|
17
|
+
"type": "component",
|
|
18
|
+
"component": "elements.section",
|
|
19
|
+
"repeatable": false
|
|
20
|
+
},
|
|
21
|
+
"items": {
|
|
22
|
+
"type": "component",
|
|
23
|
+
"component": "shared.pricing-tier",
|
|
24
|
+
"repeatable": true
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "components_blocks_sliders",
|
|
3
|
+
"info": {
|
|
4
|
+
"displayName": "Slider",
|
|
5
|
+
"icon": "slideshow",
|
|
6
|
+
"description": "Slider/carousel block with media+text items"
|
|
7
|
+
},
|
|
8
|
+
"attributes": {
|
|
9
|
+
"name": {
|
|
10
|
+
"type": "string"
|
|
11
|
+
},
|
|
12
|
+
"variant": {
|
|
13
|
+
"type": "enumeration",
|
|
14
|
+
"enum": ["cover-flow", "card-slider"]
|
|
15
|
+
},
|
|
16
|
+
"section": {
|
|
17
|
+
"type": "component",
|
|
18
|
+
"component": "elements.section",
|
|
19
|
+
"repeatable": false
|
|
20
|
+
},
|
|
21
|
+
"items": {
|
|
22
|
+
"type": "component",
|
|
23
|
+
"component": "shared.slider-item",
|
|
24
|
+
"repeatable": true
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|