@objectstack/runtime 3.2.2 → 3.2.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectstack/runtime",
3
- "version": "3.2.2",
3
+ "version": "3.2.4",
4
4
  "license": "Apache-2.0",
5
5
  "description": "ObjectStack Core Runtime & Query Engine",
6
6
  "type": "module",
@@ -15,10 +15,10 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "zod": "^4.3.6",
18
- "@objectstack/core": "3.2.2",
19
- "@objectstack/rest": "3.2.2",
20
- "@objectstack/spec": "3.2.2",
21
- "@objectstack/types": "3.2.2"
18
+ "@objectstack/core": "3.2.4",
19
+ "@objectstack/rest": "3.2.4",
20
+ "@objectstack/spec": "3.2.4",
21
+ "@objectstack/types": "3.2.4"
22
22
  },
23
23
  "devDependencies": {
24
24
  "typescript": "^5.0.0",
package/src/app-plugin.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
2
 
3
3
  import { Plugin, PluginContext } from '@objectstack/core';
4
+ import { SeedLoaderService } from './seed-loader.js';
5
+ import type { IMetadataService } from '@objectstack/spec/contracts';
4
6
 
5
7
  /**
6
8
  * AppPlugin
@@ -127,24 +129,60 @@ export class AppPlugin implements Plugin {
127
129
 
128
130
  if (seedDatasets.length > 0) {
129
131
  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) {
134
176
  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
+ }
144
182
  }
145
183
  }
184
+ ctx.logger.info('[Seeder] Data seeding complete (fallback).');
146
185
  }
147
- ctx.logger.info('[Seeder] Data seeding complete.');
148
186
  }
149
187
  }
150
188
  }
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ export type { RuntimeConfig } from './runtime.js';
10
10
  // Export Plugins
11
11
  export { DriverPlugin } from './driver-plugin.js';
12
12
  export { AppPlugin } from './app-plugin.js';
13
+ export { SeedLoaderService } from './seed-loader.js';
13
14
  export { createDispatcherPlugin } from './dispatcher-plugin.js';
14
15
  export type { DispatcherPluginConfig } from './dispatcher-plugin.js';
15
16