@lunora/seed 1.0.0-alpha.21 → 1.0.0-alpha.23

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
@@ -1,2 +1,2 @@
1
- export { createSeedClient } from './packem_shared/createSeedClient-CdcRtjwk.mjs';
2
- export { s as seedPlan } from './packem_shared/plan-mBVbPKKd.mjs';
1
+ export { createSeedClient } from './packem_shared/createSeedClient-CZuGqXLm.mjs';
2
+ export { s as seedPlan } from './packem_shared/plan-DybYaa3F.mjs';
@@ -1,4 +1,4 @@
1
- import { a as setHashKey, s as seedPlan, c as copycat } from './plan-mBVbPKKd.mjs';
1
+ import { a as setHashKey, s as seedPlan, c as copycat } from './plan-DybYaa3F.mjs';
2
2
 
3
3
  const isRange = (spec) => Array.isArray(spec) && spec.length === 2 && typeof spec[0] === "number" && typeof spec[1] === "number";
4
4
  const resolveSpec = (spec, table, seed, defaultCount) => {
@@ -35,7 +35,7 @@ const createSeedClient = (schema, options = {}) => {
35
35
  const store = {};
36
36
  const idsByTable = {};
37
37
  const createdCount = {};
38
- const seedTable = async (table, spec, callOptions) => {
38
+ const runSeedTable = async (table, spec, callOptions) => {
39
39
  setHashKey(seed);
40
40
  const { count, partials } = resolveSpec(spec, table, seed, defaultCount);
41
41
  const offset = createdCount[table] ?? 0;
@@ -64,6 +64,15 @@ const createSeedClient = (schema, options = {}) => {
64
64
  }
65
65
  return { [table]: created };
66
66
  };
67
+ let queue = Promise.resolve();
68
+ const seedTable = (table, spec, callOptions) => {
69
+ const result = queue.then(() => runSeedTable(table, spec, callOptions));
70
+ queue = result.then(
71
+ () => void 0,
72
+ () => void 0
73
+ );
74
+ return result;
75
+ };
67
76
  const state = {
68
77
  $ids: idsByTable,
69
78
  $reset: () => {
@@ -1,5 +1,5 @@
1
- import { faker } from '@faker-js/faker';
2
1
  import { LunoraError } from '@lunora/errors';
2
+ import { faker } from '@faker-js/faker';
3
3
  import { optionalInner } from '@lunora/values';
4
4
 
5
5
  let hashSalt = 0;
@@ -289,7 +289,7 @@ const orderTables = (specs, selected) => {
289
289
  }
290
290
  return ordered;
291
291
  };
292
- const fkParentClosure = (specs, roots) => {
292
+ const fkParentClosure = (specs, roots, stopAt = /* @__PURE__ */ new Set()) => {
293
293
  const byName = new Map(specs.map((spec) => [spec.name, spec]));
294
294
  const result = new Set(roots);
295
295
  const stack = [...result];
@@ -302,6 +302,9 @@ const fkParentClosure = (specs, roots) => {
302
302
  if (spec === void 0) {
303
303
  continue;
304
304
  }
305
+ if (stopAt.has(name)) {
306
+ continue;
307
+ }
305
308
  for (const field of spec.fields) {
306
309
  if (field.fkTable !== void 0 && field.fkTable !== name && byName.has(field.fkTable) && !result.has(field.fkTable)) {
307
310
  result.add(field.fkTable);
@@ -386,16 +389,28 @@ const generateValue = (validator, fieldName, input) => {
386
389
  return null;
387
390
  }
388
391
  case "number": {
389
- return copycat.int(input, { max: constraints.maximum ?? 1e3, min: constraints.minimum ?? 0 });
392
+ const { maximum, minimum } = constraints;
393
+ if (maximum !== void 0 && minimum !== void 0 && minimum > maximum) {
394
+ throw new LunoraError(
395
+ "INTERNAL",
396
+ `Seed constraint error for field "${fieldName}": minimum (${String(minimum)}) > maximum (${String(maximum)}). Adjust the schema constraints.`
397
+ );
398
+ }
399
+ const min = minimum ?? 0;
400
+ const max = maximum ?? 1e3;
401
+ if (!Number.isInteger(min) || !Number.isInteger(max)) {
402
+ return copycat.float(input, { max, min });
403
+ }
404
+ return copycat.int(input, { max, min });
390
405
  }
391
406
  case "object": {
392
407
  const shape = metaOf(inner).shape ?? {};
393
408
  return Object.fromEntries(Object.entries(shape).map(([key, child]) => [key, generateValue(child, key, [input, key])]));
394
409
  }
395
410
  case "record": {
396
- const { valueValidator } = metaOf(inner);
411
+ const { keyValidator, valueValidator } = metaOf(inner);
397
412
  const entries = copycat.times(input, [1, 3], (itemInput) => {
398
- const key = copycat.word(["k", itemInput]);
413
+ const key = keyValidator === void 0 ? copycat.word(["k", itemInput]) : String(generateValue(keyValidator, fieldName, ["k", itemInput]));
399
414
  const value = valueValidator === void 0 ? copycat.word(["v", itemInput]) : generateValue(valueValidator, fieldName, ["v", itemInput]);
400
415
  return [key, value];
401
416
  });
@@ -449,8 +464,20 @@ const seedPlan = (schema, options = {}) => {
449
464
  const { counts = {}, defaultCount = 10, existingIds = {}, indexOffset = {}, only, overrides = {}, seed = 0 } = options;
450
465
  setHashKey(seed);
451
466
  const specs = introspectSchema(schema);
467
+ if (only !== void 0) {
468
+ const known = new Set(specs.map((spec) => spec.name));
469
+ for (const name of only) {
470
+ if (!known.has(name)) {
471
+ const available = specs.map((spec) => spec.name).join(", ");
472
+ throw new LunoraError("BAD_REQUEST", `unknown table "${name}" in seed \`only\` — schema defines: ${available || "(no tables)"}`);
473
+ }
474
+ }
475
+ }
452
476
  const requested = new Set(only ?? specs.map((spec) => spec.name));
453
- const selected = new Set([...fkParentClosure(specs, requested)].filter((table) => requested.has(table) || (existingIds[table] ?? []).length === 0));
477
+ const covered = new Set(Object.keys(existingIds).filter((table) => !requested.has(table) && (existingIds[table] ?? []).length > 0));
478
+ const selected = new Set(
479
+ [...fkParentClosure(specs, requested, covered)].filter((table) => requested.has(table) || (existingIds[table] ?? []).length === 0)
480
+ );
454
481
  const order = orderTables(specs, selected);
455
482
  const specByName = new Map(specs.map((spec) => [spec.name, spec]));
456
483
  const idsByTable = /* @__PURE__ */ new Map();
@@ -0,0 +1,2 @@
1
+ import '@lunora/errors';
2
+ export { s as seedPlan } from './plan-DybYaa3F.mjs';
package/dist/testing.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { s as seedPlan, i as introspectSchema } from './packem_shared/plan-mBVbPKKd.mjs';
1
+ import { s as seedPlan, i as introspectSchema } from './packem_shared/plan-DybYaa3F.mjs';
2
2
 
3
3
  const reviveRow = (row, bigintFields, bytesFields) => {
4
4
  if (bigintFields.size === 0 && bytesFields.size === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/seed",
3
- "version": "1.0.0-alpha.21",
3
+ "version": "1.0.0-alpha.23",
4
4
  "description": "Schema-driven, deterministic database seeding for Lunora: realistic fake data from defineSchema",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -48,11 +48,11 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "@faker-js/faker": "^10.5.0",
51
- "@lunora/errors": "1.0.0-alpha.3"
51
+ "@lunora/errors": "1.0.0-alpha.4"
52
52
  },
53
53
  "peerDependencies": {
54
- "@lunora/server": "1.0.0-alpha.22",
55
- "@lunora/values": "1.0.0-alpha.6"
54
+ "@lunora/server": "1.0.0-alpha.24",
55
+ "@lunora/values": "1.0.0-alpha.7"
56
56
  },
57
57
  "engines": {
58
58
  "node": "^22.15.0 || >=24.11.0"
@@ -1 +0,0 @@
1
- export { s as seedPlan } from './plan-mBVbPKKd.mjs';