@baseplate-dev/plugin-auth 0.6.13 → 0.6.15

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/auth/core/components/auth-definition-editor.js +3 -0
  3. package/dist/auth/core/components/role-editor-form/role-editor-form.js +2 -0
  4. package/dist/better-auth/generators/fastify/seed-initial-user/seed-initial-user.generator.js +4 -0
  5. package/dist/better-auth/generators/fastify/seed-initial-user/templates/src/prisma/seed-initial-user.ts +3 -2
  6. package/dist/local-auth/core/generators/auth-email-password/templates/module/services/user-password.service.js +2 -2
  7. package/dist/local-auth/core/generators/auth-email-password/templates/module/services/user-password.service.ts +2 -5
  8. package/dist/local-auth/core/generators/auth-module/auth-module.generator.d.ts +7 -0
  9. package/dist/local-auth/core/generators/auth-module/generated/index.d.ts +21 -0
  10. package/dist/local-auth/core/generators/auth-module/generated/template-renderers.d.ts +7 -0
  11. package/dist/local-auth/core/generators/auth-module/generated/typed-templates.d.ts +14 -0
  12. package/dist/local-auth/core/generators/seed-initial-user/seed-initial-user.generator.js +4 -0
  13. package/dist/local-auth/core/generators/seed-initial-user/templates/src/prisma/seed-initial-user.js +2 -1
  14. package/dist/local-auth/core/generators/seed-initial-user/templates/src/prisma/seed-initial-user.ts +3 -1
  15. package/dist/web/assets/{_virtual_mf-localSharedImportMap___mfe_internal__plugin_mf_2_auth-DxRuC5lD.js → _virtual_mf-localSharedImportMap___mfe_internal__plugin_mf_2_auth-D2O_GHnM.js} +13 -13
  16. package/dist/web/assets/{_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib__loadShare__.js-Dbjihoi-.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib__loadShare__.js-DPxqayXr.js} +1 -1
  17. package/dist/web/assets/{_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib_mf_1_web__loadShare__.js-CpEOtTmq.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib_mf_1_web__loadShare__.js-DGL7vJhO.js} +1 -1
  18. package/dist/web/assets/{_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_ui_mf_2_components__loadShare__.js-BTSgZGcl.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_ui_mf_2_components__loadShare__.js-IL2CfUDN.js} +30 -26
  19. package/dist/web/assets/{_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_tanstack_mf_1_react_mf_2_router__loadShare__.js-CJ027_El.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_tanstack_mf_1_react_mf_2_router__loadShare__.js-olZgW088.js} +2 -2
  20. package/dist/web/assets/auth-BA-e6ORB.js +1 -0
  21. package/dist/web/assets/{common-B9sZoKR5.js → common-2qsch56z.js} +5 -5
  22. package/dist/web/assets/{common-B4cD6OfF.js → common-2sTWj7X2.js} +5 -5
  23. package/dist/web/assets/{common-DF9FD3lJ.js → common-BJslFOaI.js} +3 -3
  24. package/dist/web/assets/{common-B9LNVIXT.js → common-BY8yEk1M.js} +3 -3
  25. package/dist/web/assets/{common-S36tY-P3.js → common-D-CUPN3f.js} +2 -2
  26. package/dist/web/assets/{common-sMUs9FmV.js → common-DtVPzGI9.js} +2 -2
  27. package/dist/web/assets/{dist-CtqdAorB.js → dist-DiQ4J8N0.js} +291 -106
  28. package/dist/web/assets/{get-auth-plugin-definition-Bs9C6JrS.js → get-auth-plugin-definition-gCzcUybB.js} +2 -2
  29. package/dist/web/assets/{hostInit-BtfjN9sB.js → hostInit-BPDI3Q4j.js} +1 -1
  30. package/dist/web/assets/{index-DVCa_MuH.js → index-BocHdii2.js} +2 -2
  31. package/dist/web/assets/{mf-entry-bootstrap-0-31a63adb.js → mf-entry-bootstrap-0-b337c957.js} +2 -2
  32. package/dist/web/assets/{model-utils-BDM6ILfO.js → model-utils-BoeoBppL.js} +44 -3
  33. package/dist/web/assets/{models-DGhhwO8Q.js → models-Bb8Sa9xa.js} +2 -2
  34. package/dist/web/assets/{models-1c2urnle.js → models-CExR9mVk.js} +2 -2
  35. package/dist/web/assets/{plugin-definition-B-HRncfN.js → plugin-definition-BSgRuyCf.js} +2 -2
  36. package/dist/web/assets/{plugin-definition-Dluw2inU.js → plugin-definition-DoLu-enC.js} +2 -2
  37. package/dist/web/assets/{styles-BTmSBHAy.js → styles-DWNihayS.js} +5 -5
  38. package/dist/web/assets/{virtualExposes-C1o-SyCQ.js → virtualExposes-ZQ3-2Iup.js} +1 -1
  39. package/dist/web/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__plugin-auth__remoteEntry_js-Bs76by83.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__plugin-auth__remoteEntry_js-joyeTHHj.js} +3 -3
  40. package/dist/web/assets/{virtual_mf-exposes-ssr___mfe_internal__plugin-auth__remoteEntry_js-B5SkIaaz.js → virtual_mf-exposes-ssr___mfe_internal__plugin-auth__remoteEntry_js-Cxtxsg7w.js} +13 -13
  41. package/dist/web/assets/{virtual_mf-exposes___mfe_internal__plugin-auth__remoteEntry_js-DotA2McS.js → virtual_mf-exposes___mfe_internal__plugin-auth__remoteEntry_js-BzJkYZS3.js} +13 -13
  42. package/dist/web/assets/{web-wBaHshVG.js → web-BWF6Fc7g.js} +3 -3
  43. package/dist/web/assets/{web-CiuxQhgn.js → web-BbZNg5Ko.js} +7 -7
  44. package/dist/web/assets/{web-jcCkQISW.js → web-CbftiK5A.js} +3 -3
  45. package/dist/web/assets/{web-DGv5-Arz.js → web-DUQ-iyMI.js} +9 -7
  46. package/dist/web/assets/{web-Bh_3N1sv.js → web-QvGnMr85.js} +7 -7
  47. package/dist/web/assets/{web-B2REeIGU.js → web-pdVFZ-id.js} +3 -3
  48. package/dist/web/assets/{web-BEOhczx1.js → web-sVeHdqQo.js} +8 -8
  49. package/dist/web/index.html +2 -2
  50. package/dist/web/remoteEntry.js +1 -1
  51. package/dist/web/remoteEntry.ssr.js +1 -1
  52. package/package.json +14 -13
  53. package/dist/web/assets/auth-gRzmaSZc.js +0 -1
@@ -1,7 +1,7 @@
1
1
  import { t as __commonJSMin } from "./rolldown-runtime-FZ4Itg2g.js";
2
- import { q as stringifyPrettyStable } from "./_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_ui_mf_2_components__loadShare__.js-BTSgZGcl.js";
2
+ import { q as stringifyPrettyStable } from "./_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_ui_mf_2_components__loadShare__.js-IL2CfUDN.js";
3
3
  import { n as __mf_0, t as __mfDefaultExport } from "./_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare__zod__loadShare__.js-Do-7VDVw.js";
4
- import { $ as getTag, A as isPlainObject$1, B as int32ArrayTag, C as createPluginFieldMap, D as validationHintRegistry, E as CASE_VALIDATORS, F as dataViewTag, G as regexpTag, H as mapTag, I as dateTag, J as symbolTag, K as setTag, L as float32ArrayTag, M as arrayBufferTag, N as arrayTag, O as isEqual, P as booleanTag, Q as uint8ClampedArrayTag, R as float64ArrayTag, S as createFieldMapSpec, T as runInPluginContext, U as numberTag, V as int8ArrayTag, W as objectTag, X as uint32ArrayTag, Y as uint16ArrayTag, Z as uint8ArrayTag, _ as createRefContextSlot, a as featureEntityType, b as expressionParserSpec, c as createEntityType, d as definitionSchemaWithSlots, et as getSymbols, f as withPlaceholderSlots, g as withRef, h as withEnt, i as createFeaturesSchema, j as argumentsTag, k as isEqualsSameValueZero, l as createDefinitionSchemaParserContext, m as definitionDefaultRegistry, n as FeatureUtils, nt as createPluginSpec, o as featureNameSchema, p as withDefault, q as stringTag, r as createFeatureSchema, s as DefinitionEntityType, t as ModelUtils, tt as sortBy, u as definitionSchema, v as createRefContextSlotMap, w as getPluginContext, x as definitionRefRegistry, y as RefExpressionParser, z as int16ArrayTag } from "./model-utils-BDM6ILfO.js";
4
+ import { $ as getTag, A as isPlainObject$1, B as int32ArrayTag, C as createPluginFieldMap, D as validationHintRegistry, E as CASE_VALIDATORS, F as dataViewTag, G as regexpTag, H as mapTag, I as dateTag, J as symbolTag, K as setTag, L as float32ArrayTag, M as arrayBufferTag, N as arrayTag, O as isEqual, P as booleanTag, Q as uint8ClampedArrayTag, R as float64ArrayTag, S as createFieldMapSpec, T as runInPluginContext, U as numberTag, V as int8ArrayTag, W as objectTag, X as uint32ArrayTag, Y as uint16ArrayTag, Z as uint8ArrayTag, _ as createRefContextSlot, a as featureEntityType, b as expressionParserSpec, c as createEntityType, d as definitionSchemaWithSlots, et as getSymbols, f as withPlaceholderSlots, g as withRef, h as withEnt, i as createFeaturesSchema, j as argumentsTag, k as isEqualsSameValueZero, l as createDefinitionSchemaParserContext, m as definitionDefaultRegistry, n as FeatureUtils, nt as createPluginSpec, o as featureNameSchema, p as withDefault, q as stringTag, r as createFeatureSchema, s as DefinitionEntityType, t as ModelUtils, tt as sortBy, u as definitionSchema, v as createRefContextSlotMap, w as getPluginContext, x as definitionRefRegistry, y as RefExpressionParser, z as int16ArrayTag } from "./model-utils-BoeoBppL.js";
5
5
  //#region ../../packages/utils/dist/arrays/assert-no-duplicates.js
6
6
  /**
7
7
  * Asserts that an array has no duplicate values based on an optional key function.
@@ -488,6 +488,17 @@ var ToposortUnknownNodeError = class extends Error {
488
488
  }
489
489
  };
490
490
  //#endregion
491
+ //#region ../../packages/utils/dist/toposort/node-index.js
492
+ /**
493
+ * Reads a node index that is in-bounds by construction, throwing if the graph
494
+ * bookkeeping is corrupt rather than silently producing a wrong ordering.
495
+ */
496
+ function atNodeIndex(items, index) {
497
+ const item = items[index];
498
+ if (item === void 0) throw new Error(`Toposort encountered an unknown node index: ${index}`);
499
+ return item;
500
+ }
501
+ //#endregion
491
502
  //#region ../../node_modules/.pnpm/tinyqueue@3.0.0/node_modules/tinyqueue/index.js
492
503
  var TinyQueue = class {
493
504
  constructor(data = [], compare = (a, b) => a < b ? -1 : a > b ? 1 : 0) {
@@ -564,7 +575,7 @@ function makeOutgoingEdges(nodes, edgeArr) {
564
575
  */
565
576
  function makeNodeInDegrees(outgoingEdgesMap, nodeLength) {
566
577
  const nodeInDegrees = Array.from({ length: nodeLength }, () => 0);
567
- for (const [, targets] of outgoingEdgesMap.entries()) for (const target of targets) nodeInDegrees[target]++;
578
+ for (const [, targets] of outgoingEdgesMap.entries()) for (const target of targets) nodeInDegrees[target] = atNodeIndex(nodeInDegrees, target) + 1;
568
579
  return nodeInDegrees;
569
580
  }
570
581
  /**
@@ -591,7 +602,7 @@ function detectCycle(nodes, visited, edges) {
591
602
  for (let i = 0; i < nodes.length; i++) if (!visited.has(i)) {
592
603
  path.length = 0;
593
604
  visitSet.clear();
594
- if (dfs(i)) return path.map((idx) => nodes[idx]);
605
+ if (dfs(i)) return path.map((idx) => atNodeIndex(nodes, idx));
595
606
  }
596
607
  return [];
597
608
  }
@@ -607,7 +618,7 @@ function toposort(nodes, edges, options = {}) {
607
618
  const { compareFunc } = options;
608
619
  const outgoingEdgesMap = makeOutgoingEdges(new Map(nodes.map((node, index) => [node, index])), edges);
609
620
  const nodeInDegrees = makeNodeInDegrees(outgoingEdgesMap, nodes.length);
610
- const zeroInDegreeQueue = compareFunc ? new TinyQueue([], (a, b) => compareFunc(nodes[a], nodes[b])) : [];
621
+ const zeroInDegreeQueue = compareFunc ? new TinyQueue([], (a, b) => compareFunc(atNodeIndex(nodes, a), atNodeIndex(nodes, b))) : [];
611
622
  for (const [i, nodeInDegree] of nodeInDegrees.entries()) if (nodeInDegree === 0) zeroInDegreeQueue.push(i);
612
623
  const result = [];
613
624
  const visited = /* @__PURE__ */ new Set();
@@ -615,11 +626,12 @@ function toposort(nodes, edges, options = {}) {
615
626
  const current = zeroInDegreeQueue.pop();
616
627
  if (current === void 0) break;
617
628
  visited.add(current);
618
- result.push(nodes[current]);
629
+ result.push(atNodeIndex(nodes, current));
619
630
  const outgoingEdges = outgoingEdgesMap.get(current);
620
631
  if (outgoingEdges) for (const target of outgoingEdges) {
621
- nodeInDegrees[target]--;
622
- if (nodeInDegrees[target] === 0) zeroInDegreeQueue.push(target);
632
+ const remainingInDegree = atNodeIndex(nodeInDegrees, target) - 1;
633
+ nodeInDegrees[target] = remainingInDegree;
634
+ if (remainingInDegree === 0) zeroInDegreeQueue.push(target);
623
635
  }
624
636
  }
625
637
  if (result.length !== nodes.length) throw new ToposortCyclicalDependencyError(detectCycle(nodes, visited, outgoingEdgesMap));
@@ -1237,8 +1249,9 @@ function byId$2(projectDefinition, id) {
1237
1249
  }
1238
1250
  function getBackendApp(projectDefinition) {
1239
1251
  const backendApps = projectDefinition.apps.filter((a) => a.type === "backend");
1240
- if (backendApps.length > 1 || backendApps.length === 0) throw new Error(`Only one backend app is supported and must exist`);
1241
- return backendApps[0];
1252
+ const backendApp = backendApps[0];
1253
+ if (backendApps.length > 1 || !backendApp) throw new Error(`Only one backend app is supported and must exist`);
1254
+ return backendApp;
1242
1255
  }
1243
1256
  /**
1244
1257
  * Given an app config, get the relative directory of the app
@@ -1908,7 +1921,7 @@ function walkNode$1(schema, data, path, visitors, entityCtx) {
1908
1921
  walkNode$1(children.right, data, path, visitors, entityCtx);
1909
1922
  break;
1910
1923
  }
1911
- for (let i = cleanups.length - 1; i >= 0; i--) cleanups[i]();
1924
+ for (const cleanup of cleanups.toReversed()) cleanup();
1912
1925
  if (entityRestore) entityRestore();
1913
1926
  }
1914
1927
  //#endregion
@@ -2182,7 +2195,9 @@ function resolveZodRefPayloadNames(payload, { skipReferenceNameResolution = fals
2182
2195
  return entity.name;
2183
2196
  }
2184
2197
  for (const id of orderedEntities) {
2185
- const { nameResolver, ...rest } = entitiesById[id];
2198
+ const entity = entitiesById[id];
2199
+ if (!entity) throw new Error(`Could not find entity for id: ${id}`);
2200
+ const { nameResolver, ...rest } = entity;
2186
2201
  if (typeof nameResolver === "string") resolvedEntitiesById.set(rest.id, {
2187
2202
  ...rest,
2188
2203
  name: nameResolver
@@ -2250,7 +2265,7 @@ function resolveReferencesToIds(payload) {
2250
2265
  if (typeof data !== "object" || data === null) throw new TypeError("Data is not an object");
2251
2266
  const entitiesById = groupBy$1(entities, (entity) => entity.id);
2252
2267
  const duplicateEntityIds = Object.values(entitiesById).filter((e) => e.length > 1);
2253
- if (duplicateEntityIds.length > 0) throw new Error(`Found multiple duplicate entity IDs: ${duplicateEntityIds.map((ents) => `${ents[0].id} (${ents.map((e) => e.path.join(".")).join(",")})`).join(", ")}`);
2268
+ if (duplicateEntityIds.length > 0) throw new Error(`Found multiple duplicate entity IDs: ${duplicateEntityIds.map((ents) => `${ents[0]?.id} (${ents.map((e) => e.path.join(".")).join(",")})`).join(", ")}`);
2254
2269
  if (uniq(entities.map((e) => e.id)).length !== entities.length) throw new Error(`Found duplicate entity IDs`);
2255
2270
  const entityTypes = uniq(entities.map((e) => e.type));
2256
2271
  const entityTypeNames = uniq(entityTypes.map((t) => t.name));
@@ -3267,16 +3282,20 @@ var createAuthorizerRoleSchema = definitionSchemaWithSlots({ modelSlot: modelEnt
3267
3282
  */
3268
3283
  name: VALIDATORS.CAMEL_CASE_STRING,
3269
3284
  /**
3270
- * TypeScript expression that evaluates to a boolean.
3285
+ * Authorization expression a JS-like boolean DSL, not arbitrary
3286
+ * TypeScript. See `.agents/authorization.md` for the full grammar.
3271
3287
  *
3272
- * Available context variables:
3273
- * - `model` - The model instance being authorized
3274
- * - `userId` - The authenticated user's ID (implicit auth context)
3275
- * - `hasRole()` / `hasSomeRole()` - Role checking functions
3288
+ * Available context:
3289
+ * - `model.<field>` the row being authorized (scalars and relations)
3290
+ * - `userId` / `isAuthenticated` the principal
3291
+ * - `hasRole()` / `hasSomeRole()` global roles, or role delegation
3292
+ * across a relation in the two-argument form
3293
+ * - `exists()` / `all()` — quantify over a has-many relation
3276
3294
  *
3277
- * @example 'model.id === userId'
3278
- * @example 'hasRole("admin")'
3279
- * @example 'model.authorId === userId || hasRole("admin")'
3295
+ * @example 'model.userId === userId'
3296
+ * @example "hasRole('admin')"
3297
+ * @example "hasRole(model.blog, 'owner')"
3298
+ * @example 'exists(model.members, { userId: userId })'
3280
3299
  */
3281
3300
  expression: ctx.withExpression(authorizerExpressionRef, { model: modelSlot })
3282
3301
  }), {
@@ -8450,7 +8469,7 @@ function parseAuthorizerExpression(input) {
8450
8469
  }
8451
8470
  if (program.body.length !== 1) throw new AuthorizerExpressionParseError("Expression must be a single expression statement, e.g. model.id === auth.userId", 0, input.length);
8452
8471
  const expressionStatement = program.body[0];
8453
- if (expressionStatement.type !== "ExpressionStatement") throw new AuthorizerExpressionParseError("Line must be an expression statement, e.g. model.id === auth.userId", expressionStatement);
8472
+ if (expressionStatement?.type !== "ExpressionStatement") throw new AuthorizerExpressionParseError("Line must be an expression statement, e.g. model.id === auth.userId", expressionStatement);
8454
8473
  const ast = convertNode(expressionStatement.expression);
8455
8474
  return {
8456
8475
  ast,
@@ -8560,7 +8579,7 @@ function parseModelRelationArg(arg, funcName) {
8560
8579
  function parseHasRoleArgs(node, funcName) {
8561
8580
  if (node.arguments.length === 1) {
8562
8581
  const arg = node.arguments[0];
8563
- if (arg.type !== "Literal" || typeof arg.value !== "string") throw new AuthorizerExpressionParseError(`${funcName} argument must be a string literal`, arg);
8582
+ if (arg?.type !== "Literal" || typeof arg.value !== "string") throw new AuthorizerExpressionParseError(`${funcName} argument must be a string literal`, arg ?? node);
8564
8583
  return {
8565
8584
  type: "hasRole",
8566
8585
  role: arg.value,
@@ -8572,7 +8591,7 @@ function parseHasRoleArgs(node, funcName) {
8572
8591
  const relationArg = node.arguments[0];
8573
8592
  const roleArg = node.arguments[1];
8574
8593
  const relation = parseModelRelationArg(relationArg, funcName);
8575
- if (roleArg.type !== "Literal" || typeof roleArg.value !== "string") throw new AuthorizerExpressionParseError(`${funcName} second argument must be a string literal (role name)`, roleArg);
8594
+ if (roleArg?.type !== "Literal" || typeof roleArg.value !== "string") throw new AuthorizerExpressionParseError(`${funcName} second argument must be a string literal (role name)`, roleArg ?? node);
8576
8595
  return {
8577
8596
  type: "nestedHasRole",
8578
8597
  relationName: relation.relationName,
@@ -8646,7 +8665,7 @@ function parseRelationFilterArgs(node, operator, funcName) {
8646
8665
  const relationArg = node.arguments[0];
8647
8666
  const conditionsArg = node.arguments[1];
8648
8667
  const relation = parseModelRelationArg(relationArg, funcName);
8649
- if (conditionsArg.type !== "ObjectExpression") throw new AuthorizerExpressionParseError(`${funcName} second argument must be an object literal (e.g., { userId: userId })`, conditionsArg);
8668
+ if (conditionsArg?.type !== "ObjectExpression") throw new AuthorizerExpressionParseError(`${funcName} second argument must be an object literal (e.g., { userId: userId })`, conditionsArg ?? node);
8650
8669
  if (conditionsArg.properties.length === 0) throw new AuthorizerExpressionParseError(`${funcName} conditions object must have at least one property`, conditionsArg);
8651
8670
  const conditions = [];
8652
8671
  for (const prop of conditionsArg.properties) {
@@ -8865,10 +8884,10 @@ function validateAuthorizerExpression(ast, modelContext, pluginStore, definition
8865
8884
  });
8866
8885
  },
8867
8886
  hasSomeRole(node) {
8868
- for (let i = 0; i < node.roles.length; i++) {
8869
- const role = node.roles[i];
8887
+ for (const [i, role] of node.roles.entries()) {
8870
8888
  const start = node.rolesStart[i];
8871
8889
  const end = node.rolesEnd[i];
8890
+ if (start === void 0 || end === void 0) continue;
8872
8891
  if (allRoleNames.has(role)) warnIfAutoAssignedRole(role, start, end);
8873
8892
  else warnings.push({
8874
8893
  message: `Role '${role}' is not defined in the project configuration. Available roles: ${[...allRoleNames].join(", ")}.`,
@@ -9085,6 +9104,7 @@ function buildModelExpressionContext(model, allModels) {
9085
9104
  */
9086
9105
  var AuthorizerExpressionParser = class extends RefExpressionParser {
9087
9106
  name = "authorizer-expression";
9107
+ description = "JS-like boolean DSL over `model.<field>`, `userId`, and `isAuthenticated` — e.g. `model.userId === userId`, `hasRole(model.blog, 'owner')`, `exists(model.members, { userId: userId })`. See .agents/authorization.md for the full grammar.";
9088
9108
  /**
9089
9109
  * Creates a Zod schema for validating expression strings.
9090
9110
  * Requires a non-empty string value.
@@ -9199,13 +9219,15 @@ var AuthorizerExpressionParser = class extends RefExpressionParser {
9199
9219
  const foreignModel = modelById.get(relation.modelRef);
9200
9220
  if (foreignModel) {
9201
9221
  const foreignRoleByName = new Map(foreignModel.authorizer.roles.map((r) => [r.name, r]));
9202
- for (let i = 0; i < node.roles.length; i++) {
9203
- const foreignRole = foreignRoleByName.get(node.roles[i]);
9204
- if (foreignRole) deps.push({
9222
+ for (const [i, roleName] of node.roles.entries()) {
9223
+ const foreignRole = foreignRoleByName.get(roleName);
9224
+ const roleStart = node.rolesStart[i];
9225
+ const roleEnd = node.rolesEnd[i];
9226
+ if (foreignRole && roleStart !== void 0 && roleEnd !== void 0) deps.push({
9205
9227
  entityType: modelAuthorizerRoleEntityType,
9206
9228
  entityId: foreignRole.id,
9207
- start: node.rolesStart[i] + 1,
9208
- end: node.rolesEnd[i] - 1
9229
+ start: roleStart + 1,
9230
+ end: roleEnd - 1
9209
9231
  });
9210
9232
  }
9211
9233
  }
@@ -9261,9 +9283,9 @@ var AuthorizerExpressionParser = class extends RefExpressionParser {
9261
9283
  const modelPath = resolvedSlots.model;
9262
9284
  for (let len = modelPath.length; len > 0; len--) {
9263
9285
  let current = definition;
9264
- for (let i = 0; i < len; i++) {
9286
+ for (const part of modelPath.slice(0, len)) {
9265
9287
  if (current === null || current === void 0) break;
9266
- current = current[modelPath[i]];
9288
+ current = current[part];
9267
9289
  }
9268
9290
  if (current !== null && current !== void 0 && typeof current === "object" && "name" in current && typeof current.name === "string") return current;
9269
9291
  }
@@ -9551,21 +9573,7 @@ var createModelGraphqlSchema = definitionSchemaWithSlots({ modelSlot: modelEntit
9551
9573
  type: modelAuthorizerRoleEntityType,
9552
9574
  onDelete: "DELETE",
9553
9575
  parentSlot: modelSlot
9554
- })), []),
9555
- /**
9556
- * Whether this field is exposed as a `where` filter operand
9557
- * when the model's list query has where filtering enabled.
9558
- * Opt-in: an author must explicitly choose which exposed
9559
- * fields are filterable.
9560
- */
9561
- filterable: ctx.withDefault(__mf_0.boolean(), false),
9562
- /**
9563
- * Whether this field is exposed as an `orderBy` sort key
9564
- * when the model's list query has sorting enabled. Opt-in:
9565
- * an author must explicitly choose which exposed fields are
9566
- * sortable.
9567
- */
9568
- sortable: ctx.withDefault(__mf_0.boolean(), false)
9576
+ })), [])
9569
9577
  })).apply(withByKeyMergeRule({ getKey: (item) => item.ref })).apply(withDefault([])),
9570
9578
  localRelations: __mf_0.array(__mf_0.object({
9571
9579
  ref: ctx.withRef({
@@ -9592,9 +9600,67 @@ var createModelGraphqlSchema = definitionSchemaWithSlots({ modelSlot: modelEntit
9592
9600
  onDelete: "DELETE",
9593
9601
  parentSlot: modelSlot
9594
9602
  })), []),
9595
- paginated: ctx.withDefault(__mf_0.boolean(), false)
9603
+ paginated: ctx.withDefault(__mf_0.boolean(), false),
9604
+ orderable: ctx.withDefault(__mf_0.boolean(), false)
9596
9605
  })).apply(withByKeyMergeRule({ getKey: (item) => item.ref })).apply(withDefault([]))
9597
9606
  }), {}),
9607
+ /**
9608
+ * Sorting configuration shared by every surface that exposes an
9609
+ * `orderBy` argument — the list and connection queries, and `orderable`
9610
+ * list relations. Each surface opts in separately (`queries.orderBy.enabled`,
9611
+ * `objectType.foreignRelations[].orderable`) but they all sort by the
9612
+ * same fields.
9613
+ */
9614
+ orderBy: ctx.withDefault(__mf_0.object({
9615
+ /** Fields exposed as `orderBy` sort keys. */
9616
+ fields: __mf_0.array(ctx.withRef({
9617
+ type: modelScalarFieldEntityType,
9618
+ onDelete: "DELETE_PARENT",
9619
+ parentSlot: modelSlot
9620
+ })).apply(withDefault([])),
9621
+ /**
9622
+ * Applied when a caller supplies no `orderBy`. Ordered, so multi-key
9623
+ * defaults sort by the first entry first. Not restricted to
9624
+ * `fields` — a model can default to a sort key it does not expose.
9625
+ */
9626
+ defaultSort: __mf_0.array(__mf_0.object({
9627
+ ref: ctx.withRef({
9628
+ type: modelScalarFieldEntityType,
9629
+ onDelete: "DELETE_PARENT",
9630
+ parentSlot: modelSlot
9631
+ }),
9632
+ direction: ctx.withDefault(__mf_0.enum(["asc", "desc"]), "asc")
9633
+ })).apply(withByKeyMergeRule({ getKey: (item) => item.ref })).apply(withDefault([]))
9634
+ }), {}),
9635
+ /**
9636
+ * Filtering configuration for surfaces that expose a `where` argument —
9637
+ * the list and connection queries (`queries.where.enabled`). Shaped like
9638
+ * `orderBy` so relation-level filtering can reuse it.
9639
+ */
9640
+ where: ctx.withDefault(__mf_0.object({
9641
+ /** Fields exposed as `where` filter operands. */
9642
+ fields: __mf_0.array(ctx.withRef({
9643
+ type: modelScalarFieldEntityType,
9644
+ onDelete: "DELETE_PARENT",
9645
+ parentSlot: modelSlot
9646
+ })).apply(withDefault([])) }), {}),
9647
+ /**
9648
+ * Page-size limits shared by every paginated surface — the list query,
9649
+ * the connection query, and paginated list relations. Both are optional;
9650
+ * leaving them unset keeps the offset surfaces unbounded and lets the
9651
+ * connection fall back to Pothos' own defaults (20 / 100). Setting only a
9652
+ * max also applies it as the default, since the cap on an offset surface
9653
+ * would otherwise be bypassed by omitting the argument.
9654
+ */
9655
+ pagination: ctx.withDefault(__mf_0.object({
9656
+ /** Page size applied when the caller requests no explicit size. */
9657
+ defaultPageSize: __mf_0.number().int().positive().optional(),
9658
+ /** Largest page a caller may request. */
9659
+ maxPageSize: __mf_0.number().int().positive().optional()
9660
+ }).refine(({ defaultPageSize, maxPageSize }) => defaultPageSize === void 0 || maxPageSize === void 0 || defaultPageSize <= maxPageSize, {
9661
+ message: "Default page size cannot exceed max page size",
9662
+ path: ["defaultPageSize"]
9663
+ }), {}),
9598
9664
  queries: ctx.withDefault(__mf_0.object({
9599
9665
  globalRoles: createRoleArray(ctx),
9600
9666
  instanceRoles: ctx.withDefault(__mf_0.array(ctx.withRef({
@@ -9603,13 +9669,23 @@ var createModelGraphqlSchema = definitionSchemaWithSlots({ modelSlot: modelEntit
9603
9669
  parentSlot: modelSlot
9604
9670
  })), []),
9605
9671
  get: ctx.withDefault(__mf_0.object({ enabled: ctx.withDefault(__mf_0.boolean(), false) }), {}),
9672
+ /** Offset pagination (`skip`/`take`). */
9606
9673
  list: ctx.withDefault(__mf_0.object({
9607
9674
  enabled: ctx.withDefault(__mf_0.boolean(), false),
9608
- count: ctx.withDefault(__mf_0.object({ enabled: ctx.withDefault(__mf_0.boolean(), false) }), {}),
9609
- connection: ctx.withDefault(__mf_0.object({ enabled: ctx.withDefault(__mf_0.boolean(), false) }), {}),
9610
- where: ctx.withDefault(__mf_0.object({ enabled: ctx.withDefault(__mf_0.boolean(), false) }), {}),
9611
- orderBy: ctx.withDefault(__mf_0.object({ enabled: ctx.withDefault(__mf_0.boolean(), false) }), {})
9612
- }), {})
9675
+ count: ctx.withDefault(__mf_0.object({ enabled: ctx.withDefault(__mf_0.boolean(), false) }), {})
9676
+ }), {}),
9677
+ /**
9678
+ * Cursor pagination (Relay connection). Independent of `list` — a
9679
+ * model may expose either, both, or neither.
9680
+ */
9681
+ connection: ctx.withDefault(__mf_0.object({ enabled: ctx.withDefault(__mf_0.boolean(), false) }), {}),
9682
+ /**
9683
+ * `where`/`orderBy` arguments, shared by the list and connection
9684
+ * queries. The fields each may operate on live in the model-level
9685
+ * `where.fields` / `orderBy.fields` lists.
9686
+ */
9687
+ where: ctx.withDefault(__mf_0.object({ enabled: ctx.withDefault(__mf_0.boolean(), false) }), {}),
9688
+ orderBy: ctx.withDefault(__mf_0.object({ enabled: ctx.withDefault(__mf_0.boolean(), false) }), {})
9613
9689
  }), {}),
9614
9690
  mutations: ctx.withDefault(__mf_0.object({
9615
9691
  create: ctx.withDefault(__mf_0.object({ enabled: ctx.withDefault(__mf_0.boolean(), false) }), {}),
@@ -10703,7 +10779,7 @@ var pluginMetadataSchema = __mf_0.object({
10703
10779
  function sortAndValidateMigrations(migrations, pluginKey) {
10704
10780
  const sortedMigrations = [...migrations].toSorted((a, b) => a.version - b.version);
10705
10781
  if (sortedMigrations.some((m) => m.version <= 0)) throw new Error(`All migrations for plugin ${pluginKey} must have a positive version`);
10706
- for (let i = 0; i < sortedMigrations.length - 1; i++) if (sortedMigrations[i].version === sortedMigrations[i + 1].version) throw new Error(`All migrations for plugin ${pluginKey} must have a unique version`);
10782
+ for (const [i, migration] of sortedMigrations.slice(0, -1).entries()) if (migration.version === sortedMigrations[i + 1]?.version) throw new Error(`All migrations for plugin ${pluginKey} must have a unique version`);
10707
10783
  return sortedMigrations;
10708
10784
  }
10709
10785
  /**
@@ -11150,7 +11226,7 @@ var EnumUtils = {
11150
11226
  function isScalarUnique(model, fieldId) {
11151
11227
  const { primaryKeyFieldRefs } = model.model;
11152
11228
  const { uniqueConstraints } = model.model;
11153
- return primaryKeyFieldRefs.length === 1 && primaryKeyFieldRefs.includes(fieldId) || uniqueConstraints.some((c) => c.fields.length === 1 && c.fields[0].fieldRef === fieldId);
11229
+ return primaryKeyFieldRefs.length === 1 && primaryKeyFieldRefs.includes(fieldId) || uniqueConstraints.some((c) => c.fields.length === 1 && c.fields[0]?.fieldRef === fieldId);
11154
11230
  }
11155
11231
  function areScalarsUnique(model, fieldIds) {
11156
11232
  const sortedFieldIds = [...fieldIds].toSorted();
@@ -11224,9 +11300,10 @@ function byId(projectDefinition, id) {
11224
11300
  }
11225
11301
  function byUniqueTypeOrThrow(projectDefinition, type) {
11226
11302
  const config = projectDefinition.libraries.filter((lib) => lib.type === type);
11227
- if (config.length === 0) throw new Error(`Unable to find library with type ${type}`);
11303
+ const library = config[0];
11304
+ if (!library) throw new Error(`Unable to find library with type ${type}`);
11228
11305
  if (config.length > 1) throw new Error(`Multiple libraries with type ${type} found and only one is expected (${config.map((lib) => lib.name).join(", ")})`);
11229
- return config[0];
11306
+ return library;
11230
11307
  }
11231
11308
  /**
11232
11309
  * Given a library config, get the relative directory of the library
@@ -11482,7 +11559,7 @@ function walkNode(schema, path, visitors, visited) {
11482
11559
  walkNode(children.right, path, visitors, visited);
11483
11560
  break;
11484
11561
  }
11485
- for (let i = cleanups.length - 1; i >= 0; i--) cleanups[i]();
11562
+ for (const cleanup of cleanups.toReversed()) cleanup();
11486
11563
  visited.delete(schema);
11487
11564
  }
11488
11565
  /**
@@ -11929,6 +12006,7 @@ function transformJsonPath(data, path, transformFn) {
11929
12006
  const navigateAndTransform = (current, parts) => {
11930
12007
  if (parts.length === 0) return transformFn(structuredClone(current));
11931
12008
  const [currentPart, ...remainingParts] = parts;
12009
+ if (currentPart === void 0) return transformFn(structuredClone(current));
11932
12010
  if (currentPart === "*") {
11933
12011
  if (!Array.isArray(current)) throw new TypeError(`Expected an array at ${pathParts.join(".")}`);
11934
12012
  return current.map((item) => navigateAndTransform(item, remainingParts));
@@ -11949,7 +12027,7 @@ function renameObjectKeysTransform(renames) {
11949
12027
  return (data) => {
11950
12028
  if (data === null) return null;
11951
12029
  if (typeof data !== "object") throw new TypeError(`Expected an object, got ${typeof data}`);
11952
- return Object.fromEntries(Object.entries(data).map(([key, value]) => [renames[key] || key, value]));
12030
+ return Object.fromEntries(Object.entries(data).map(([key, value]) => [renames[key] ?? key, value]));
11953
12031
  };
11954
12032
  }
11955
12033
  //#endregion
@@ -15188,10 +15266,13 @@ var migration012MigrateAuthConfig = createSchemaMigration({
15188
15266
  version: "0.1.0",
15189
15267
  config: auth0Config
15190
15268
  });
15191
- else plugins[pluginIndex] = {
15192
- ...plugins[pluginIndex],
15193
- config: auth0Config
15194
- };
15269
+ else {
15270
+ const existingPlugin = plugins[pluginIndex];
15271
+ if (existingPlugin) plugins[pluginIndex] = {
15272
+ ...existingPlugin,
15273
+ config: auth0Config
15274
+ };
15275
+ }
15195
15276
  return {
15196
15277
  ...config,
15197
15278
  auth: void 0,
@@ -15370,7 +15451,7 @@ var migration018CrudNameFieldRef = createSchemaMigration({
15370
15451
  selectedField ??= model.model.fields[0];
15371
15452
  return {
15372
15453
  ...section,
15373
- nameFieldRef: selectedField.name
15454
+ nameFieldRef: selectedField?.name ?? ""
15374
15455
  };
15375
15456
  });
15376
15457
  return {
@@ -15518,13 +15599,16 @@ var migration021MigrateBullmqToPlugin = createSchemaMigration({
15518
15599
  version: "1.0.0",
15519
15600
  config: { implementationPluginKey: "baseplate-dev_plugin-queue_bullmq" }
15520
15601
  });
15521
- else plugins[queuePluginIndex] = {
15522
- ...plugins[queuePluginIndex],
15523
- config: {
15524
- ...plugins[queuePluginIndex].config,
15525
- implementationPluginKey: "baseplate-dev_plugin-queue_bullmq"
15526
- }
15527
- };
15602
+ else {
15603
+ const existingQueuePlugin = plugins[queuePluginIndex];
15604
+ if (existingQueuePlugin) plugins[queuePluginIndex] = {
15605
+ ...existingQueuePlugin,
15606
+ config: {
15607
+ ...existingQueuePlugin.config,
15608
+ implementationPluginKey: "baseplate-dev_plugin-queue_bullmq"
15609
+ }
15610
+ };
15611
+ }
15528
15612
  if (plugins.findIndex((p) => p.id === bullmqPluginId) === -1) plugins.push({
15529
15613
  id: bullmqPluginId,
15530
15614
  name: "bullmq",
@@ -15959,6 +16043,101 @@ var migration031UuidDefaultGeneration = createSchemaMigration({
15959
16043
  //#region ../../packages/project-builder-lib/dist/migrations/migration-032-web-app-plugin-data.js
15960
16044
  var STORAGE_PLUGIN_KEY = "baseplate-dev_plugin-storage_storage";
15961
16045
  var NOTIFICATIONS_PLUGIN_KEY = "baseplate-dev_plugin-notifications_notifications";
16046
+ /**
16047
+ * Moves hardcoded per-app opt-in flags off the core web app config and into the
16048
+ * generic `pluginData[pluginKey]` bag introduced by the web app schema extension
16049
+ * point.
16050
+ *
16051
+ * - `includeUploadComponents` -> `pluginData['<storage>'].includeUploadComponents`
16052
+ * - `includeNotifications` -> `pluginData['<notifications>'].includeNotifications`
16053
+ * - `includeAuth` -> dropped (it was never read by any generator)
16054
+ *
16055
+ * Only `true` values are relocated so existing opt-ins are preserved; the flags
16056
+ * are always stripped from the core config.
16057
+ */
16058
+ var migration032WebAppPluginData = createSchemaMigration({
16059
+ version: 32,
16060
+ name: "webAppPluginData",
16061
+ description: "Move includeUploadComponents/includeNotifications into web app pluginData and drop includeAuth",
16062
+ migrate: (config) => {
16063
+ const apps = config.apps?.map((app) => {
16064
+ if (app.type !== "web") return app;
16065
+ const { includeAuth: _includeAuth, includeUploadComponents, includeNotifications, pluginData: existingPluginData, ...rest } = app;
16066
+ const pluginData = { ...existingPluginData };
16067
+ if (includeUploadComponents) pluginData[STORAGE_PLUGIN_KEY] = {
16068
+ ...pluginData[STORAGE_PLUGIN_KEY],
16069
+ includeUploadComponents: true
16070
+ };
16071
+ if (includeNotifications) pluginData[NOTIFICATIONS_PLUGIN_KEY] = {
16072
+ ...pluginData[NOTIFICATIONS_PLUGIN_KEY],
16073
+ includeNotifications: true
16074
+ };
16075
+ return Object.keys(pluginData).length > 0 ? {
16076
+ ...rest,
16077
+ pluginData
16078
+ } : rest;
16079
+ });
16080
+ return {
16081
+ ...config,
16082
+ apps: apps ?? []
16083
+ };
16084
+ }
16085
+ });
16086
+ //#endregion
16087
+ //#region ../../packages/project-builder-lib/dist/migrations/migration-033-hoist-sort-filter-config.js
16088
+ /**
16089
+ * Hoists the per-field `sortable`/`filterable` flags off
16090
+ * `graphql.objectType.fields[]` into the shared `graphql.orderBy.fields` and
16091
+ * `graphql.where.fields` lists.
16092
+ *
16093
+ * Both flags gate vocabulary used by more than one surface — the list query and
16094
+ * `orderable` list relations — so they belong beside the other shared sort and
16095
+ * filter configuration rather than under the object type. The per-surface
16096
+ * enable switches (`queries.list.orderBy.enabled`, `queries.list.where.enabled`)
16097
+ * are unaffected.
16098
+ */
16099
+ var migration033HoistSortFilterConfig = createSchemaMigration({
16100
+ version: 33,
16101
+ name: "hoistSortFilterConfig",
16102
+ description: "Hoist sortable/filterable field flags into shared graphql.orderBy and graphql.where config",
16103
+ migrate: (config) => {
16104
+ if (!config.models) return config;
16105
+ const refsWhere = (fields, key) => fields.filter((field) => field[key] === true).map((field) => field.ref).filter((ref) => ref !== void 0);
16106
+ return {
16107
+ ...config,
16108
+ models: config.models.map((model) => {
16109
+ const { graphql } = model;
16110
+ if (!graphql?.objectType?.fields) return model;
16111
+ const { fields } = graphql.objectType;
16112
+ return {
16113
+ ...model,
16114
+ graphql: {
16115
+ ...graphql,
16116
+ objectType: {
16117
+ ...graphql.objectType,
16118
+ fields: fields.map((field) => omit(field, ["sortable", "filterable"]))
16119
+ },
16120
+ orderBy: {
16121
+ ...graphql.orderBy,
16122
+ fields: refsWhere(fields, "sortable")
16123
+ },
16124
+ where: {
16125
+ ...graphql.where,
16126
+ fields: refsWhere(fields, "filterable")
16127
+ }
16128
+ }
16129
+ };
16130
+ })
16131
+ };
16132
+ }
16133
+ });
16134
+ //#endregion
16135
+ //#region ../../packages/project-builder-lib/dist/migrations/migration-034-hoist-connection-config.js
16136
+ var HOISTED_KEYS = [
16137
+ "connection",
16138
+ "where",
16139
+ "orderBy"
16140
+ ];
15962
16141
  //#endregion
15963
16142
  //#region ../../packages/project-builder-lib/dist/migrations/index.js
15964
16143
  var SCHEMA_MIGRATIONS = [
@@ -15989,31 +16168,36 @@ var SCHEMA_MIGRATIONS = [
15989
16168
  migration029AdminRoleAndAutoAssigned,
15990
16169
  migration030RemoveThemeHoverColors,
15991
16170
  migration031UuidDefaultGeneration,
16171
+ migration032WebAppPluginData,
16172
+ migration033HoistSortFilterConfig,
15992
16173
  createSchemaMigration({
15993
- version: 32,
15994
- name: "webAppPluginData",
15995
- description: "Move includeUploadComponents/includeNotifications into web app pluginData and drop includeAuth",
16174
+ version: 34,
16175
+ name: "hoistConnectionConfig",
16176
+ description: "Hoist connection, where, and orderBy toggles out of graphql.queries.list into graphql.queries",
15996
16177
  migrate: (config) => {
15997
- const apps = config.apps?.map((app) => {
15998
- if (app.type !== "web") return app;
15999
- const { includeAuth: _includeAuth, includeUploadComponents, includeNotifications, pluginData: existingPluginData, ...rest } = app;
16000
- const pluginData = { ...existingPluginData };
16001
- if (includeUploadComponents) pluginData[STORAGE_PLUGIN_KEY] = {
16002
- ...pluginData[STORAGE_PLUGIN_KEY],
16003
- includeUploadComponents: true
16004
- };
16005
- if (includeNotifications) pluginData[NOTIFICATIONS_PLUGIN_KEY] = {
16006
- ...pluginData[NOTIFICATIONS_PLUGIN_KEY],
16007
- includeNotifications: true
16008
- };
16009
- return Object.keys(pluginData).length > 0 ? {
16010
- ...rest,
16011
- pluginData
16012
- } : rest;
16013
- });
16178
+ if (!config.models) return config;
16014
16179
  return {
16015
16180
  ...config,
16016
- apps: apps ?? []
16181
+ models: config.models.map((model) => {
16182
+ const { graphql } = model;
16183
+ const list = graphql?.queries?.list;
16184
+ if (!graphql?.queries || !list) return model;
16185
+ const hoisted = Object.fromEntries(HOISTED_KEYS.filter((key) => list[key] !== void 0).map((key) => [key, key === "connection" && list.enabled !== true ? {
16186
+ ...list[key],
16187
+ enabled: false
16188
+ } : list[key]]));
16189
+ return {
16190
+ ...model,
16191
+ graphql: {
16192
+ ...graphql,
16193
+ queries: {
16194
+ ...graphql.queries,
16195
+ ...hoisted,
16196
+ list: omit(list, HOISTED_KEYS)
16197
+ }
16198
+ }
16199
+ };
16200
+ })
16017
16201
  };
16018
16202
  }
16019
16203
  })
@@ -17205,12 +17389,10 @@ function convertColorNameToOklch(color) {
17205
17389
  const fixedColorMapping = FIXED_COLOR_MAPPINGS[color];
17206
17390
  if (fixedColorMapping) return fixedColorMapping;
17207
17391
  const colorComponents = color.split("-");
17208
- if (colorComponents.length === 2) {
17209
- const paletteName = colorComponents[0];
17210
- if (Object.prototype.hasOwnProperty.call(COLOR_PALETTES, paletteName)) {
17211
- const shade = COLOR_PALETTES[colorComponents[0]][colorComponents[1]];
17212
- if (shade) return shade;
17213
- }
17392
+ const [paletteName, shadeName] = colorComponents;
17393
+ if (colorComponents.length === 2 && paletteName !== void 0 && shadeName !== void 0 && Object.prototype.hasOwnProperty.call(COLOR_PALETTES, paletteName)) {
17394
+ const shade = COLOR_PALETTES[paletteName][shadeName];
17395
+ if (shade) return shade;
17214
17396
  }
17215
17397
  return color;
17216
17398
  }
@@ -17300,10 +17482,12 @@ var DefinitionDiffKeyedArrayField = class extends DefinitionDiffField {
17300
17482
  case "add":
17301
17483
  items.push(item);
17302
17484
  break;
17303
- case "update":
17304
- if (index === -1) throw new Error(`Cannot apply patch. Item with key "${key}" not found.`);
17305
- items[index] = toMerged(items[index], item);
17485
+ case "update": {
17486
+ const existingItem = items[index];
17487
+ if (index === -1 || !existingItem) throw new Error(`Cannot apply patch. Item with key "${key}" not found.`);
17488
+ items[index] = toMerged(existingItem, item);
17306
17489
  break;
17490
+ }
17307
17491
  case "remove":
17308
17492
  if (index !== -1) items.splice(index, 1);
17309
17493
  break;
@@ -17329,8 +17513,9 @@ var DefinitionDiffReplacementField = class extends DefinitionDiffField {
17329
17513
  return [];
17330
17514
  }
17331
17515
  apply(current, diff) {
17332
- if (diff.length === 0) return current;
17333
- return diff[0].item;
17516
+ const firstOperation = diff[0];
17517
+ if (!firstOperation) return current;
17518
+ return firstOperation.item;
17334
17519
  }
17335
17520
  getActionVerb(isNew) {
17336
17521
  return isNew ? "set" : "replaced";
@@ -18265,4 +18450,4 @@ function generateDefaultTheme() {
18265
18450
  //#endregion
18266
18451
  export { AVAILABLE_FLAGS, AppUtils, AuthorizerExpressionParseError, AuthorizerExpressionParser, BUILT_IN_ADMIN_CRUD_ACTIONS, BUILT_IN_ADMIN_CRUD_COLUMNS, BUILT_IN_ADMIN_CRUD_INPUTS, BUILT_IN_TRANSFORMERS, COLOR_PALETTES, DEFAULT_APPS_FOLDER, DEFAULT_LIBRARIES_FOLDER, DefinitionDiffArrayIncludesField, DefinitionDiffKeyedArrayField, DefinitionDiffReplacementField, DefinitionEntityType, EnumUtils, FIXED_COLOR_MAPPINGS, FeatureUtils, LibraryCompiler, LibraryUtils, ModelFieldUtils, ModelTransformerUtils, ModelUtils, PALETTE_SHADES, PackageCompiler, PluginSpecStore, PluginUtils, ProjectDefinitionContainer, REFERENTIAL_ACTIONS, RefExpressionParser, SCALAR_FIELD_TYPES, SCHEMA_MIGRATIONS, SchemaMigrationError, THEME_COLORS, THEME_COLOR_KEYS, VALIDATORS, adminCrudActionCompilerSpec, adminCrudActionEntityType, adminCrudActionSpec, adminCrudColumnCompilerSpec, adminCrudColumnEntityType, adminCrudColumnSpec, adminCrudEmbeddedFormEntityType, adminCrudEmbeddedInputType, adminCrudEmbeddedLocalInputType, adminCrudInputCompilerSpec, adminCrudInputEntityType, adminCrudInputSpec, adminCrudSectionColumnEntityType, adminSectionEntityType, appCompilerSpec, appEntityType, applyDefinitionDiff, applyDefinitionFixes, applyExpressionRenames, applyMergedDefinition, assignEntityIds, authConfigSpec, authModelsSpec, authRoleEntityType, backendAppEntryType, baseAdminCrudActionSchema, baseAdminCrudColumnSchema, baseAdminCrudInputSchema, baseAppSchema, baseAppValidators, baseLibrarySchema, baseLibraryValidators, basePluginDefinitionSchema, baseTransformerFields, baseTransformerSchema, buildEnabledPluginFqnSet, buildModelExpressionContext, buildPackageName, checkUniqueField, checkUniqueFieldValue, cleanDefaultValues, collectDefinitionIssues, collectEntityArrays, collectEntityMetadata, collectExpressionIssues, collectFieldIssues, convertColorNameToOklch, convertHexToOklch, convertOklchToColorName, convertOklchToHex, createAdminAppSchema, createAdminCrudActionSchema, createAdminCrudActionType, createAdminCrudColumnCompiler, createAdminCrudColumnSchema, createAdminCrudColumnType, createAdminCrudDeleteActionSchema, createAdminCrudEditActionSchema, createAdminCrudEmbeddedFormSchema, createAdminCrudEmbeddedInputSchema, createAdminCrudEmbeddedLocalInputSchema, createAdminCrudEnumInputSchema, createAdminCrudForeignColumnSchema, createAdminCrudForeignInputSchema, createAdminCrudInputSchema, createAdminCrudInputType, createAdminCrudPasswordInputSchema, createAdminCrudSectionSchema, createAdminCrudTextColumnSchema, createAdminCrudTextInputSchema, createAppCompiler, createAppEntryType, createAppSchema, createAuthorizerRoleSchema, createBackendAppSchema, createBaseAdminSectionValidators, createDefinitionDiff, createDefinitionDiffConfig, createDefinitionEntityNameResolver, createDefinitionSchemaParserContext, createEmbeddedRelationTransformerSchema, createEntity, createEntityIssue, createEntityType, createEnumBaseSchema, createEnumSchema, createEnumValueSchema, createExpressionParserRef, createFeatureSchema, createFeaturesSchema, createFieldMapSpec, createIssueFixSetter, createLibraryWebConfig, createModelAuthorizerSchema, createModelBaseSchema, createModelGraphqlSchema, createModelIndexSchema, createModelRelationFieldSchema, createModelScalarFieldSchema, createModelSchema, createModelServiceSchema, createModelTransformerType, createModelUniqueConstraintSchema, createPluginFieldMap, createPluginImplementationStoreWithNewPlugins, createPluginModelSyncChecker, createPluginModule, createPluginSpec, createPluginSpecStore, createPluginWithConfigSchema, createPluginsSchema, createProjectDefinitionSchema, createProjectDefinitionSchemaWithContext, createRefContextSlot, createRefContextSlotMap, createRefSchemaCollector, createRefSchemaVisitor, createSettingsSchema, createTemplateExtractorSchema, createThemeSchema, createTransformerSchema, createWebAdminSectionSchema, createWebAppSchema, definitionFieldIssueRegistry, definitionFixRegistry, definitionIssueCheckerSpec, definitionRefRegistry, definitionSchema, definitionSchemaWithSlots, deleteEntity, deserializeSchemaWithTransformedReferences, diffDefinition, diffSerializedDefinitions, expressionParserCoreModule, expressionParserSpec, extractDefinitionRefs, featureEntityType, featureNameSchema, findDiscriminatedUnionMatch, findOrphanedUnionItems, fixDefinitionRefs, fixRefDeletions, formatOklch, generalSettingsSchema, generateCssBlockFromThemeColors, generateCssFromThemeConfig, generateDefaultTheme, generateThemeColorsFromShade, getBackendRelativePath, getDefaultThemeColorFromShade, getEntity, getEntityName, getLatestMigrationVersion, getManagedPluginsForPlugin, getMergeRule, getPackageDirectory, getPluginContext, getPluginDependencies, getPluginMetadataByKey, getPluginMetadataByKeyOrThrow, getUnmetPluginDependencies, getWebAppPluginData, infrastructureSettingsSchema, initializePlugins, isMigrateableProjectDefinition, libraryEntityType, libraryTypeSpec, listEntities, mergeDataWithSchema, mergeDefinition, mergeDefinitionContainer, modelAuthorizerRoleEntityType, modelEntityType, modelEnumEntityType, modelEnumValueEntityType, modelForeignRelationEntityType, modelIndexEntityType, modelLocalRelationEntityType, modelScalarFieldEntityType, modelTransformerCompilerSpec, modelTransformerEntityType, modelTransformerSpec, modelUniqueConstraintEntityType, monorepoSettingsSchema, nodeLibraryDefinitionSchemaEntry, normalizeOklch, oklchColor, paletteSchema, palettesSchema, parseAuthorizerExpression, parseOklch, parseProjectDefinitionWithContext, parseProjectDefinitionWithReferences, partitionIssuesBySeverity, patchEntity, pluginAppCompiler, pluginConfigSpec, pluginDefaultsSpec, pluginDependencySchema, pluginEntityType, pluginMetadataSchema, pluginSpecDependencySchema, pluginSpecSupportSchema, previewIssueFix, resolveIssuePath, rootCompilerSpec, runInPluginContext, runPluginMigrations, runSchemaMigrations, serializeSchema, serializeSchemaFromRefPayload, sortEntityArrays, stripEmptyGeneratorChildren, stripUndefinedValues, themeColorSchema, transformDataWithSchema, undefinedIfEmpty, undefinedIfFalsy, updateEntity, validateAuthorizerExpression, validatePluginDependencyGraph, visitAuthorizerExpression, walkDataWithSchema, walkSchemaStructure, webAppEntryType, webAppSchemaExtensionSpec, webConfigSpec, withByKeyMergeRule, withDefault, withEnt, withFix, withIssueChecker, withMergeRule, withPlaceholderSlots, withRef };
18267
18452
 
18268
- //# sourceMappingURL=dist-CtqdAorB.js.map
18453
+ //# sourceMappingURL=dist-DiQ4J8N0.js.map