Skip to content

Commit 5a1f7df

Browse files
authored
Merge pull request #875 from objectstack-ai/copilot/support-dynamic-relationship-resolution
2 parents c23df16 + 8f64292 commit 5a1f7df

10 files changed

Lines changed: 3098 additions & 14 deletions

File tree

packages/runtime/src/app-plugin.ts

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
22

33
import { Plugin, PluginContext } from '@objectstack/core';
4+
import { SeedLoaderService } from './seed-loader.js';
5+
import type { IMetadataService } from '@objectstack/spec/contracts';
46

57
/**
68
* AppPlugin
@@ -127,24 +129,60 @@ export class AppPlugin implements Plugin {
127129

128130
if (seedDatasets.length > 0) {
129131
ctx.logger.info(`[AppPlugin] Found ${seedDatasets.length} seed datasets for ${appId}`);
130-
for (const dataset of seedDatasets) {
131-
if (dataset.object && Array.isArray(dataset.records)) {
132-
const objectFQN = toFQN(dataset.object);
133-
ctx.logger.info(`[Seeder] Seeding ${dataset.records.length} records for ${objectFQN}`);
132+
133+
// Normalize dataset object names to FQN
134+
const normalizedDatasets = seedDatasets
135+
.filter((d: any) => d.object && Array.isArray(d.records))
136+
.map((d: any) => ({
137+
...d,
138+
object: toFQN(d.object),
139+
}));
140+
141+
// Use SeedLoaderService for metadata-driven loading with reference resolution
142+
try {
143+
const metadata = ctx.getService('metadata') as IMetadataService | undefined;
144+
if (metadata) {
145+
const seedLoader = new SeedLoaderService(ql, metadata, ctx.logger);
146+
const { SeedLoaderRequestSchema } = await import('@objectstack/spec/data');
147+
const request = SeedLoaderRequestSchema.parse({
148+
datasets: normalizedDatasets,
149+
config: { defaultMode: 'upsert', multiPass: true },
150+
});
151+
const result = await seedLoader.load(request);
152+
ctx.logger.info('[Seeder] Seed loading complete', {
153+
inserted: result.summary.totalInserted,
154+
updated: result.summary.totalUpdated,
155+
errors: result.errors.length,
156+
});
157+
} else {
158+
// Fallback: basic insert when metadata service is not available
159+
ctx.logger.debug('[Seeder] No metadata service; using basic insert fallback');
160+
for (const dataset of normalizedDatasets) {
161+
ctx.logger.info(`[Seeder] Seeding ${dataset.records.length} records for ${dataset.object}`);
162+
for (const record of dataset.records) {
163+
try {
164+
await ql.insert(dataset.object, record);
165+
} catch (err: any) {
166+
ctx.logger.warn(`[Seeder] Failed to insert ${dataset.object} record:`, { error: err.message });
167+
}
168+
}
169+
}
170+
ctx.logger.info('[Seeder] Data seeding complete.');
171+
}
172+
} catch (err: any) {
173+
// If SeedLoaderService fails (e.g., metadata not available), fall back to basic insert
174+
ctx.logger.warn('[Seeder] SeedLoaderService failed, falling back to basic insert', { error: err.message });
175+
for (const dataset of normalizedDatasets) {
134176
for (const record of dataset.records) {
135-
try {
136-
// Use ObjectQL engine to insert data
137-
// This ensures driver resolution and hook execution
138-
// Use 'insert' which corresponds to 'create' in driver
139-
await ql.insert(objectFQN, record);
140-
} catch (err: any) {
141-
// Ignore duplicate errors if needed, or log/warn
142-
ctx.logger.warn(`[Seeder] Failed to insert ${objectFQN} record:`, { error: err.message });
143-
}
177+
try {
178+
await ql.insert(dataset.object, record);
179+
} catch (insertErr: any) {
180+
ctx.logger.warn(`[Seeder] Failed to insert ${dataset.object} record:`, { error: insertErr.message });
181+
}
144182
}
145183
}
184+
ctx.logger.info('[Seeder] Data seeding complete (fallback).');
146185
}
147-
ctx.logger.info('[Seeder] Data seeding complete.');
148186
}
149187
}
150188
}

packages/runtime/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export type { RuntimeConfig } from './runtime.js';
1010
// Export Plugins
1111
export { DriverPlugin } from './driver-plugin.js';
1212
export { AppPlugin } from './app-plugin.js';
13+
export { SeedLoaderService } from './seed-loader.js';
1314
export { createDispatcherPlugin } from './dispatcher-plugin.js';
1415
export type { DispatcherPluginConfig } from './dispatcher-plugin.js';
1516

0 commit comments

Comments
 (0)