@objectstack/objectql 3.2.9 → 3.3.1

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/index.mjs CHANGED
@@ -167,8 +167,14 @@ var SchemaRegistry = class {
167
167
  return merged;
168
168
  }
169
169
  /**
170
- * Get object by name (FQN or short name with fallback scan).
171
- * For compatibility, tries exact match first, then scans for suffix match.
170
+ * Get object by name (FQN, short name, or physical table name).
171
+ *
172
+ * Resolution order:
173
+ * 1. Exact FQN match (e.g., 'crm__account')
174
+ * 2. Short name fallback (e.g., 'account' → 'crm__account')
175
+ * 3. Physical table name match (e.g., 'sys_user' → 'sys__user')
176
+ * ObjectSchema.create() auto-derives tableName as {namespace}_{name},
177
+ * which uses a single underscore — different from the FQN double underscore.
172
178
  */
173
179
  static getObject(name) {
174
180
  const direct = this.resolveObject(name);
@@ -179,6 +185,12 @@ var SchemaRegistry = class {
179
185
  return this.resolveObject(fqn);
180
186
  }
181
187
  }
188
+ for (const fqn of this.objectContributors.keys()) {
189
+ const resolved = this.resolveObject(fqn);
190
+ if (resolved?.tableName === name) {
191
+ return resolved;
192
+ }
193
+ }
182
194
  return void 0;
183
195
  }
184
196
  /**
@@ -1720,7 +1732,7 @@ var _ObjectQL = class _ObjectQL {
1720
1732
  resolveObjectName(name) {
1721
1733
  const schema = SchemaRegistry.getObject(name);
1722
1734
  if (schema) {
1723
- return schema.name;
1735
+ return schema.tableName || schema.name;
1724
1736
  }
1725
1737
  return name;
1726
1738
  }
@@ -2718,9 +2730,13 @@ var ObjectQLPlugin = class {
2718
2730
  /**
2719
2731
  * Synchronize all registered object schemas to the database.
2720
2732
  *
2721
- * Iterates every object in the SchemaRegistry and calls the
2722
- * responsible driver's `syncSchema()` for each one. This is
2723
- * idempotent drivers must tolerate repeated calls without
2733
+ * Groups objects by their responsible driver, then:
2734
+ * - If the driver advertises `supports.batchSchemaSync` and implements
2735
+ * `syncSchemasBatch()`, submits all schemas in a single call (reducing
2736
+ * network round-trips for remote drivers like Turso).
2737
+ * - Otherwise falls back to sequential `syncSchema()` per object.
2738
+ *
2739
+ * This is idempotent — drivers must tolerate repeated calls without
2724
2740
  * duplicating tables or erroring out.
2725
2741
  *
2726
2742
  * Drivers that do not implement `syncSchema` are silently skipped.
@@ -2731,6 +2747,7 @@ var ObjectQLPlugin = class {
2731
2747
  if (allObjects.length === 0) return;
2732
2748
  let synced = 0;
2733
2749
  let skipped = 0;
2750
+ const driverGroups = /* @__PURE__ */ new Map();
2734
2751
  for (const obj of allObjects) {
2735
2752
  const driver = this.ql.getDriverForObject(obj.name);
2736
2753
  if (!driver) {
@@ -2748,15 +2765,60 @@ var ObjectQLPlugin = class {
2748
2765
  skipped++;
2749
2766
  continue;
2750
2767
  }
2751
- try {
2752
- await driver.syncSchema(obj.name, obj);
2753
- synced++;
2754
- } catch (e) {
2755
- ctx.logger.warn("Failed to sync schema for object", {
2756
- object: obj.name,
2757
- driver: driver.name,
2758
- error: e instanceof Error ? e.message : String(e)
2759
- });
2768
+ const tableName = obj.tableName || obj.name;
2769
+ let group = driverGroups.get(driver);
2770
+ if (!group) {
2771
+ group = [];
2772
+ driverGroups.set(driver, group);
2773
+ }
2774
+ group.push({ obj, tableName });
2775
+ }
2776
+ for (const [driver, entries] of driverGroups) {
2777
+ if (driver.supports?.batchSchemaSync && typeof driver.syncSchemasBatch === "function") {
2778
+ const batchPayload = entries.map((e) => ({
2779
+ object: e.tableName,
2780
+ schema: e.obj
2781
+ }));
2782
+ try {
2783
+ await driver.syncSchemasBatch(batchPayload);
2784
+ synced += entries.length;
2785
+ ctx.logger.debug("Batch schema sync succeeded", {
2786
+ driver: driver.name,
2787
+ count: entries.length
2788
+ });
2789
+ } catch (e) {
2790
+ ctx.logger.warn("Batch schema sync failed, falling back to sequential", {
2791
+ driver: driver.name,
2792
+ error: e instanceof Error ? e.message : String(e)
2793
+ });
2794
+ for (const { obj, tableName } of entries) {
2795
+ try {
2796
+ await driver.syncSchema(tableName, obj);
2797
+ synced++;
2798
+ } catch (seqErr) {
2799
+ ctx.logger.warn("Failed to sync schema for object", {
2800
+ object: obj.name,
2801
+ tableName,
2802
+ driver: driver.name,
2803
+ error: seqErr instanceof Error ? seqErr.message : String(seqErr)
2804
+ });
2805
+ }
2806
+ }
2807
+ }
2808
+ } else {
2809
+ for (const { obj, tableName } of entries) {
2810
+ try {
2811
+ await driver.syncSchema(tableName, obj);
2812
+ synced++;
2813
+ } catch (e) {
2814
+ ctx.logger.warn("Failed to sync schema for object", {
2815
+ object: obj.name,
2816
+ tableName,
2817
+ driver: driver.name,
2818
+ error: e instanceof Error ? e.message : String(e)
2819
+ });
2820
+ }
2821
+ }
2760
2822
  }
2761
2823
  }
2762
2824
  if (synced > 0 || skipped > 0) {