@farm.js/sync 0.1.0-beta.5 → 0.1.0-beta.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAsB,MAAM,aAAa,CAAC;AAC3F,OAAO,EACL,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EAErB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,wEAAwE;IACxE,MAAM,EAAE,UAAU,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,+DAA+D;IAC/D,KAAK,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IAC1B,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACzC,kEAAkE;IAClE,UAAU,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACvC,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,CAC3B,GAAG,EAAE,qBAAqB,KACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AAE9E,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EACV,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAIpB,wBAAgB,IAAI,CAAC,OAAO,EAAE,iBAAiB;;;;;;;;;;;yDAgJ9C;AAqMD,mCAAmC;AACnC,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,CAAC;AACvE,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAsB,MAAM,aAAa,CAAC;AAC3F,OAAO,EACL,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EAErB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,wEAAwE;IACxE,MAAM,EAAE,UAAU,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,+DAA+D;IAC/D,KAAK,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IAC1B,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACzC,kEAAkE;IAClE,UAAU,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACvC,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,CAC3B,GAAG,EAAE,qBAAqB,KACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AAE9E,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EACV,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAIpB,wBAAgB,IAAI,CAAC,OAAO,EAAE,iBAAiB;;;;;;;;;;;yDAmI9C;AAsOD,mCAAmC;AACnC,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,CAAC;AACvE,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { declareSchemaTables, definePlugin, describeIntegrationOriginRejection, resolveIntegrationAllowedOrigins, validateIntegrationRequestOrigin, } from "@farm.js/core";
1
+ import { definePlugin, describeIntegrationOriginRejection, resolveIntegrationAllowedOrigins, validateIntegrationRequestOrigin, } from "@farm.js/core";
2
2
  import { executeSyncOperation, SyncOperationError } from "./server.js";
3
3
  import { resolveSyncModels, } from "./types.js";
4
4
  const DEFAULT_PATH = "/_farm/sync";
@@ -18,8 +18,17 @@ export function sync(options) {
18
18
  ormPromise ??= resolveSyncClient(options, models);
19
19
  return ormPromise;
20
20
  };
21
- const plugin = definePlugin({
21
+ return definePlugin({
22
22
  name: "farm:sync",
23
+ // `farm sync migrate` creates the tables of the models the app exposed.
24
+ // The rest of the app's schema is described, not created: those tables
25
+ // are the app's.
26
+ schema: syncOwnedSchema(options.schema, models),
27
+ // The database the app gave sync, not storage.client.
28
+ database: {
29
+ client: () => resolveSyncConnection(options),
30
+ dialect: options.dialect,
31
+ },
23
32
  client: {
24
33
  // Serializable descriptor the browser runtime reads at startup.
25
34
  public: {
@@ -96,27 +105,6 @@ export function sync(options) {
96
105
  await sendNodeResponse(res, response);
97
106
  },
98
107
  });
99
- // Declare the tables sync owns, so `farm sync migrate` can create them
100
- // without re-reading or re-validating configuration.
101
- return declareSchemaTables(plugin, {
102
- name: "sync",
103
- schema: options.schema,
104
- // A model the app has not opened to the browser is not sync's to create.
105
- models: Array.from(models.keys()),
106
- dialect: options.dialect,
107
- resolveClient: async () => {
108
- if (options.client) {
109
- return typeof options.client === "function"
110
- ? await options.client()
111
- : options.client;
112
- }
113
- if (options.storage) {
114
- const { getStorage } = await import("@farm.js/core/storage");
115
- return getStorage(options.storage);
116
- }
117
- return undefined;
118
- },
119
- });
120
108
  }
121
109
  async function handleSyncRequest(request, bodyOverride, options) {
122
110
  const pathname = new URL(request.url).pathname;
@@ -210,28 +198,59 @@ async function runMiddleware(middleware, request) {
210
198
  }
211
199
  return context;
212
200
  }
213
- async function resolveSyncClient(options, models) {
201
+ /**
202
+ * The app's schema as sync owns it: exposed models are sync's tables, the rest
203
+ * are described but never created. `extend` is folded into the models first,
204
+ * so the app composing its own schema is never read as sync asking to add
205
+ * columns to the app's tables.
206
+ */
207
+ function syncOwnedSchema(schema, exposed) {
208
+ const models = { ...schema.models };
209
+ for (const [key, extension] of Object.entries(schema.extend ?? {})) {
210
+ const existing = models[key];
211
+ models[key] = {
212
+ ...(existing ?? { fields: {} }),
213
+ ...(extension.name ? { name: extension.name } : {}),
214
+ ...(extension.description ? { description: extension.description } : {}),
215
+ fields: { ...existing?.fields, ...extension.fields },
216
+ constraints: [...(existing?.constraints ?? []), ...(extension.constraints ?? [])],
217
+ meta: { ...existing?.meta, ...extension.meta },
218
+ };
219
+ }
220
+ return {
221
+ ...schema,
222
+ extend: undefined,
223
+ models: Object.fromEntries(Object.entries(models).map(([key, model]) => [
224
+ key,
225
+ { ...model, external: !exposed.has(key) },
226
+ ])),
227
+ };
228
+ }
229
+ /** The connection or storage mount the app gave sync. */
230
+ async function resolveSyncConnection(options) {
214
231
  if (options.client) {
215
- const provided = typeof options.client === "function"
232
+ return typeof options.client === "function"
216
233
  ? await options.client()
217
234
  : options.client;
218
- // Already model-shaped: an @farming-labs/orm client, or anything exposing
219
- // the same four methods. Use it directly.
220
- if (isModelClient(provided, models))
221
- return provided;
222
- return buildOrm(options.schema, provided);
223
235
  }
224
236
  if (options.storage) {
225
- const mount = options.storage;
226
237
  // Imported lazily so the storage runtime never reaches a browser bundle.
227
238
  const { getStorage } = await import("@farm.js/core/storage");
228
239
  // A mount is an unstorage instance, which the orm runtime drives like any
229
240
  // other backend — so this is the same code path as a real database.
230
- return buildOrm(options.schema, getStorage(mount));
241
+ return getStorage(options.storage);
231
242
  }
232
243
  throw new Error("sync(): no data source is configured. Set `storage` to a mount name from " +
233
244
  "storage.mounts in farm.config.ts, or pass `client` with your database connection.");
234
245
  }
246
+ async function resolveSyncClient(options, models) {
247
+ const provided = await resolveSyncConnection(options);
248
+ // Already model-shaped: an @farming-labs/orm client, or anything exposing
249
+ // the same four methods. Use it directly.
250
+ if (options.client && isModelClient(provided, models))
251
+ return provided;
252
+ return buildOrm(options.schema, provided);
253
+ }
235
254
  /** Let the orm runtime detect the driver and build the model client. */
236
255
  async function buildOrm(schema, client) {
237
256
  const { createIntegrationOrm } = await import("@farm.js/core");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farm.js/sync",
3
- "version": "0.1.0-beta.5",
3
+ "version": "0.1.0-beta.6",
4
4
  "description": "Local-first collections for Farm.js: schema-driven reads, optimistic writes, offline queueing",
5
5
  "keywords": [
6
6
  "farm.js",
@@ -40,7 +40,7 @@
40
40
  "access": "public"
41
41
  },
42
42
  "dependencies": {
43
- "@farm.js/core": "0.1.0"
43
+ "@farm.js/core": "0.1.1"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@farming-labs/orm": "0.0.62",