@sonicjs-cms/core 2.0.10 → 2.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/dist/chunk-22EFGHAX.cjs +801 -0
- package/dist/chunk-22EFGHAX.cjs.map +1 -0
- package/dist/{chunk-3PHG75W4.cjs → chunk-2MBNRFS5.cjs} +7 -5
- package/dist/chunk-2MBNRFS5.cjs.map +1 -0
- package/dist/{chunk-LW33AOBF.js → chunk-5RKQB2JG.js} +6 -222
- package/dist/chunk-5RKQB2JG.js.map +1 -0
- package/dist/{chunk-HXA5QSI3.cjs → chunk-7EGKU7OO.cjs} +22 -6
- package/dist/chunk-7EGKU7OO.cjs.map +1 -0
- package/dist/{chunk-6FR25MPC.js → chunk-F4K5QAN6.js} +246 -3
- package/dist/chunk-F4K5QAN6.js.map +1 -0
- package/dist/{chunk-MXJJN4IA.js → chunk-K5JZ4JI3.js} +7 -5
- package/dist/chunk-K5JZ4JI3.js.map +1 -0
- package/dist/{chunk-Z4H6DBVF.js → chunk-KZ5XDGE6.js} +11991 -10731
- package/dist/chunk-KZ5XDGE6.js.map +1 -0
- package/dist/{chunk-Q7SL7U43.cjs → chunk-LPM3NPAX.cjs} +12001 -10740
- package/dist/chunk-LPM3NPAX.cjs.map +1 -0
- package/dist/chunk-LWMMMW43.js +787 -0
- package/dist/chunk-LWMMMW43.js.map +1 -0
- package/dist/chunk-NMVOTNSL.js +61 -0
- package/dist/chunk-NMVOTNSL.js.map +1 -0
- package/dist/{chunk-FTMKKKNH.js → chunk-QNWYQZ55.js} +3 -3
- package/dist/{chunk-FTMKKKNH.js.map → chunk-QNWYQZ55.js.map} +1 -1
- package/dist/{chunk-COBUPOMD.js → chunk-T7IYBGGO.cjs} +5 -770
- package/dist/chunk-T7IYBGGO.cjs.map +1 -0
- package/dist/{chunk-YHG45LMU.js → chunk-UJ4K4B23.js} +20 -4
- package/dist/chunk-UJ4K4B23.js.map +1 -0
- package/dist/chunk-WBX5YMTB.cjs +70 -0
- package/dist/chunk-WBX5YMTB.cjs.map +1 -0
- package/dist/{chunk-DOR2IU73.cjs → chunk-YP52USGX.cjs} +249 -2
- package/dist/chunk-YP52USGX.cjs.map +1 -0
- package/dist/{chunk-MU3MR2QR.cjs → chunk-YU6QFFI4.cjs} +5 -222
- package/dist/chunk-YU6QFFI4.cjs.map +1 -0
- package/dist/{chunk-CAP6QQR2.cjs → chunk-ZMSYKV62.cjs} +5 -5
- package/dist/{chunk-CAP6QQR2.cjs.map → chunk-ZMSYKV62.cjs.map} +1 -1
- package/dist/{chunk-NBDPIRQS.cjs → chunk-ZPMFT2JW.js} +4 -786
- package/dist/chunk-ZPMFT2JW.js.map +1 -0
- package/dist/index.cjs +520 -147
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +389 -12
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +24 -23
- package/dist/middleware.js +3 -2
- package/dist/migrations-IHERIQVD.js +4 -0
- package/dist/migrations-IHERIQVD.js.map +1 -0
- package/dist/migrations-POFD5KNG.cjs +13 -0
- package/dist/migrations-POFD5KNG.cjs.map +1 -0
- package/dist/routes.cjs +31 -29
- package/dist/routes.js +8 -6
- package/dist/services.cjs +42 -24
- package/dist/services.js +4 -2
- package/dist/templates.cjs +17 -21
- package/dist/templates.js +2 -2
- package/dist/utils.cjs +44 -11
- package/dist/utils.js +2 -1
- package/migrations/001_initial_schema.sql +2 -2
- package/migrations/007_demo_login_plugin.sql +1 -1
- package/migrations/020_add_email_plugin.sql +22 -0
- package/migrations/021_add_magic_link_auth_plugin.sql +42 -0
- package/migrations/021_add_otp_login.sql +42 -0
- package/migrations/022_add_tinymce_plugin.sql +25 -0
- package/migrations/023_add_easy_mdx_plugin.sql +25 -0
- package/migrations/024_add_quill_editor_plugin.sql +25 -0
- package/migrations/025_rename_mdxeditor_to_easy_mdx.sql +22 -0
- package/package.json +5 -3
- package/dist/chunk-3PHG75W4.cjs.map +0 -1
- package/dist/chunk-6FR25MPC.js.map +0 -1
- package/dist/chunk-COBUPOMD.js.map +0 -1
- package/dist/chunk-DOR2IU73.cjs.map +0 -1
- package/dist/chunk-HXA5QSI3.cjs.map +0 -1
- package/dist/chunk-LW33AOBF.js.map +0 -1
- package/dist/chunk-MU3MR2QR.cjs.map +0 -1
- package/dist/chunk-MXJJN4IA.js.map +0 -1
- package/dist/chunk-NBDPIRQS.cjs.map +0 -1
- package/dist/chunk-Q7SL7U43.cjs.map +0 -1
- package/dist/chunk-YHG45LMU.js.map +0 -1
- package/dist/chunk-Z4H6DBVF.js.map +0 -1
- package/migrations/002_faq_plugin.sql +0 -86
|
@@ -1,271 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// src/services/collection-loader.ts
|
|
4
|
-
var registeredCollections = [];
|
|
5
|
-
function registerCollections(collections) {
|
|
6
|
-
for (const config of collections) {
|
|
7
|
-
if (!config.name || !config.displayName || !config.schema) {
|
|
8
|
-
console.error(`Invalid collection config: missing required fields`, config);
|
|
9
|
-
continue;
|
|
10
|
-
}
|
|
11
|
-
const normalizedConfig = {
|
|
12
|
-
...config,
|
|
13
|
-
managed: config.managed !== void 0 ? config.managed : true,
|
|
14
|
-
isActive: config.isActive !== void 0 ? config.isActive : true
|
|
15
|
-
};
|
|
16
|
-
registeredCollections.push(normalizedConfig);
|
|
17
|
-
console.log(`\u2713 Registered collection: ${config.name}`);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
async function loadCollectionConfigs() {
|
|
21
|
-
const collections = [...registeredCollections];
|
|
22
|
-
try {
|
|
23
|
-
const modules = undefined?.("../collections/*.collection.ts", { eager: true }) || {};
|
|
24
|
-
for (const [path, module] of Object.entries(modules)) {
|
|
25
|
-
try {
|
|
26
|
-
const configModule = module;
|
|
27
|
-
if (!configModule.default) {
|
|
28
|
-
console.warn(`Collection file ${path} does not export a default config`);
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
const config = configModule.default;
|
|
32
|
-
if (!config.name || !config.displayName || !config.schema) {
|
|
33
|
-
console.error(`Invalid collection config in ${path}: missing required fields`);
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
const normalizedConfig = {
|
|
37
|
-
...config,
|
|
38
|
-
managed: config.managed !== void 0 ? config.managed : true,
|
|
39
|
-
isActive: config.isActive !== void 0 ? config.isActive : true
|
|
40
|
-
};
|
|
41
|
-
collections.push(normalizedConfig);
|
|
42
|
-
console.log(`\u2713 Loaded collection config: ${config.name}`);
|
|
43
|
-
} catch (error) {
|
|
44
|
-
console.error(`Error loading collection from ${path}:`, error);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
console.log(`Loaded ${collections.length} total collection configuration(s) (${registeredCollections.length} registered, ${collections.length - registeredCollections.length} from core)`);
|
|
48
|
-
return collections;
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.error("Error loading collection configurations:", error);
|
|
51
|
-
return collections;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
async function loadCollectionConfig(name) {
|
|
55
|
-
try {
|
|
56
|
-
console.warn("loadCollectionConfig requires implementation in consuming application");
|
|
57
|
-
return null;
|
|
58
|
-
} catch (error) {
|
|
59
|
-
console.error(`Error loading collection ${name}:`, error);
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
async function getAvailableCollectionNames() {
|
|
64
|
-
try {
|
|
65
|
-
const modules = undefined?.("../collections/*.collection.ts") || {};
|
|
66
|
-
const names = [];
|
|
67
|
-
for (const path of Object.keys(modules)) {
|
|
68
|
-
const match = path.match(/\/([^/]+)\.collection\.ts$/);
|
|
69
|
-
if (match && match[1]) {
|
|
70
|
-
names.push(match[1]);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return names;
|
|
74
|
-
} catch (error) {
|
|
75
|
-
console.error("Error getting collection names:", error);
|
|
76
|
-
return [];
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
function validateCollectionConfig(config) {
|
|
80
|
-
const errors = [];
|
|
81
|
-
if (!config.name) {
|
|
82
|
-
errors.push("Collection name is required");
|
|
83
|
-
} else if (!/^[a-z0-9_]+$/.test(config.name)) {
|
|
84
|
-
errors.push("Collection name must contain only lowercase letters, numbers, and underscores");
|
|
85
|
-
}
|
|
86
|
-
if (!config.displayName) {
|
|
87
|
-
errors.push("Display name is required");
|
|
88
|
-
}
|
|
89
|
-
if (!config.schema) {
|
|
90
|
-
errors.push("Schema is required");
|
|
91
|
-
} else {
|
|
92
|
-
if (config.schema.type !== "object") {
|
|
93
|
-
errors.push('Schema type must be "object"');
|
|
94
|
-
}
|
|
95
|
-
if (!config.schema.properties || typeof config.schema.properties !== "object") {
|
|
96
|
-
errors.push("Schema must have properties");
|
|
97
|
-
}
|
|
98
|
-
for (const [fieldName, fieldConfig] of Object.entries(config.schema.properties || {})) {
|
|
99
|
-
if (!fieldConfig.type) {
|
|
100
|
-
errors.push(`Field "${fieldName}" is missing type`);
|
|
101
|
-
}
|
|
102
|
-
if (fieldConfig.type === "reference" && !fieldConfig.collection) {
|
|
103
|
-
errors.push(`Reference field "${fieldName}" is missing collection property`);
|
|
104
|
-
}
|
|
105
|
-
if (["select", "multiselect", "radio"].includes(fieldConfig.type) && !fieldConfig.enum) {
|
|
106
|
-
errors.push(`Select field "${fieldName}" is missing enum options`);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return {
|
|
111
|
-
valid: errors.length === 0,
|
|
112
|
-
errors
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// src/services/collection-sync.ts
|
|
117
|
-
async function syncCollections(db) {
|
|
118
|
-
console.log("\u{1F504} Starting collection sync...");
|
|
119
|
-
const results = [];
|
|
120
|
-
const configs = await loadCollectionConfigs();
|
|
121
|
-
if (configs.length === 0) {
|
|
122
|
-
console.log("\u26A0\uFE0F No collection configurations found");
|
|
123
|
-
return results;
|
|
124
|
-
}
|
|
125
|
-
for (const config of configs) {
|
|
126
|
-
const result = await syncCollection(db, config);
|
|
127
|
-
results.push(result);
|
|
128
|
-
}
|
|
129
|
-
const created = results.filter((r) => r.status === "created").length;
|
|
130
|
-
const updated = results.filter((r) => r.status === "updated").length;
|
|
131
|
-
const unchanged = results.filter((r) => r.status === "unchanged").length;
|
|
132
|
-
const errors = results.filter((r) => r.status === "error").length;
|
|
133
|
-
console.log(`\u2705 Collection sync complete: ${created} created, ${updated} updated, ${unchanged} unchanged, ${errors} errors`);
|
|
134
|
-
return results;
|
|
135
|
-
}
|
|
136
|
-
async function syncCollection(db, config) {
|
|
137
|
-
try {
|
|
138
|
-
const validation = validateCollectionConfig(config);
|
|
139
|
-
if (!validation.valid) {
|
|
140
|
-
return {
|
|
141
|
-
name: config.name,
|
|
142
|
-
status: "error",
|
|
143
|
-
error: `Validation failed: ${validation.errors.join(", ")}`
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
const existingStmt = db.prepare("SELECT * FROM collections WHERE name = ?");
|
|
147
|
-
const existing = await existingStmt.bind(config.name).first();
|
|
148
|
-
const now = Date.now();
|
|
149
|
-
const collectionId = existing?.id || `col-${config.name}-${crypto.randomUUID().slice(0, 8)}`;
|
|
150
|
-
const schemaJson = JSON.stringify(config.schema);
|
|
151
|
-
const isActive = config.isActive !== false ? 1 : 0;
|
|
152
|
-
const managed = config.managed !== false ? 1 : 0;
|
|
153
|
-
if (!existing) {
|
|
154
|
-
const insertStmt = db.prepare(`
|
|
155
|
-
INSERT INTO collections (id, name, display_name, description, schema, is_active, managed, created_at, updated_at)
|
|
156
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
157
|
-
`);
|
|
158
|
-
await insertStmt.bind(
|
|
159
|
-
collectionId,
|
|
160
|
-
config.name,
|
|
161
|
-
config.displayName,
|
|
162
|
-
config.description || null,
|
|
163
|
-
schemaJson,
|
|
164
|
-
isActive,
|
|
165
|
-
managed,
|
|
166
|
-
now,
|
|
167
|
-
now
|
|
168
|
-
).run();
|
|
169
|
-
console.log(` \u2713 Created collection: ${config.name}`);
|
|
170
|
-
return {
|
|
171
|
-
name: config.name,
|
|
172
|
-
status: "created",
|
|
173
|
-
message: `Created collection "${config.displayName}"`
|
|
174
|
-
};
|
|
175
|
-
} else {
|
|
176
|
-
const existingSchema = existing.schema ? JSON.stringify(existing.schema) : "{}";
|
|
177
|
-
const existingDisplayName = existing.display_name;
|
|
178
|
-
const existingDescription = existing.description;
|
|
179
|
-
const existingIsActive = existing.is_active;
|
|
180
|
-
const existingManaged = existing.managed;
|
|
181
|
-
const needsUpdate = schemaJson !== existingSchema || config.displayName !== existingDisplayName || (config.description || null) !== existingDescription || isActive !== existingIsActive || managed !== existingManaged;
|
|
182
|
-
if (!needsUpdate) {
|
|
183
|
-
return {
|
|
184
|
-
name: config.name,
|
|
185
|
-
status: "unchanged",
|
|
186
|
-
message: `Collection "${config.displayName}" is up to date`
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
const updateStmt = db.prepare(`
|
|
190
|
-
UPDATE collections
|
|
191
|
-
SET display_name = ?, description = ?, schema = ?, is_active = ?, managed = ?, updated_at = ?
|
|
192
|
-
WHERE name = ?
|
|
193
|
-
`);
|
|
194
|
-
await updateStmt.bind(
|
|
195
|
-
config.displayName,
|
|
196
|
-
config.description || null,
|
|
197
|
-
schemaJson,
|
|
198
|
-
isActive,
|
|
199
|
-
managed,
|
|
200
|
-
now,
|
|
201
|
-
config.name
|
|
202
|
-
).run();
|
|
203
|
-
console.log(` \u2713 Updated collection: ${config.name}`);
|
|
204
|
-
return {
|
|
205
|
-
name: config.name,
|
|
206
|
-
status: "updated",
|
|
207
|
-
message: `Updated collection "${config.displayName}"`
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
} catch (error) {
|
|
211
|
-
console.error(` \u2717 Error syncing collection ${config.name}:`, error);
|
|
212
|
-
return {
|
|
213
|
-
name: config.name,
|
|
214
|
-
status: "error",
|
|
215
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
async function isCollectionManaged(db, collectionName) {
|
|
220
|
-
try {
|
|
221
|
-
const stmt = db.prepare("SELECT managed FROM collections WHERE name = ?");
|
|
222
|
-
const result = await stmt.bind(collectionName).first();
|
|
223
|
-
return result?.managed === 1;
|
|
224
|
-
} catch (error) {
|
|
225
|
-
console.error(`Error checking if collection is managed:`, error);
|
|
226
|
-
return false;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
async function getManagedCollections(db) {
|
|
230
|
-
try {
|
|
231
|
-
const stmt = db.prepare("SELECT name FROM collections WHERE managed = 1");
|
|
232
|
-
const { results } = await stmt.all();
|
|
233
|
-
return (results || []).map((row) => row.name);
|
|
234
|
-
} catch (error) {
|
|
235
|
-
console.error("Error getting managed collections:", error);
|
|
236
|
-
return [];
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
async function cleanupRemovedCollections(db) {
|
|
240
|
-
try {
|
|
241
|
-
const configs = await loadCollectionConfigs();
|
|
242
|
-
const configNames = new Set(configs.map((c) => c.name));
|
|
243
|
-
const managedCollections = await getManagedCollections(db);
|
|
244
|
-
const removed = [];
|
|
245
|
-
for (const managedName of managedCollections) {
|
|
246
|
-
if (!configNames.has(managedName)) {
|
|
247
|
-
const updateStmt = db.prepare(`
|
|
248
|
-
UPDATE collections
|
|
249
|
-
SET is_active = 0, updated_at = ?
|
|
250
|
-
WHERE name = ? AND managed = 1
|
|
251
|
-
`);
|
|
252
|
-
await updateStmt.bind(Date.now(), managedName).run();
|
|
253
|
-
removed.push(managedName);
|
|
254
|
-
console.log(` \u26A0\uFE0F Deactivated removed collection: ${managedName}`);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
return removed;
|
|
258
|
-
} catch (error) {
|
|
259
|
-
console.error("Error cleaning up removed collections:", error);
|
|
260
|
-
return [];
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
async function fullCollectionSync(db) {
|
|
264
|
-
const results = await syncCollections(db);
|
|
265
|
-
const removed = await cleanupRemovedCollections(db);
|
|
266
|
-
return { results, removed };
|
|
267
|
-
}
|
|
268
|
-
|
|
269
1
|
// src/services/migrations.ts
|
|
270
2
|
var MigrationService = class {
|
|
271
3
|
constructor(db) {
|
|
@@ -706,7 +438,7 @@ CREATE INDEX IF NOT EXISTS idx_api_tokens_token ON api_tokens(token);
|
|
|
706
438
|
CREATE INDEX IF NOT EXISTS idx_workflow_history_content ON workflow_history(content_id);
|
|
707
439
|
CREATE INDEX IF NOT EXISTS idx_workflow_history_user ON workflow_history(user_id);
|
|
708
440
|
|
|
709
|
-
-- Insert default admin user (password:
|
|
441
|
+
-- Insert default admin user (password: sonicjs!)
|
|
710
442
|
INSERT OR IGNORE INTO users (
|
|
711
443
|
id, email, username, first_name, last_name, password_hash,
|
|
712
444
|
role, is_active, created_at, updated_at
|
|
@@ -1007,520 +739,6 @@ INSERT OR IGNORE INTO content (
|
|
|
1007
739
|
}
|
|
1008
740
|
};
|
|
1009
741
|
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
this.db = db;
|
|
1014
|
-
}
|
|
1015
|
-
async getAllPlugins() {
|
|
1016
|
-
await this.ensureAllPluginsExist();
|
|
1017
|
-
const stmt = this.db.prepare(`
|
|
1018
|
-
SELECT * FROM plugins
|
|
1019
|
-
ORDER BY is_core DESC, display_name ASC
|
|
1020
|
-
`);
|
|
1021
|
-
const { results } = await stmt.all();
|
|
1022
|
-
return (results || []).map(this.mapPluginFromDb);
|
|
1023
|
-
}
|
|
1024
|
-
/**
|
|
1025
|
-
* Ensure all plugins from the registry exist in the database
|
|
1026
|
-
* Auto-installs any newly detected plugins with inactive status
|
|
1027
|
-
*
|
|
1028
|
-
* Note: This method should be overridden or configured with a plugin registry
|
|
1029
|
-
* in the consuming application
|
|
1030
|
-
*/
|
|
1031
|
-
async ensureAllPluginsExist() {
|
|
1032
|
-
console.log("[PluginService] ensureAllPluginsExist - requires PLUGIN_REGISTRY configuration");
|
|
1033
|
-
}
|
|
1034
|
-
async getPlugin(pluginId) {
|
|
1035
|
-
const stmt = this.db.prepare("SELECT * FROM plugins WHERE id = ?");
|
|
1036
|
-
const plugin = await stmt.bind(pluginId).first();
|
|
1037
|
-
if (!plugin) return null;
|
|
1038
|
-
return this.mapPluginFromDb(plugin);
|
|
1039
|
-
}
|
|
1040
|
-
async getPluginByName(name) {
|
|
1041
|
-
const stmt = this.db.prepare("SELECT * FROM plugins WHERE name = ?");
|
|
1042
|
-
const plugin = await stmt.bind(name).first();
|
|
1043
|
-
if (!plugin) return null;
|
|
1044
|
-
return this.mapPluginFromDb(plugin);
|
|
1045
|
-
}
|
|
1046
|
-
async getPluginStats() {
|
|
1047
|
-
const stmt = this.db.prepare(`
|
|
1048
|
-
SELECT
|
|
1049
|
-
COUNT(*) as total,
|
|
1050
|
-
COUNT(CASE WHEN status = 'active' THEN 1 END) as active,
|
|
1051
|
-
COUNT(CASE WHEN status = 'inactive' THEN 1 END) as inactive,
|
|
1052
|
-
COUNT(CASE WHEN status = 'error' THEN 1 END) as errors
|
|
1053
|
-
FROM plugins
|
|
1054
|
-
`);
|
|
1055
|
-
const stats = await stmt.first();
|
|
1056
|
-
return {
|
|
1057
|
-
total: stats.total || 0,
|
|
1058
|
-
active: stats.active || 0,
|
|
1059
|
-
inactive: stats.inactive || 0,
|
|
1060
|
-
errors: stats.errors || 0
|
|
1061
|
-
};
|
|
1062
|
-
}
|
|
1063
|
-
async installPlugin(pluginData) {
|
|
1064
|
-
const id = pluginData.id || `plugin-${Date.now()}`;
|
|
1065
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
1066
|
-
const stmt = this.db.prepare(`
|
|
1067
|
-
INSERT INTO plugins (
|
|
1068
|
-
id, name, display_name, description, version, author, category, icon,
|
|
1069
|
-
status, is_core, settings, permissions, dependencies, download_count,
|
|
1070
|
-
rating, installed_at, last_updated
|
|
1071
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1072
|
-
`);
|
|
1073
|
-
await stmt.bind(
|
|
1074
|
-
id,
|
|
1075
|
-
pluginData.name || id,
|
|
1076
|
-
pluginData.display_name || "Unnamed Plugin",
|
|
1077
|
-
pluginData.description || "",
|
|
1078
|
-
pluginData.version || "1.0.0",
|
|
1079
|
-
pluginData.author || "Unknown",
|
|
1080
|
-
pluginData.category || "utilities",
|
|
1081
|
-
pluginData.icon || "\u{1F50C}",
|
|
1082
|
-
"inactive",
|
|
1083
|
-
pluginData.is_core || false,
|
|
1084
|
-
JSON.stringify(pluginData.settings || {}),
|
|
1085
|
-
JSON.stringify(pluginData.permissions || []),
|
|
1086
|
-
JSON.stringify(pluginData.dependencies || []),
|
|
1087
|
-
pluginData.download_count || 0,
|
|
1088
|
-
pluginData.rating || 0,
|
|
1089
|
-
now,
|
|
1090
|
-
now
|
|
1091
|
-
).run();
|
|
1092
|
-
await this.logActivity(id, "installed", null, { version: pluginData.version });
|
|
1093
|
-
const installed = await this.getPlugin(id);
|
|
1094
|
-
if (!installed) throw new Error("Failed to install plugin");
|
|
1095
|
-
return installed;
|
|
1096
|
-
}
|
|
1097
|
-
async uninstallPlugin(pluginId) {
|
|
1098
|
-
const plugin = await this.getPlugin(pluginId);
|
|
1099
|
-
if (!plugin) throw new Error("Plugin not found");
|
|
1100
|
-
if (plugin.is_core) throw new Error("Cannot uninstall core plugins");
|
|
1101
|
-
if (plugin.status === "active") {
|
|
1102
|
-
await this.deactivatePlugin(pluginId);
|
|
1103
|
-
}
|
|
1104
|
-
const stmt = this.db.prepare("DELETE FROM plugins WHERE id = ?");
|
|
1105
|
-
await stmt.bind(pluginId).run();
|
|
1106
|
-
await this.logActivity(pluginId, "uninstalled", null, { name: plugin.name });
|
|
1107
|
-
}
|
|
1108
|
-
async activatePlugin(pluginId) {
|
|
1109
|
-
const plugin = await this.getPlugin(pluginId);
|
|
1110
|
-
if (!plugin) throw new Error("Plugin not found");
|
|
1111
|
-
if (plugin.dependencies && plugin.dependencies.length > 0) {
|
|
1112
|
-
await this.checkDependencies(plugin.dependencies);
|
|
1113
|
-
}
|
|
1114
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
1115
|
-
const stmt = this.db.prepare(`
|
|
1116
|
-
UPDATE plugins
|
|
1117
|
-
SET status = 'active', activated_at = ?, error_message = NULL
|
|
1118
|
-
WHERE id = ?
|
|
1119
|
-
`);
|
|
1120
|
-
await stmt.bind(now, pluginId).run();
|
|
1121
|
-
await this.logActivity(pluginId, "activated", null);
|
|
1122
|
-
}
|
|
1123
|
-
async deactivatePlugin(pluginId) {
|
|
1124
|
-
const plugin = await this.getPlugin(pluginId);
|
|
1125
|
-
if (!plugin) throw new Error("Plugin not found");
|
|
1126
|
-
await this.checkDependents(plugin.name);
|
|
1127
|
-
const stmt = this.db.prepare(`
|
|
1128
|
-
UPDATE plugins
|
|
1129
|
-
SET status = 'inactive', activated_at = NULL
|
|
1130
|
-
WHERE id = ?
|
|
1131
|
-
`);
|
|
1132
|
-
await stmt.bind(pluginId).run();
|
|
1133
|
-
await this.logActivity(pluginId, "deactivated", null);
|
|
1134
|
-
}
|
|
1135
|
-
async updatePluginSettings(pluginId, settings) {
|
|
1136
|
-
const plugin = await this.getPlugin(pluginId);
|
|
1137
|
-
if (!plugin) throw new Error("Plugin not found");
|
|
1138
|
-
const stmt = this.db.prepare(`
|
|
1139
|
-
UPDATE plugins
|
|
1140
|
-
SET settings = ?, updated_at = unixepoch()
|
|
1141
|
-
WHERE id = ?
|
|
1142
|
-
`);
|
|
1143
|
-
await stmt.bind(JSON.stringify(settings), pluginId).run();
|
|
1144
|
-
await this.logActivity(pluginId, "settings_updated", null);
|
|
1145
|
-
}
|
|
1146
|
-
async setPluginError(pluginId, error) {
|
|
1147
|
-
const stmt = this.db.prepare(`
|
|
1148
|
-
UPDATE plugins
|
|
1149
|
-
SET status = 'error', error_message = ?
|
|
1150
|
-
WHERE id = ?
|
|
1151
|
-
`);
|
|
1152
|
-
await stmt.bind(error, pluginId).run();
|
|
1153
|
-
await this.logActivity(pluginId, "error", null, { error });
|
|
1154
|
-
}
|
|
1155
|
-
async getPluginActivity(pluginId, limit = 10) {
|
|
1156
|
-
const stmt = this.db.prepare(`
|
|
1157
|
-
SELECT * FROM plugin_activity_log
|
|
1158
|
-
WHERE plugin_id = ?
|
|
1159
|
-
ORDER BY timestamp DESC
|
|
1160
|
-
LIMIT ?
|
|
1161
|
-
`);
|
|
1162
|
-
const { results } = await stmt.bind(pluginId, limit).all();
|
|
1163
|
-
return (results || []).map((row) => ({
|
|
1164
|
-
id: row.id,
|
|
1165
|
-
action: row.action,
|
|
1166
|
-
userId: row.user_id,
|
|
1167
|
-
details: row.details ? JSON.parse(row.details) : null,
|
|
1168
|
-
timestamp: row.timestamp
|
|
1169
|
-
}));
|
|
1170
|
-
}
|
|
1171
|
-
async registerHook(pluginId, hookName, handlerName, priority = 10) {
|
|
1172
|
-
const id = `hook-${Date.now()}`;
|
|
1173
|
-
const stmt = this.db.prepare(`
|
|
1174
|
-
INSERT INTO plugin_hooks (id, plugin_id, hook_name, handler_name, priority)
|
|
1175
|
-
VALUES (?, ?, ?, ?, ?)
|
|
1176
|
-
`);
|
|
1177
|
-
await stmt.bind(id, pluginId, hookName, handlerName, priority).run();
|
|
1178
|
-
}
|
|
1179
|
-
async registerRoute(pluginId, path, method, handlerName, middleware) {
|
|
1180
|
-
const id = `route-${Date.now()}`;
|
|
1181
|
-
const stmt = this.db.prepare(`
|
|
1182
|
-
INSERT INTO plugin_routes (id, plugin_id, path, method, handler_name, middleware)
|
|
1183
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
1184
|
-
`);
|
|
1185
|
-
await stmt.bind(
|
|
1186
|
-
id,
|
|
1187
|
-
pluginId,
|
|
1188
|
-
path,
|
|
1189
|
-
method,
|
|
1190
|
-
handlerName,
|
|
1191
|
-
JSON.stringify(middleware || [])
|
|
1192
|
-
).run();
|
|
1193
|
-
}
|
|
1194
|
-
async getPluginHooks(pluginId) {
|
|
1195
|
-
const stmt = this.db.prepare(`
|
|
1196
|
-
SELECT * FROM plugin_hooks
|
|
1197
|
-
WHERE plugin_id = ? AND is_active = TRUE
|
|
1198
|
-
ORDER BY priority ASC
|
|
1199
|
-
`);
|
|
1200
|
-
const { results } = await stmt.bind(pluginId).all();
|
|
1201
|
-
return results || [];
|
|
1202
|
-
}
|
|
1203
|
-
async getPluginRoutes(pluginId) {
|
|
1204
|
-
const stmt = this.db.prepare(`
|
|
1205
|
-
SELECT * FROM plugin_routes
|
|
1206
|
-
WHERE plugin_id = ? AND is_active = TRUE
|
|
1207
|
-
`);
|
|
1208
|
-
const { results } = await stmt.bind(pluginId).all();
|
|
1209
|
-
return results || [];
|
|
1210
|
-
}
|
|
1211
|
-
async checkDependencies(dependencies) {
|
|
1212
|
-
for (const dep of dependencies) {
|
|
1213
|
-
const plugin = await this.getPluginByName(dep);
|
|
1214
|
-
if (!plugin || plugin.status !== "active") {
|
|
1215
|
-
throw new Error(`Required dependency '${dep}' is not active`);
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
async checkDependents(pluginName) {
|
|
1220
|
-
const stmt = this.db.prepare(`
|
|
1221
|
-
SELECT id, display_name FROM plugins
|
|
1222
|
-
WHERE status = 'active'
|
|
1223
|
-
AND dependencies LIKE ?
|
|
1224
|
-
`);
|
|
1225
|
-
const { results } = await stmt.bind(`%"${pluginName}"%`).all();
|
|
1226
|
-
if (results && results.length > 0) {
|
|
1227
|
-
const names = results.map((p) => p.display_name).join(", ");
|
|
1228
|
-
throw new Error(`Cannot deactivate. The following plugins depend on this one: ${names}`);
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
async logActivity(pluginId, action, userId, details) {
|
|
1232
|
-
const id = `activity-${Date.now()}`;
|
|
1233
|
-
const stmt = this.db.prepare(`
|
|
1234
|
-
INSERT INTO plugin_activity_log (id, plugin_id, action, user_id, details)
|
|
1235
|
-
VALUES (?, ?, ?, ?, ?)
|
|
1236
|
-
`);
|
|
1237
|
-
await stmt.bind(
|
|
1238
|
-
id,
|
|
1239
|
-
pluginId,
|
|
1240
|
-
action,
|
|
1241
|
-
userId,
|
|
1242
|
-
details ? JSON.stringify(details) : null
|
|
1243
|
-
).run();
|
|
1244
|
-
}
|
|
1245
|
-
mapPluginFromDb(row) {
|
|
1246
|
-
return {
|
|
1247
|
-
id: row.id,
|
|
1248
|
-
name: row.name,
|
|
1249
|
-
display_name: row.display_name,
|
|
1250
|
-
description: row.description,
|
|
1251
|
-
version: row.version,
|
|
1252
|
-
author: row.author,
|
|
1253
|
-
category: row.category,
|
|
1254
|
-
icon: row.icon,
|
|
1255
|
-
status: row.status,
|
|
1256
|
-
is_core: row.is_core === 1,
|
|
1257
|
-
settings: row.settings ? JSON.parse(row.settings) : void 0,
|
|
1258
|
-
permissions: row.permissions ? JSON.parse(row.permissions) : void 0,
|
|
1259
|
-
dependencies: row.dependencies ? JSON.parse(row.dependencies) : void 0,
|
|
1260
|
-
download_count: row.download_count || 0,
|
|
1261
|
-
rating: row.rating || 0,
|
|
1262
|
-
installed_at: row.installed_at,
|
|
1263
|
-
activated_at: row.activated_at,
|
|
1264
|
-
last_updated: row.last_updated,
|
|
1265
|
-
error_message: row.error_message
|
|
1266
|
-
};
|
|
1267
|
-
}
|
|
1268
|
-
};
|
|
1269
|
-
|
|
1270
|
-
// src/services/plugin-bootstrap.ts
|
|
1271
|
-
var PluginBootstrapService = class {
|
|
1272
|
-
constructor(db) {
|
|
1273
|
-
this.db = db;
|
|
1274
|
-
this.pluginService = new PluginService(db);
|
|
1275
|
-
}
|
|
1276
|
-
pluginService;
|
|
1277
|
-
/**
|
|
1278
|
-
* Core plugins that should always be available in the system
|
|
1279
|
-
*/
|
|
1280
|
-
CORE_PLUGINS = [
|
|
1281
|
-
{
|
|
1282
|
-
id: "core-auth",
|
|
1283
|
-
name: "core-auth",
|
|
1284
|
-
display_name: "Authentication System",
|
|
1285
|
-
description: "Core authentication and user management system",
|
|
1286
|
-
version: "1.0.0",
|
|
1287
|
-
author: "SonicJS Team",
|
|
1288
|
-
category: "security",
|
|
1289
|
-
icon: "\u{1F510}",
|
|
1290
|
-
permissions: ["manage:users", "manage:roles", "manage:permissions"],
|
|
1291
|
-
dependencies: [],
|
|
1292
|
-
settings: {
|
|
1293
|
-
requiredFields: {
|
|
1294
|
-
email: { required: true, minLength: 5, label: "Email", type: "email" },
|
|
1295
|
-
password: { required: true, minLength: 8, label: "Password", type: "password" },
|
|
1296
|
-
username: { required: true, minLength: 3, label: "Username", type: "text" },
|
|
1297
|
-
firstName: { required: true, minLength: 1, label: "First Name", type: "text" },
|
|
1298
|
-
lastName: { required: true, minLength: 1, label: "Last Name", type: "text" }
|
|
1299
|
-
},
|
|
1300
|
-
validation: {
|
|
1301
|
-
emailFormat: true,
|
|
1302
|
-
allowDuplicateUsernames: false,
|
|
1303
|
-
passwordRequirements: {
|
|
1304
|
-
requireUppercase: false,
|
|
1305
|
-
requireLowercase: false,
|
|
1306
|
-
requireNumbers: false,
|
|
1307
|
-
requireSpecialChars: false
|
|
1308
|
-
}
|
|
1309
|
-
},
|
|
1310
|
-
registration: {
|
|
1311
|
-
enabled: true,
|
|
1312
|
-
requireEmailVerification: false,
|
|
1313
|
-
defaultRole: "viewer"
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
},
|
|
1317
|
-
{
|
|
1318
|
-
id: "core-media",
|
|
1319
|
-
name: "core-media",
|
|
1320
|
-
display_name: "Media Manager",
|
|
1321
|
-
description: "Core media upload and management system",
|
|
1322
|
-
version: "1.0.0",
|
|
1323
|
-
author: "SonicJS Team",
|
|
1324
|
-
category: "media",
|
|
1325
|
-
icon: "\u{1F4F8}",
|
|
1326
|
-
permissions: ["manage:media", "upload:files"],
|
|
1327
|
-
dependencies: [],
|
|
1328
|
-
settings: {}
|
|
1329
|
-
},
|
|
1330
|
-
{
|
|
1331
|
-
id: "database-tools",
|
|
1332
|
-
name: "database-tools",
|
|
1333
|
-
display_name: "Database Tools",
|
|
1334
|
-
description: "Database management tools including truncate, backup, and validation",
|
|
1335
|
-
version: "1.0.0",
|
|
1336
|
-
author: "SonicJS Team",
|
|
1337
|
-
category: "system",
|
|
1338
|
-
icon: "\u{1F5C4}\uFE0F",
|
|
1339
|
-
permissions: ["manage:database", "admin"],
|
|
1340
|
-
dependencies: [],
|
|
1341
|
-
settings: {
|
|
1342
|
-
enableTruncate: true,
|
|
1343
|
-
enableBackup: true,
|
|
1344
|
-
enableValidation: true,
|
|
1345
|
-
requireConfirmation: true
|
|
1346
|
-
}
|
|
1347
|
-
},
|
|
1348
|
-
{
|
|
1349
|
-
id: "seed-data",
|
|
1350
|
-
name: "seed-data",
|
|
1351
|
-
display_name: "Seed Data",
|
|
1352
|
-
description: "Generate realistic example users and content for testing and development",
|
|
1353
|
-
version: "1.0.0",
|
|
1354
|
-
author: "SonicJS Team",
|
|
1355
|
-
category: "development",
|
|
1356
|
-
icon: "\u{1F331}",
|
|
1357
|
-
permissions: ["admin"],
|
|
1358
|
-
dependencies: [],
|
|
1359
|
-
settings: {
|
|
1360
|
-
userCount: 20,
|
|
1361
|
-
contentCount: 200,
|
|
1362
|
-
defaultPassword: "password123"
|
|
1363
|
-
}
|
|
1364
|
-
},
|
|
1365
|
-
{
|
|
1366
|
-
id: "core-cache",
|
|
1367
|
-
name: "core-cache",
|
|
1368
|
-
display_name: "Cache System",
|
|
1369
|
-
description: "Three-tiered caching system with memory, KV, and database layers",
|
|
1370
|
-
version: "1.0.0",
|
|
1371
|
-
author: "SonicJS Team",
|
|
1372
|
-
category: "performance",
|
|
1373
|
-
icon: "\u26A1",
|
|
1374
|
-
permissions: ["manage:cache", "view:stats"],
|
|
1375
|
-
dependencies: [],
|
|
1376
|
-
settings: {
|
|
1377
|
-
enableMemoryCache: true,
|
|
1378
|
-
enableKVCache: true,
|
|
1379
|
-
enableDatabaseCache: true,
|
|
1380
|
-
defaultTTL: 3600
|
|
1381
|
-
}
|
|
1382
|
-
},
|
|
1383
|
-
{
|
|
1384
|
-
id: "workflow-plugin",
|
|
1385
|
-
name: "workflow-plugin",
|
|
1386
|
-
display_name: "Workflow Management",
|
|
1387
|
-
description: "Content workflow management with approval chains, scheduling, and automation",
|
|
1388
|
-
version: "1.0.0-beta.1",
|
|
1389
|
-
author: "SonicJS Team",
|
|
1390
|
-
category: "content",
|
|
1391
|
-
icon: "\u{1F504}",
|
|
1392
|
-
permissions: ["manage:workflows", "view:workflows", "transition:content"],
|
|
1393
|
-
dependencies: ["content-plugin"],
|
|
1394
|
-
settings: {
|
|
1395
|
-
enableApprovalChains: true,
|
|
1396
|
-
enableScheduling: true,
|
|
1397
|
-
enableAutomation: true,
|
|
1398
|
-
enableNotifications: true
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
];
|
|
1402
|
-
/**
|
|
1403
|
-
* Bootstrap all core plugins - install them if they don't exist
|
|
1404
|
-
*/
|
|
1405
|
-
async bootstrapCorePlugins() {
|
|
1406
|
-
console.log("[PluginBootstrap] Starting core plugin bootstrap process...");
|
|
1407
|
-
try {
|
|
1408
|
-
for (const corePlugin of this.CORE_PLUGINS) {
|
|
1409
|
-
await this.ensurePluginInstalled(corePlugin);
|
|
1410
|
-
}
|
|
1411
|
-
console.log(
|
|
1412
|
-
"[PluginBootstrap] Core plugin bootstrap completed successfully"
|
|
1413
|
-
);
|
|
1414
|
-
} catch (error) {
|
|
1415
|
-
console.error("[PluginBootstrap] Error during plugin bootstrap:", error);
|
|
1416
|
-
throw error;
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
|
-
/**
|
|
1420
|
-
* Ensure a specific plugin is installed
|
|
1421
|
-
*/
|
|
1422
|
-
async ensurePluginInstalled(plugin) {
|
|
1423
|
-
try {
|
|
1424
|
-
const existingPlugin = await this.pluginService.getPlugin(plugin.id);
|
|
1425
|
-
if (existingPlugin) {
|
|
1426
|
-
console.log(
|
|
1427
|
-
`[PluginBootstrap] Plugin already installed: ${plugin.display_name} (status: ${existingPlugin.status})`
|
|
1428
|
-
);
|
|
1429
|
-
if (existingPlugin.version !== plugin.version) {
|
|
1430
|
-
console.log(
|
|
1431
|
-
`[PluginBootstrap] Updating plugin version: ${plugin.display_name} from ${existingPlugin.version} to ${plugin.version}`
|
|
1432
|
-
);
|
|
1433
|
-
await this.updatePlugin(plugin);
|
|
1434
|
-
}
|
|
1435
|
-
if (plugin.id === "core-auth" && existingPlugin.status !== "active") {
|
|
1436
|
-
console.log(
|
|
1437
|
-
`[PluginBootstrap] Core-auth plugin is inactive, activating it now...`
|
|
1438
|
-
);
|
|
1439
|
-
await this.pluginService.activatePlugin(plugin.id);
|
|
1440
|
-
}
|
|
1441
|
-
} else {
|
|
1442
|
-
console.log(
|
|
1443
|
-
`[PluginBootstrap] Installing plugin: ${plugin.display_name}`
|
|
1444
|
-
);
|
|
1445
|
-
await this.pluginService.installPlugin({
|
|
1446
|
-
...plugin,
|
|
1447
|
-
is_core: plugin.name.startsWith("core-")
|
|
1448
|
-
});
|
|
1449
|
-
if (plugin.name.startsWith("core-")) {
|
|
1450
|
-
console.log(
|
|
1451
|
-
`[PluginBootstrap] Activating newly installed core plugin: ${plugin.display_name}`
|
|
1452
|
-
);
|
|
1453
|
-
await this.pluginService.activatePlugin(plugin.id);
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
} catch (error) {
|
|
1457
|
-
console.error(
|
|
1458
|
-
`[PluginBootstrap] Error ensuring plugin ${plugin.display_name}:`,
|
|
1459
|
-
error
|
|
1460
|
-
);
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
/**
|
|
1464
|
-
* Update an existing plugin
|
|
1465
|
-
*/
|
|
1466
|
-
async updatePlugin(plugin) {
|
|
1467
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
1468
|
-
const stmt = this.db.prepare(`
|
|
1469
|
-
UPDATE plugins
|
|
1470
|
-
SET
|
|
1471
|
-
version = ?,
|
|
1472
|
-
description = ?,
|
|
1473
|
-
permissions = ?,
|
|
1474
|
-
settings = ?,
|
|
1475
|
-
last_updated = ?
|
|
1476
|
-
WHERE id = ?
|
|
1477
|
-
`);
|
|
1478
|
-
await stmt.bind(
|
|
1479
|
-
plugin.version,
|
|
1480
|
-
plugin.description,
|
|
1481
|
-
JSON.stringify(plugin.permissions),
|
|
1482
|
-
JSON.stringify(plugin.settings || {}),
|
|
1483
|
-
now,
|
|
1484
|
-
plugin.id
|
|
1485
|
-
).run();
|
|
1486
|
-
}
|
|
1487
|
-
/**
|
|
1488
|
-
* Check if bootstrap is needed (first run detection)
|
|
1489
|
-
*/
|
|
1490
|
-
async isBootstrapNeeded() {
|
|
1491
|
-
try {
|
|
1492
|
-
for (const corePlugin of this.CORE_PLUGINS.filter(
|
|
1493
|
-
(p) => p.name.startsWith("core-")
|
|
1494
|
-
)) {
|
|
1495
|
-
const exists = await this.pluginService.getPlugin(corePlugin.id);
|
|
1496
|
-
if (!exists) {
|
|
1497
|
-
return true;
|
|
1498
|
-
}
|
|
1499
|
-
}
|
|
1500
|
-
return false;
|
|
1501
|
-
} catch (error) {
|
|
1502
|
-
console.error(
|
|
1503
|
-
"[PluginBootstrap] Error checking bootstrap status:",
|
|
1504
|
-
error
|
|
1505
|
-
);
|
|
1506
|
-
return true;
|
|
1507
|
-
}
|
|
1508
|
-
}
|
|
1509
|
-
};
|
|
1510
|
-
|
|
1511
|
-
exports.MigrationService = MigrationService;
|
|
1512
|
-
exports.PluginBootstrapService = PluginBootstrapService;
|
|
1513
|
-
exports.PluginService = PluginService;
|
|
1514
|
-
exports.cleanupRemovedCollections = cleanupRemovedCollections;
|
|
1515
|
-
exports.fullCollectionSync = fullCollectionSync;
|
|
1516
|
-
exports.getAvailableCollectionNames = getAvailableCollectionNames;
|
|
1517
|
-
exports.getManagedCollections = getManagedCollections;
|
|
1518
|
-
exports.isCollectionManaged = isCollectionManaged;
|
|
1519
|
-
exports.loadCollectionConfig = loadCollectionConfig;
|
|
1520
|
-
exports.loadCollectionConfigs = loadCollectionConfigs;
|
|
1521
|
-
exports.registerCollections = registerCollections;
|
|
1522
|
-
exports.syncCollection = syncCollection;
|
|
1523
|
-
exports.syncCollections = syncCollections;
|
|
1524
|
-
exports.validateCollectionConfig = validateCollectionConfig;
|
|
1525
|
-
//# sourceMappingURL=chunk-NBDPIRQS.cjs.map
|
|
1526
|
-
//# sourceMappingURL=chunk-NBDPIRQS.cjs.map
|
|
742
|
+
export { MigrationService };
|
|
743
|
+
//# sourceMappingURL=chunk-ZPMFT2JW.js.map
|
|
744
|
+
//# sourceMappingURL=chunk-ZPMFT2JW.js.map
|