@objectstack/metadata 0.8.1 → 0.9.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/CHANGELOG.md +9 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/migration/executor.d.ts +9 -0
- package/dist/migration/executor.d.ts.map +1 -0
- package/dist/migration/executor.js +49 -0
- package/dist/migration/index.d.ts +2 -0
- package/dist/migration/index.d.ts.map +1 -0
- package/dist/migration/index.js +1 -0
- package/dist/plugin.d.ts +15 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +71 -0
- package/package.json +4 -4
- package/src/index.ts +4 -0
- package/src/migration/executor.ts +52 -0
- package/src/migration/index.ts +1 -0
- package/src/plugin.ts +89 -0
package/CHANGELOG.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
* Metadata loading, saving, and persistence for ObjectStack
|
|
5
5
|
*/
|
|
6
6
|
export { MetadataManager, type WatchCallback } from './metadata-manager.js';
|
|
7
|
+
export { MetadataPlugin } from './plugin.js';
|
|
7
8
|
export { type MetadataLoader } from './loaders/loader-interface.js';
|
|
8
9
|
export { FilesystemLoader } from './loaders/filesystem-loader.js';
|
|
9
10
|
export { type MetadataSerializer, type SerializeOptions } from './serializers/serializer-interface.js';
|
|
10
11
|
export { JSONSerializer } from './serializers/json-serializer.js';
|
|
11
12
|
export { YAMLSerializer } from './serializers/yaml-serializer.js';
|
|
13
|
+
export * as Migration from './migration/index.js';
|
|
12
14
|
export { TypeScriptSerializer } from './serializers/typescript-serializer.js';
|
|
13
15
|
export type { MetadataFormat, MetadataStats, MetadataLoadOptions, MetadataSaveOptions, MetadataExportOptions, MetadataImportOptions, MetadataLoadResult, MetadataSaveResult, MetadataWatchEvent, MetadataCollectionInfo, MetadataLoaderContract, MetadataManagerConfig, } from '@objectstack/spec/system';
|
|
14
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG5E,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACvG,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAG9E,YAAY,EACV,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG5E,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACvG,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAG9E,YAAY,EACV,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
// Main Manager
|
|
7
7
|
export { MetadataManager } from './metadata-manager.js';
|
|
8
|
+
// Plugin
|
|
9
|
+
export { MetadataPlugin } from './plugin.js';
|
|
8
10
|
export { FilesystemLoader } from './loaders/filesystem-loader.js';
|
|
9
11
|
export { JSONSerializer } from './serializers/json-serializer.js';
|
|
10
12
|
export { YAMLSerializer } from './serializers/yaml-serializer.js';
|
|
13
|
+
export * as Migration from './migration/index.js';
|
|
11
14
|
export { TypeScriptSerializer } from './serializers/typescript-serializer.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { System } from '@objectstack/spec';
|
|
2
|
+
import { ISchemaDriver } from '@objectstack/spec/contracts';
|
|
3
|
+
export declare class MigrationExecutor {
|
|
4
|
+
private driver;
|
|
5
|
+
constructor(driver: ISchemaDriver);
|
|
6
|
+
executeChangeSet(changeSet: System.ChangeSet): Promise<void>;
|
|
7
|
+
private executeOperation;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/migration/executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,qBAAa,iBAAiB;IAChB,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEnC,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;YAapD,gBAAgB;CAgC/B"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export class MigrationExecutor {
|
|
2
|
+
constructor(driver) {
|
|
3
|
+
this.driver = driver;
|
|
4
|
+
}
|
|
5
|
+
async executeChangeSet(changeSet) {
|
|
6
|
+
console.log(`Executing ChangeSet: ${changeSet.name} (${changeSet.id})`);
|
|
7
|
+
for (const op of changeSet.operations) {
|
|
8
|
+
try {
|
|
9
|
+
await this.executeOperation(op);
|
|
10
|
+
}
|
|
11
|
+
catch (e) {
|
|
12
|
+
console.error(`Failed to execute operation ${op.type}:`, e);
|
|
13
|
+
throw e;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async executeOperation(op) {
|
|
18
|
+
switch (op.type) {
|
|
19
|
+
case 'create_object':
|
|
20
|
+
console.log(` > Create Object: ${op.object.name}`);
|
|
21
|
+
await this.driver.createCollection(op.object.name, op.object);
|
|
22
|
+
break;
|
|
23
|
+
case 'add_field':
|
|
24
|
+
console.log(` > Add Field: ${op.objectName}.${op.fieldName}`);
|
|
25
|
+
await this.driver.addColumn(op.objectName, op.fieldName, op.field);
|
|
26
|
+
break;
|
|
27
|
+
case 'remove_field':
|
|
28
|
+
console.log(` > Remove Field: ${op.objectName}.${op.fieldName}`);
|
|
29
|
+
await this.driver.dropColumn(op.objectName, op.fieldName);
|
|
30
|
+
break;
|
|
31
|
+
case 'delete_object':
|
|
32
|
+
console.log(` > Delete Object: ${op.objectName}`);
|
|
33
|
+
await this.driver.dropCollection(op.objectName);
|
|
34
|
+
break;
|
|
35
|
+
case 'execute_sql':
|
|
36
|
+
console.log(` > Execute SQL`);
|
|
37
|
+
await this.driver.executeRaw(op.sql);
|
|
38
|
+
break;
|
|
39
|
+
case 'modify_field':
|
|
40
|
+
console.warn(` ! Modify Field: ${op.objectName}.${op.fieldName} (Not fully implemented)`);
|
|
41
|
+
break;
|
|
42
|
+
case 'rename_object':
|
|
43
|
+
console.warn(` ! Rename Object: ${op.oldName} -> ${op.newName} (Not fully implemented)`);
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
throw new Error(`Unknown operation type`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migration/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './executor.js';
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Plugin, PluginContext } from '@objectstack/core';
|
|
2
|
+
export interface MetadataPluginOptions {
|
|
3
|
+
rootDir?: string;
|
|
4
|
+
watch?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare class MetadataPlugin implements Plugin {
|
|
7
|
+
name: string;
|
|
8
|
+
version: string;
|
|
9
|
+
private manager;
|
|
10
|
+
private options;
|
|
11
|
+
constructor(options?: MetadataPluginOptions);
|
|
12
|
+
init(ctx: PluginContext): Promise<void>;
|
|
13
|
+
start(ctx: PluginContext): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAI1D,MAAM,WAAW,qBAAqB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,cAAe,YAAW,MAAM;IACzC,IAAI,SAA8B;IAClC,OAAO,SAAW;IAElB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,OAAO,CAAwB;gBAE3B,OAAO,GAAE,qBAA0B;IAezC,IAAI,CAAC,GAAG,EAAE,aAAa;IAQvB,KAAK,CAAC,GAAG,EAAE,aAAa;CAiDjC"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { MetadataManager } from './metadata-manager.js';
|
|
2
|
+
import { ObjectStackDefinitionSchema } from '@objectstack/spec';
|
|
3
|
+
export class MetadataPlugin {
|
|
4
|
+
constructor(options = {}) {
|
|
5
|
+
this.name = 'com.objectstack.metadata';
|
|
6
|
+
this.version = '1.0.0';
|
|
7
|
+
this.options = {
|
|
8
|
+
watch: true,
|
|
9
|
+
...options
|
|
10
|
+
};
|
|
11
|
+
const rootDir = this.options.rootDir || process.cwd();
|
|
12
|
+
this.manager = new MetadataManager({
|
|
13
|
+
rootDir,
|
|
14
|
+
watch: this.options.watch ?? true,
|
|
15
|
+
formats: ['yaml', 'json', 'typescript', 'javascript']
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
async init(ctx) {
|
|
19
|
+
ctx.logger.info('Initializing Metadata Manager', { root: this.options.rootDir || process.cwd() });
|
|
20
|
+
// Register Metadata Manager as a service
|
|
21
|
+
// This allows other plugins to query raw metadata or listen to changes
|
|
22
|
+
ctx.registerService('metadata', this.manager);
|
|
23
|
+
}
|
|
24
|
+
async start(ctx) {
|
|
25
|
+
ctx.logger.info('Loading metadata...');
|
|
26
|
+
// Define metadata types directly from the Protocol Definition
|
|
27
|
+
// This ensures the loader is always in sync with the Spec
|
|
28
|
+
const metadataTypes = Object.keys(ObjectStackDefinitionSchema.shape)
|
|
29
|
+
.filter(key => key !== 'manifest'); // Manifest is handled separately
|
|
30
|
+
for (const type of metadataTypes) {
|
|
31
|
+
try {
|
|
32
|
+
// Try to load metadata of this type
|
|
33
|
+
const items = await this.manager.loadMany(type, {
|
|
34
|
+
recursive: true
|
|
35
|
+
});
|
|
36
|
+
if (items.length > 0) {
|
|
37
|
+
ctx.logger.info(`Loaded ${items.length} ${type}`);
|
|
38
|
+
// Helper: Register with ObjectQL Registry
|
|
39
|
+
const ql = ctx.getService('objectql');
|
|
40
|
+
if (ql && ql.registry) {
|
|
41
|
+
items.forEach((item) => {
|
|
42
|
+
// Determine key field (id or name)
|
|
43
|
+
const keyField = item.id ? 'id' : 'name';
|
|
44
|
+
// Map plural type to singular/registry type if needed
|
|
45
|
+
// For now, we use the singular form for standard types:
|
|
46
|
+
// objects -> object, apps -> app, etc.
|
|
47
|
+
// But Registry seems to accept arbitrary strings.
|
|
48
|
+
// To match Protocol standard, we might want to normalize.
|
|
49
|
+
// Let's use the directory name (plural) as the type for now,
|
|
50
|
+
// OR map 'objects' -> 'object' specifically.
|
|
51
|
+
let registryType = type;
|
|
52
|
+
if (type === 'objects')
|
|
53
|
+
registryType = 'object';
|
|
54
|
+
if (type === 'apps')
|
|
55
|
+
registryType = 'app';
|
|
56
|
+
if (type === 'plugins')
|
|
57
|
+
registryType = 'plugin';
|
|
58
|
+
if (type === 'functions')
|
|
59
|
+
registryType = 'function';
|
|
60
|
+
ql.registry.registerItem(registryType, item, keyField);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
// Ignore missing directories or errors
|
|
67
|
+
// ctx.logger.debug(`No metadata found for type: ${type}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/metadata",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Metadata loading, saving, and persistence for ObjectStack",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"js-yaml": "^4.1.0",
|
|
17
17
|
"chokidar": "^3.5.3",
|
|
18
18
|
"zod": "^4.3.6",
|
|
19
|
-
"@objectstack/core": "0.
|
|
20
|
-
"@objectstack/spec": "0.
|
|
21
|
-
"@objectstack/types": "0.
|
|
19
|
+
"@objectstack/core": "0.9.0",
|
|
20
|
+
"@objectstack/spec": "0.9.0",
|
|
21
|
+
"@objectstack/types": "0.9.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/js-yaml": "^4.0.9",
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
// Main Manager
|
|
8
8
|
export { MetadataManager, type WatchCallback } from './metadata-manager.js';
|
|
9
9
|
|
|
10
|
+
// Plugin
|
|
11
|
+
export { MetadataPlugin } from './plugin.js';
|
|
12
|
+
|
|
10
13
|
// Loaders
|
|
11
14
|
export { type MetadataLoader } from './loaders/loader-interface.js';
|
|
12
15
|
export { FilesystemLoader } from './loaders/filesystem-loader.js';
|
|
@@ -15,6 +18,7 @@ export { FilesystemLoader } from './loaders/filesystem-loader.js';
|
|
|
15
18
|
export { type MetadataSerializer, type SerializeOptions } from './serializers/serializer-interface.js';
|
|
16
19
|
export { JSONSerializer } from './serializers/json-serializer.js';
|
|
17
20
|
export { YAMLSerializer } from './serializers/yaml-serializer.js';
|
|
21
|
+
export * as Migration from './migration/index.js';
|
|
18
22
|
export { TypeScriptSerializer } from './serializers/typescript-serializer.js';
|
|
19
23
|
|
|
20
24
|
// Re-export types from spec
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { System } from '@objectstack/spec';
|
|
2
|
+
import { ISchemaDriver } from '@objectstack/spec/contracts';
|
|
3
|
+
|
|
4
|
+
export class MigrationExecutor {
|
|
5
|
+
constructor(private driver: ISchemaDriver) {}
|
|
6
|
+
|
|
7
|
+
async executeChangeSet(changeSet: System.ChangeSet): Promise<void> {
|
|
8
|
+
console.log(`Executing ChangeSet: ${changeSet.name} (${changeSet.id})`);
|
|
9
|
+
|
|
10
|
+
for (const op of changeSet.operations) {
|
|
11
|
+
try {
|
|
12
|
+
await this.executeOperation(op);
|
|
13
|
+
} catch (e) {
|
|
14
|
+
console.error(`Failed to execute operation ${op.type}:`, e);
|
|
15
|
+
throw e;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private async executeOperation(op: System.MigrationOperation): Promise<void> {
|
|
21
|
+
switch (op.type) {
|
|
22
|
+
case 'create_object':
|
|
23
|
+
console.log(` > Create Object: ${op.object.name}`);
|
|
24
|
+
await this.driver.createCollection(op.object.name, op.object);
|
|
25
|
+
break;
|
|
26
|
+
case 'add_field':
|
|
27
|
+
console.log(` > Add Field: ${op.objectName}.${op.fieldName}`);
|
|
28
|
+
await this.driver.addColumn(op.objectName, op.fieldName, op.field);
|
|
29
|
+
break;
|
|
30
|
+
case 'remove_field':
|
|
31
|
+
console.log(` > Remove Field: ${op.objectName}.${op.fieldName}`);
|
|
32
|
+
await this.driver.dropColumn(op.objectName, op.fieldName);
|
|
33
|
+
break;
|
|
34
|
+
case 'delete_object':
|
|
35
|
+
console.log(` > Delete Object: ${op.objectName}`);
|
|
36
|
+
await this.driver.dropCollection(op.objectName);
|
|
37
|
+
break;
|
|
38
|
+
case 'execute_sql':
|
|
39
|
+
console.log(` > Execute SQL`);
|
|
40
|
+
await this.driver.executeRaw(op.sql);
|
|
41
|
+
break;
|
|
42
|
+
case 'modify_field':
|
|
43
|
+
console.warn(` ! Modify Field: ${op.objectName}.${op.fieldName} (Not fully implemented)`);
|
|
44
|
+
break;
|
|
45
|
+
case 'rename_object':
|
|
46
|
+
console.warn(` ! Rename Object: ${op.oldName} -> ${op.newName} (Not fully implemented)`);
|
|
47
|
+
break;
|
|
48
|
+
default:
|
|
49
|
+
throw new Error(`Unknown operation type`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './executor.js';
|
package/src/plugin.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Plugin, PluginContext } from '@objectstack/core';
|
|
2
|
+
import { MetadataManager } from './metadata-manager.js';
|
|
3
|
+
import { ObjectStackDefinitionSchema } from '@objectstack/spec';
|
|
4
|
+
|
|
5
|
+
export interface MetadataPluginOptions {
|
|
6
|
+
rootDir?: string;
|
|
7
|
+
watch?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class MetadataPlugin implements Plugin {
|
|
11
|
+
name = 'com.objectstack.metadata';
|
|
12
|
+
version = '1.0.0';
|
|
13
|
+
|
|
14
|
+
private manager: MetadataManager;
|
|
15
|
+
private options: MetadataPluginOptions;
|
|
16
|
+
|
|
17
|
+
constructor(options: MetadataPluginOptions = {}) {
|
|
18
|
+
this.options = {
|
|
19
|
+
watch: true,
|
|
20
|
+
...options
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const rootDir = this.options.rootDir || process.cwd();
|
|
24
|
+
|
|
25
|
+
this.manager = new MetadataManager({
|
|
26
|
+
rootDir,
|
|
27
|
+
watch: this.options.watch ?? true,
|
|
28
|
+
formats: ['yaml', 'json', 'typescript', 'javascript']
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async init(ctx: PluginContext) {
|
|
33
|
+
ctx.logger.info('Initializing Metadata Manager', { root: this.options.rootDir || process.cwd() });
|
|
34
|
+
|
|
35
|
+
// Register Metadata Manager as a service
|
|
36
|
+
// This allows other plugins to query raw metadata or listen to changes
|
|
37
|
+
ctx.registerService('metadata', this.manager);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async start(ctx: PluginContext) {
|
|
41
|
+
ctx.logger.info('Loading metadata...');
|
|
42
|
+
|
|
43
|
+
// Define metadata types directly from the Protocol Definition
|
|
44
|
+
// This ensures the loader is always in sync with the Spec
|
|
45
|
+
const metadataTypes = Object.keys(ObjectStackDefinitionSchema.shape)
|
|
46
|
+
.filter(key => key !== 'manifest'); // Manifest is handled separately
|
|
47
|
+
|
|
48
|
+
for (const type of metadataTypes) {
|
|
49
|
+
try {
|
|
50
|
+
// Try to load metadata of this type
|
|
51
|
+
const items = await this.manager.loadMany(type, {
|
|
52
|
+
recursive: true
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
if (items.length > 0) {
|
|
56
|
+
ctx.logger.info(`Loaded ${items.length} ${type}`);
|
|
57
|
+
|
|
58
|
+
// Helper: Register with ObjectQL Registry
|
|
59
|
+
const ql = ctx.getService('objectql') as any;
|
|
60
|
+
if (ql && ql.registry) {
|
|
61
|
+
items.forEach((item: any) => {
|
|
62
|
+
// Determine key field (id or name)
|
|
63
|
+
const keyField = item.id ? 'id' : 'name';
|
|
64
|
+
|
|
65
|
+
// Map plural type to singular/registry type if needed
|
|
66
|
+
// For now, we use the singular form for standard types:
|
|
67
|
+
// objects -> object, apps -> app, etc.
|
|
68
|
+
// But Registry seems to accept arbitrary strings.
|
|
69
|
+
// To match Protocol standard, we might want to normalize.
|
|
70
|
+
// Let's use the directory name (plural) as the type for now,
|
|
71
|
+
// OR map 'objects' -> 'object' specifically.
|
|
72
|
+
|
|
73
|
+
let registryType = type;
|
|
74
|
+
if (type === 'objects') registryType = 'object';
|
|
75
|
+
if (type === 'apps') registryType = 'app';
|
|
76
|
+
if (type === 'plugins') registryType = 'plugin';
|
|
77
|
+
if (type === 'functions') registryType = 'function';
|
|
78
|
+
|
|
79
|
+
ql.registry.registerItem(registryType, item, keyField);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} catch (e: any) {
|
|
84
|
+
// Ignore missing directories or errors
|
|
85
|
+
// ctx.logger.debug(`No metadata found for type: ${type}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|