@baseplate-dev/plugin-auth 4.0.0 → 4.0.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.
Files changed (131) hide show
  1. package/dist/auth/core/common.d.ts +2 -5
  2. package/dist/auth/core/common.d.ts.map +1 -1
  3. package/dist/auth/core/common.js +14 -14
  4. package/dist/auth/core/common.js.map +1 -1
  5. package/dist/auth/core/node.d.ts +3 -3
  6. package/dist/auth/core/node.d.ts.map +1 -1
  7. package/dist/auth/core/node.js +5 -8
  8. package/dist/auth/core/node.js.map +1 -1
  9. package/dist/auth/core/web.d.ts +3 -3
  10. package/dist/auth/core/web.d.ts.map +1 -1
  11. package/dist/auth/core/web.js +4 -5
  12. package/dist/auth/core/web.js.map +1 -1
  13. package/dist/auth0/core/common.d.ts +3 -5
  14. package/dist/auth0/core/common.d.ts.map +1 -1
  15. package/dist/auth0/core/common.js +11 -14
  16. package/dist/auth0/core/common.js.map +1 -1
  17. package/dist/auth0/core/node.d.ts +3 -3
  18. package/dist/auth0/core/node.d.ts.map +1 -1
  19. package/dist/auth0/core/node.js +5 -8
  20. package/dist/auth0/core/node.js.map +1 -1
  21. package/dist/auth0/core/web.d.ts +3 -3
  22. package/dist/auth0/core/web.d.ts.map +1 -1
  23. package/dist/auth0/core/web.js +4 -5
  24. package/dist/auth0/core/web.js.map +1 -1
  25. package/dist/local-auth/admin/common.d.ts +3 -2
  26. package/dist/local-auth/admin/common.d.ts.map +1 -1
  27. package/dist/local-auth/admin/common.js +6 -7
  28. package/dist/local-auth/admin/common.js.map +1 -1
  29. package/dist/local-auth/admin/node.d.ts +3 -6
  30. package/dist/local-auth/admin/node.d.ts.map +1 -1
  31. package/dist/local-auth/admin/node.js +13 -12
  32. package/dist/local-auth/admin/node.js.map +1 -1
  33. package/dist/local-auth/admin/web.d.ts +3 -4
  34. package/dist/local-auth/admin/web.d.ts.map +1 -1
  35. package/dist/local-auth/admin/web.js +22 -21
  36. package/dist/local-auth/admin/web.js.map +1 -1
  37. package/dist/local-auth/core/common.d.ts +3 -5
  38. package/dist/local-auth/core/common.d.ts.map +1 -1
  39. package/dist/local-auth/core/common.js +10 -13
  40. package/dist/local-auth/core/common.js.map +1 -1
  41. package/dist/local-auth/core/node.d.ts +3 -3
  42. package/dist/local-auth/core/node.d.ts.map +1 -1
  43. package/dist/local-auth/core/node.js +5 -8
  44. package/dist/local-auth/core/node.js.map +1 -1
  45. package/dist/local-auth/core/web.d.ts +3 -3
  46. package/dist/local-auth/core/web.d.ts.map +1 -1
  47. package/dist/local-auth/core/web.js +4 -5
  48. package/dist/local-auth/core/web.js.map +1 -1
  49. package/dist/placeholder-auth/core/common.d.ts +2 -5
  50. package/dist/placeholder-auth/core/common.d.ts.map +1 -1
  51. package/dist/placeholder-auth/core/common.js +10 -13
  52. package/dist/placeholder-auth/core/common.js.map +1 -1
  53. package/dist/placeholder-auth/core/node.d.ts +3 -3
  54. package/dist/placeholder-auth/core/node.d.ts.map +1 -1
  55. package/dist/placeholder-auth/core/node.js +5 -8
  56. package/dist/placeholder-auth/core/node.js.map +1 -1
  57. package/dist/placeholder-auth/core/web.d.ts +3 -3
  58. package/dist/placeholder-auth/core/web.d.ts.map +1 -1
  59. package/dist/placeholder-auth/core/web.js +4 -5
  60. package/dist/placeholder-auth/core/web.js.map +1 -1
  61. package/dist/web/assets/__federation_expose_auth0CoreCommon-DLSGXjCI.js +40 -0
  62. package/dist/web/assets/__federation_expose_auth0CoreCommon-DLSGXjCI.js.map +1 -0
  63. package/dist/web/assets/{__federation_expose_auth0CoreWeb-CZueDXPK.js → __federation_expose_auth0CoreWeb-C7FfhlmF.js} +9 -10
  64. package/dist/web/assets/{__federation_expose_auth0CoreWeb-CZueDXPK.js.map → __federation_expose_auth0CoreWeb-C7FfhlmF.js.map} +1 -1
  65. package/dist/web/assets/__federation_expose_authCoreCommon-BF58isGa.js +29 -0
  66. package/dist/web/assets/__federation_expose_authCoreCommon-BF58isGa.js.map +1 -0
  67. package/dist/web/assets/{__federation_expose_authCoreWeb-C8rgnA2v.js → __federation_expose_authCoreWeb-DMq9M88g.js} +10 -11
  68. package/dist/web/assets/{__federation_expose_authCoreWeb-C8rgnA2v.js.map → __federation_expose_authCoreWeb-DMq9M88g.js.map} +1 -1
  69. package/dist/web/assets/{__federation_expose_local-authAdminCommon-C75-DAzO.js → __federation_expose_local-authAdminCommon-sQw4q5YX.js} +8 -9
  70. package/dist/web/assets/__federation_expose_local-authAdminCommon-sQw4q5YX.js.map +1 -0
  71. package/dist/web/assets/__federation_expose_local-authAdminWeb-9FbO89NR.js +41 -0
  72. package/dist/web/assets/__federation_expose_local-authAdminWeb-9FbO89NR.js.map +1 -0
  73. package/dist/web/assets/__federation_expose_local-authCoreCommon-CpUK09_4.js +21 -0
  74. package/dist/web/assets/__federation_expose_local-authCoreCommon-CpUK09_4.js.map +1 -0
  75. package/dist/web/assets/{__federation_expose_local-authCoreWeb-ChyvdsRq.js → __federation_expose_local-authCoreWeb-Czp0GaY1.js} +9 -10
  76. package/dist/web/assets/{__federation_expose_local-authCoreWeb-ChyvdsRq.js.map → __federation_expose_local-authCoreWeb-Czp0GaY1.js.map} +1 -1
  77. package/dist/web/assets/__federation_expose_placeholder-authCoreCommon-CFDDdOMo.js +23 -0
  78. package/dist/web/assets/__federation_expose_placeholder-authCoreCommon-CFDDdOMo.js.map +1 -0
  79. package/dist/web/assets/{__federation_expose_placeholder-authCoreWeb-CT8JKYLB.js → __federation_expose_placeholder-authCoreWeb-Bcn1_oDP.js} +9 -13
  80. package/dist/web/assets/{__federation_expose_placeholder-authCoreWeb-CT8JKYLB.js.map → __federation_expose_placeholder-authCoreWeb-Bcn1_oDP.js.map} +1 -1
  81. package/dist/web/assets/{__federation_fn_import-C_QCk5FX.js → __federation_fn_import-DsXcpNlB.js} +2 -2
  82. package/dist/web/assets/{__federation_fn_import-C_QCk5FX.js.map → __federation_fn_import-DsXcpNlB.js.map} +1 -1
  83. package/dist/web/assets/__federation_shared_@baseplate-dev/project-builder-lib/{web-DtztAtUw.js → web-zqe3PPcn.js} +37 -118
  84. package/dist/web/assets/__federation_shared_@baseplate-dev/project-builder-lib/web-zqe3PPcn.js.map +1 -0
  85. package/dist/web/assets/__federation_shared_@baseplate-dev/{project-builder-lib-CcNtL_U6.js → project-builder-lib-CmgMfkI5.js} +2152 -2215
  86. package/dist/web/assets/__federation_shared_@baseplate-dev/project-builder-lib-CmgMfkI5.js.map +1 -0
  87. package/dist/web/assets/__federation_shared_@baseplate-dev/{ui-components-DA_4I2Vy.js → ui-components-D1Dayhn9.js} +5 -5
  88. package/dist/web/assets/__federation_shared_@baseplate-dev/{ui-components-DA_4I2Vy.js.map → ui-components-D1Dayhn9.js.map} +1 -1
  89. package/dist/web/assets/__federation_shared_@baseplate-dev/{utils-Bxy-1ETU.js → utils-BO5VHrCf.js} +27 -6
  90. package/dist/web/assets/__federation_shared_@baseplate-dev/utils-BO5VHrCf.js.map +1 -0
  91. package/dist/web/assets/__federation_shared_@tanstack/{react-router-DooFj-IS.js → react-router-CNzDweD5.js} +2 -2
  92. package/dist/web/assets/__federation_shared_@tanstack/{react-router-DooFj-IS.js.map → react-router-CNzDweD5.js.map} +1 -1
  93. package/dist/web/assets/{get-auth-plugin-definition-D2XMaoy7.js → get-auth-plugin-definition-BV2O8wTa.js} +2 -2
  94. package/dist/web/assets/{get-auth-plugin-definition-D2XMaoy7.js.map → get-auth-plugin-definition-BV2O8wTa.js.map} +1 -1
  95. package/dist/web/assets/{index-DwJT6_Wn.js → index-BL7fotl7.js} +2 -2
  96. package/dist/web/assets/{index-DwJT6_Wn.js.map → index-BL7fotl7.js.map} +1 -1
  97. package/dist/web/assets/{index.esm-ChwWPPiL.js → index.esm-B4RpOlq_.js} +2 -2
  98. package/dist/web/assets/{index.esm-ChwWPPiL.js.map → index.esm-B4RpOlq_.js.map} +1 -1
  99. package/dist/web/assets/{isEqual-DAXqKRba.js → isEqual-BQtm2LNT.js} +5 -5
  100. package/dist/web/assets/{isEqual-DAXqKRba.js.map → isEqual-BQtm2LNT.js.map} +1 -1
  101. package/dist/web/assets/{model-merger-gGkFnyaY.js → model-merger-BwRNqcBu.js} +189 -81
  102. package/dist/web/assets/model-merger-BwRNqcBu.js.map +1 -0
  103. package/dist/web/assets/{plugin-definition-hAzbWO7b.js → plugin-definition-B9d2CoQL.js} +2 -2
  104. package/dist/web/assets/{plugin-definition-hAzbWO7b.js.map → plugin-definition-B9d2CoQL.js.map} +1 -1
  105. package/dist/web/assets/{plugin-definition-_slrOM0G.js → plugin-definition-BMTsmwyH.js} +2 -2
  106. package/dist/web/assets/{plugin-definition-_slrOM0G.js.map → plugin-definition-BMTsmwyH.js.map} +1 -1
  107. package/dist/web/assets/{plugin-definition-rpMj4pr8.js → plugin-definition-CHD5r-h7.js} +2 -2
  108. package/dist/web/assets/{plugin-definition-rpMj4pr8.js.map → plugin-definition-CHD5r-h7.js.map} +1 -1
  109. package/dist/web/assets/{plugin-definition-QRBMcFiG.js → plugin-definition-DA9rJBcS.js} +2 -2
  110. package/dist/web/assets/{plugin-definition-QRBMcFiG.js.map → plugin-definition-DA9rJBcS.js.map} +1 -1
  111. package/dist/web/assets/{react-DbX1FP85.js → react-B9vhIZMy.js} +2 -2
  112. package/dist/web/assets/{react-DbX1FP85.js.map → react-B9vhIZMy.js.map} +1 -1
  113. package/dist/web/assets/remoteEntry.js +10 -10
  114. package/dist/web/assets/{styles-DqLt1Blm.js → styles-CEm5K1iU.js} +3 -3
  115. package/dist/web/assets/{styles-DqLt1Blm.js.map → styles-CEm5K1iU.js.map} +1 -1
  116. package/package.json +13 -12
  117. package/dist/web/assets/__federation_expose_auth0CoreCommon-Ga9LD3d6.js +0 -43
  118. package/dist/web/assets/__federation_expose_auth0CoreCommon-Ga9LD3d6.js.map +0 -1
  119. package/dist/web/assets/__federation_expose_authCoreCommon-BrTLsuJC.js +0 -29
  120. package/dist/web/assets/__federation_expose_authCoreCommon-BrTLsuJC.js.map +0 -1
  121. package/dist/web/assets/__federation_expose_local-authAdminCommon-C75-DAzO.js.map +0 -1
  122. package/dist/web/assets/__federation_expose_local-authAdminWeb-D2xGvwyL.js +0 -40
  123. package/dist/web/assets/__federation_expose_local-authAdminWeb-D2xGvwyL.js.map +0 -1
  124. package/dist/web/assets/__federation_expose_local-authCoreCommon-BFUbyPYg.js +0 -27
  125. package/dist/web/assets/__federation_expose_local-authCoreCommon-BFUbyPYg.js.map +0 -1
  126. package/dist/web/assets/__federation_expose_placeholder-authCoreCommon-DrFV9FSW.js +0 -26
  127. package/dist/web/assets/__federation_expose_placeholder-authCoreCommon-DrFV9FSW.js.map +0 -1
  128. package/dist/web/assets/__federation_shared_@baseplate-dev/project-builder-lib/web-DtztAtUw.js.map +0 -1
  129. package/dist/web/assets/__federation_shared_@baseplate-dev/project-builder-lib-CcNtL_U6.js.map +0 -1
  130. package/dist/web/assets/__federation_shared_@baseplate-dev/utils-Bxy-1ETU.js.map +0 -1
  131. package/dist/web/assets/model-merger-gGkFnyaY.js.map +0 -1
@@ -1,1208 +1,74 @@
1
- import { c as createPluginSpec, m as mapValues, a as createEntityType, d as definitionSchemaWithSlots, D as DefinitionReferenceMarker, R as REF_ANNOTATIONS_MARKER_SYMBOL, s as stripRefMarkers, b as createDefinitionSchemaParserContext, g as get, e as set$1, f as definitionSchema, h as modelForeignRelationEntityType, i as modelLocalRelationEntityType, j as modelScalarFieldEntityType, k as modelEntityType, l as modelTransformerEntityType, n as modelEnumValueEntityType, o as modelEnumEntityType, p as featureEntityType, q as modelUniqueConstraintEntityType, r as createFeaturesSchema, M as ModelUtils, t as omit, u as cloneDeep } from '../model-merger-gGkFnyaY.js';
2
- export { O as DefinitionDiffArrayIncludesField, L as DefinitionDiffKeyedArrayField, N as DefinitionDiffReplacementField, y as DefinitionEntityType, F as FeatureUtils, S as applyDefinitionDiff, I as applyModelMergerDiff, J as applyModelMergerResultInPlace, K as createAndApplyModelMergerResults, Q as createDefinitionDiff, P as createDefinitionDiffConfig, B as createFeatureSchema, v as createInitializedPluginSpec, E as createModelMergerResult, H as createModelMergerResults, w as createRefContextSlot, x as createRefContextSlotMap, G as doesModelMergerResultsHaveChanges, A as featureNameSchema, C as modelMergerDefinitionDiffConfig, z as withPlaceholderSlots } from '../model-merger-gGkFnyaY.js';
3
- import { importShared } from '../__federation_fn_import-C_QCk5FX.js';
4
- import { i as isEqual } from '../isEqual-DAXqKRba.js';
1
+ import { c as createFieldMapSpec, a as createEntityType, d as definitionSchemaWithSlots, D as DefinitionReferenceMarker, R as REF_ANNOTATIONS_MARKER_SYMBOL, s as stripRefMarkers, m as mapValues, b as createDefinitionSchemaParserContext, g as get, e as set$1, f as definitionSchema, h as modelForeignRelationEntityType, i as modelLocalRelationEntityType, j as modelScalarFieldEntityType, k as modelEntityType, l as modelTransformerEntityType, n as modelEnumValueEntityType, o as modelEnumEntityType, p as featureEntityType, q as modelUniqueConstraintEntityType, r as runInPluginContext, t as createFeaturesSchema, M as ModelUtils, u as omit, v as cloneDeep } from '../model-merger-BwRNqcBu.js';
2
+ export { S as DefinitionDiffArrayIncludesField, P as DefinitionDiffKeyedArrayField, Q as DefinitionDiffReplacementField, B as DefinitionEntityType, F as FeatureUtils, V as applyDefinitionDiff, L as applyModelMergerDiff, N as applyModelMergerResultInPlace, O as createAndApplyModelMergerResults, U as createDefinitionDiff, T as createDefinitionDiffConfig, G as createFeatureSchema, I as createModelMergerResult, K as createModelMergerResults, y as createPluginFieldMap, x as createPluginSpec, z as createRefContextSlot, A as createRefContextSlotMap, J as doesModelMergerResultsHaveChanges, E as featureNameSchema, w as getPluginContext, H as modelMergerDefinitionDiffConfig, C as withPlaceholderSlots } from '../model-merger-BwRNqcBu.js';
3
+ import { importShared } from '../__federation_fn_import-DsXcpNlB.js';
4
+ import { i as isEqual } from '../isEqual-BQtm2LNT.js';
5
5
  import { s as sortBy } from '../sortBy-BPH_zRB8.js';
6
6
 
7
- function createAdminCrudActionCompilerImplementation() {
8
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
- const actions = new Map();
10
- return {
11
- registerCompiler(action) {
12
- if (actions.has(action.name)) {
13
- throw new Error(`Admin CRUD action with name ${action.name} is already registered`);
14
- }
15
- actions.set(action.name, action);
16
- },
17
- getCompiler(name, builtInActions = []) {
18
- const builtInAction = builtInActions.find((b) => b.name === name);
19
- if (builtInAction) {
20
- return builtInAction;
21
- }
22
- const action = actions.get(name);
23
- if (!action) {
24
- throw new Error(`Unable to find action with name ${name}`);
25
- }
26
- return action;
27
- },
28
- };
29
- }
30
- /**
31
- * Spec for adding config component for plugin
32
- */
33
- const adminCrudActionCompilerSpec = createPluginSpec('core/admin-crud-action-compiler', { defaultInitializer: createAdminCrudActionCompilerImplementation });
7
+ const adminCrudActionCompilerSpec = createFieldMapSpec('core/admin-crud-action-compiler', (t) => ({
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- plugins register varying action types at runtime
9
+ actions: t.namedArrayToMap(),
10
+ }));
34
11
 
35
12
  function createAdminCrudColumnCompiler(input) {
36
13
  return input;
37
14
  }
38
- function createAdminCrudColumnCompilerImplementation() {
39
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
- const columns = new Map();
41
- return {
42
- registerCompiler(column) {
43
- if (columns.has(column.name)) {
44
- throw new Error(`Admin CRUD column with name ${column.name} is already registered`);
45
- }
46
- columns.set(column.name, column);
47
- },
48
- getCompiler(type, builtInColumns = []) {
49
- const builtInColumn = builtInColumns.find((b) => b.name === type);
50
- if (builtInColumn) {
51
- return builtInColumn;
52
- }
53
- const column = columns.get(type);
54
- if (!column) {
55
- throw new Error(`Unable to find column with type ${type}`);
56
- }
57
- return column;
58
- },
59
- getColumnCompilers() {
60
- return columns;
61
- },
62
- };
63
- }
64
15
  /**
65
- * Spec for adding column compilers
16
+ * Spec for registering admin CRUD column compilers
66
17
  */
67
- const adminCrudColumnCompilerSpec = createPluginSpec('core/admin-crud-column-compiler', { defaultInitializer: createAdminCrudColumnCompilerImplementation });
18
+ const adminCrudColumnCompilerSpec = createFieldMapSpec('core/admin-crud-column-compiler', (t) => ({
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- plugins register varying column types at runtime
20
+ columns: t.namedArrayToMap(),
21
+ }));
68
22
 
69
- function createAdminCrudInputCompilerImplementation() {
70
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
71
- const inputs = new Map();
72
- return {
73
- registerCompiler(input) {
74
- if (inputs.has(input.name)) {
75
- throw new Error(`Admin CRUD input with name ${input.name} is already registered`);
76
- }
77
- inputs.set(input.name, input);
78
- },
79
- getCompiler(name, builtInInputs = []) {
80
- const builtInInput = builtInInputs.find((b) => b.name === name);
81
- if (builtInInput) {
82
- return builtInInput;
83
- }
84
- const input = inputs.get(name);
85
- if (!input) {
86
- throw new Error(`Unable to find input with name ${name}`);
87
- }
88
- return input;
89
- },
90
- };
91
- }
92
23
  /**
93
- * Spec for adding config component for plugin
24
+ * Spec for registering admin CRUD input compilers
94
25
  */
95
- const adminCrudInputCompilerSpec = createPluginSpec('core/admin-crud-input-compiler', { defaultInitializer: createAdminCrudInputCompilerImplementation });
96
-
97
- function groupBy(arr, getKeyFromItem) {
98
- const result = {};
99
- for (let i = 0; i < arr.length; i++) {
100
- const item = arr[i];
101
- const key = getKeyFromItem(item);
102
- if (!Object.hasOwn(result, key)) {
103
- result[key] = [];
104
- }
105
- result[key].push(item);
106
- }
107
- return result;
108
- }
109
-
110
- function keyBy(arr, getKeyFromItem) {
111
- const result = {};
112
- for (let i = 0; i < arr.length; i++) {
113
- const item = arr[i];
114
- const key = getKeyFromItem(item);
115
- result[key] = item;
116
- }
117
- return result;
118
- }
119
-
120
- function uniq(arr) {
121
- return Array.from(new Set(arr));
122
- }
26
+ const adminCrudInputCompilerSpec = createFieldMapSpec('core/admin-crud-input-compiler', (t) => ({
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- plugins register varying input types at runtime
28
+ inputs: t.namedArrayToMap(),
29
+ }));
123
30
 
124
- function flow(...funcs) {
125
- return function (...args) {
126
- let result = funcs.length ? funcs[0].apply(this, args) : args[0];
127
- for (let i = 1; i < funcs.length; i++) {
128
- result = funcs[i].call(this, result);
129
- }
130
- return result;
31
+ const {safeMerge} = await importShared('@baseplate-dev/utils');
32
+ function createAppCompiler() {
33
+ const children = {};
34
+ let rootChildren = {};
35
+ return {
36
+ addChildrenToFeature(featureId, newChildren) {
37
+ children[featureId] = safeMerge(children[featureId] ?? {}, newChildren);
38
+ },
39
+ getChildrenForFeature(featureId) {
40
+ return children[featureId] ?? {};
41
+ },
42
+ addRootChildren(newChildren) {
43
+ rootChildren = safeMerge(rootChildren, newChildren);
44
+ },
45
+ getRootChildren() {
46
+ return rootChildren;
47
+ },
131
48
  };
132
49
  }
133
-
134
- function pickBy(obj, shouldPick) {
135
- const result = {};
136
- const keys = Object.keys(obj);
137
- for (let i = 0; i < keys.length; i++) {
138
- const key = keys[i];
139
- const value = obj[key];
140
- if (shouldPick(value, key)) {
141
- result[key] = value;
142
- }
143
- }
144
- return result;
145
- }
146
-
147
- /**
148
- * Strip object of any values that are empty arrays, empty objects, null, or undefined
149
- */
150
- function stripEmptyGeneratorChildren(children) {
151
- return pickBy(children, (value) => value !== undefined && !(Array.isArray(value) && value.length === 0));
152
- }
153
- /**
154
- * Strip object of any values that are undefined
155
- */
156
- function stripUndefinedValues(obj) {
157
- return pickBy(obj, (value) => value !== undefined);
158
- }
159
- /**
160
- * Returns undefined if the value is an empty object (as defined by all values are undefined)/array/null, otherwise return value.
161
- */
162
- function undefinedIfEmpty(value) {
163
- if (value === null)
164
- return undefined;
165
- if (Array.isArray(value) && value.length === 0) {
166
- return undefined;
167
- }
168
- if (typeof value === 'object' &&
169
- Object.keys(value).every((key) => value[key] === undefined)) {
170
- return undefined;
171
- }
172
- return value;
173
- }
174
- /**
175
- * Returns undefined if the value is falsy, otherwise return value.
176
- */
177
- function undefinedIfFalsy(value) {
178
- if (!value)
179
- return undefined;
180
- return value;
181
- }
182
-
183
- class PluginImplementationStore {
184
- implementations;
185
- constructor(implementations) {
186
- this.implementations = implementations;
187
- }
188
- getPluginSpec(spec) {
189
- const implementation = this.implementations[spec.name];
190
- if (!implementation) {
191
- throw new Error(`Unable to find implementation for spec ${spec.name}`);
192
- }
193
- return implementation;
194
- }
195
- getPluginSpecOptional(spec) {
196
- return this.implementations[spec.name];
197
- }
198
- }
199
-
200
- const {toposortOrdered} = await importShared('@baseplate-dev/utils');
201
- function extractPlatformModulesFromPlugins(plugins) {
202
- return plugins.flatMap((plugin) => plugin.pluginModules.map((m) => ({
203
- ...m,
204
- id: `${plugin.key}/${m.key}`,
205
- name: `${plugin.name}/${m.key}`,
206
- pluginKey: plugin.key,
207
- pluginName: plugin.name,
208
- })));
209
- }
210
- function getOrderedPluginModuleInitializationSteps(pluginModules, initialSpecImplementations) {
211
- const pluginModulesById = keyBy(pluginModules, (p) => p.id);
212
- // create export map of plugin ID to export spec name
213
- const pluginModuleIdByExport = mapValues(initialSpecImplementations, () => 'built-in');
214
- for (const { name, module, id } of pluginModules) {
215
- for (const m of Object.values(module.exports ?? {})) {
216
- const exportName = m.name;
217
- if (exportName in pluginModuleIdByExport) {
218
- const existingPlugin = pluginModulesById[pluginModuleIdByExport[exportName]];
219
- throw new Error(`Duplicate export from plugins found ${exportName} (${name} and ${existingPlugin.name})`);
220
- }
221
- pluginModuleIdByExport[exportName] = id;
222
- }
223
- }
224
- // create list of plugin to plugin dependencies
225
- const edges = pluginModules.flatMap(({ module, name, id }) => Object.values(module.dependencies ?? {})
226
- .map((m) => {
227
- const resolvedDep = pluginModuleIdByExport[m.name];
228
- if (!resolvedDep) {
229
- if (m.isOptional) {
230
- return undefined;
231
- }
232
- throw new Error(`Cannot resolve plugin dependency for ${name} (${m.name})`);
233
- }
234
- if (resolvedDep === 'built-in') {
235
- return undefined;
236
- }
237
- return [resolvedDep, id];
238
- })
239
- .filter((x) => x !== undefined));
240
- const nodes = pluginModules.map((p) => p.id);
241
- return toposortOrdered(nodes, edges);
242
- }
243
- function initializeOrderedPluginModules(orderedPluginModules, initialSpecImplementations) {
244
- const specImplementations = { ...initialSpecImplementations };
245
- for (const { name, module, pluginKey } of orderedPluginModules) {
246
- const dependencies = module.dependencies
247
- ? stripUndefinedValues(mapValues(module.dependencies, (dep) => {
248
- const implementation = specImplementations[dep.name];
249
- if (!implementation && !dep.isOptional) {
250
- throw new Error(`Plugin ${name} missing dependency ${dep.name}`);
251
- }
252
- return implementation;
253
- }))
254
- : {};
255
- const context = { pluginKey };
256
- const exports = module.initialize(dependencies, context);
257
- Object.entries(module.exports ?? {}).map(([key, spec]) => {
258
- const exportedImplementation = exports[key];
259
- if (!exportedImplementation) {
260
- throw new Error(`Plugin ${name} did not return required export ${key}`);
261
- }
262
- specImplementations[spec.name] = exportedImplementation;
263
- });
264
- }
265
- return specImplementations;
266
- }
267
- /**
268
- * Initialize the plugins based on their interdependencies and creates a store of the plugin implementations
269
- */
270
- function initializePlugins(plugins, initialSpecImplementations) {
271
- const pluginModules = extractPlatformModulesFromPlugins(plugins);
272
- const pluginModulesById = keyBy(pluginModules, (p) => p.id);
273
- const orderedModuleIds = getOrderedPluginModuleInitializationSteps(pluginModules, initialSpecImplementations);
274
- const specImplementations = initializeOrderedPluginModules(orderedModuleIds.map((p) => pluginModulesById[p]), initialSpecImplementations);
275
- return new PluginImplementationStore(specImplementations);
276
- }
277
-
278
- function createPlatformPluginExport(config) {
279
- return config;
280
- }
281
-
282
- /**
283
- * Gets a plugin metadata object by its key.
284
- *
285
- * @param pluginStore The plugin store to use
286
- * @param key The key of the plugin to get
287
- * @returns The plugin metadata object or undefined if the plugin is not found
288
- */
289
- function getPluginMetadataByKey(pluginStore, key) {
290
- return pluginStore.availablePlugins.find((p) => p.metadata.key === key)
291
- ?.metadata;
50
+ function pluginAppCompiler(options) {
51
+ return options;
292
52
  }
293
53
  /**
294
- * Gets a plugin metadata object by its key.
295
- *
296
- * @param pluginStore The plugin store to use
297
- * @param key The key of the plugin to get
298
- * @returns The plugin metadata object
299
- * @throws An error if the plugin is not found
54
+ * Spec for registering app compilers
300
55
  */
301
- function getPluginMetadataByKeyOrThrow(pluginStore, key) {
302
- const metadata = getPluginMetadataByKey(pluginStore, key);
303
- if (!metadata) {
304
- throw new Error(`Could not find plugin with key ${key}`);
305
- }
306
- return metadata;
307
- }
308
- function getManagedPluginsForPlugin(pluginStore, pluginKey) {
309
- const plugin = getPluginMetadataByKeyOrThrow(pluginStore, pluginKey);
310
- return pluginStore.availablePlugins
311
- .filter((p) => p.metadata.managedBy === plugin.fullyQualifiedName)
312
- .map((p) => p.metadata);
313
- }
314
-
315
- const {z: z$u} = await importShared('zod');
316
-
317
- // matches semver
318
- const versionSchema = z$u.string().regex(/^(\d+\.\d+\.\d+)$/);
319
- const pluginSpecSupportSchema = z$u.object({
320
- spec: z$u.string().min(1),
321
- version: z$u.string().min(1),
322
- });
323
- const pluginSpecDependencySchema = z$u.object({
324
- spec: z$u.string(),
325
- version: z$u.string(),
56
+ const appCompilerSpec = createFieldMapSpec('core/app-compiler', (t) => ({
57
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- plugins register varying app definition types at runtime
58
+ compilers: t.array(),
59
+ }), {
60
+ use: (values) => ({
61
+ getAppCompilers: (appType) => values.compilers.filter((c) => c.appType === appType),
62
+ }),
326
63
  });
64
+
327
65
  /**
328
- * Schema for the plugin's metadata (plugin.json)
66
+ * Spec for registering model transformer compilers
329
67
  */
330
- const pluginMetadataSchema = z$u.object({
331
- /**
332
- * The name of the plugin - must be lowercase and contain only letters, numbers, and hyphens
333
- */
334
- name: z$u
335
- .string()
336
- .min(1)
337
- .regex(/^[a-z0-9-]+$/),
338
- /**
339
- * A list of directories with entrypoints in them. Defaults to ['.']
340
- */
341
- moduleDirectories: z$u.array(z$u.string()).optional(),
342
- /**
343
- * The display name of the plugin
344
- */
345
- displayName: z$u.string().min(1),
346
- /**
347
- * The icon to display for the plugin as a pointer to the icon in the plugin's static folder
348
- */
349
- icon: z$u.string().optional(),
350
- /**
351
- * A description of the plugin
352
- */
353
- description: z$u.string(),
354
- /**
355
- * The fully qualified name of the plugin that manages this plugin,
356
- * e.g. "@baseplate-dev/plugin-auth:auth0" would be managed by the "@baseplate-dev/plugin-auth:auth" plugin.
357
- *
358
- * Managed plugins do not appear in the plugin list but are managed by the base plugin. If the base
359
- * plugin is disabled, the managed plugins will also be disabled.
360
- */
361
- managedBy: z$u.string().optional(),
362
- /**
363
- * The version of the plugin using semver
364
- */
365
- version: versionSchema,
366
- /**
367
- * Configuration for the specs that the plugin exports/depends on
368
- */
369
- specs: z$u
370
- .object({
371
- /**
372
- * The specs that the plugin exports
373
- */
374
- exports: z$u.array(pluginSpecSupportSchema).optional(),
375
- /**
376
- * The specs that the plugin depends on
377
- */
378
- dependencies: z$u.array(pluginSpecDependencySchema).optional(),
379
- })
380
- .optional(),
381
- /**
382
- * Whether the plugin should be hidden in the project builder UI
383
- *
384
- * (It can be used once in the definition but cannot be added)
385
- */
386
- hidden: z$u.boolean().optional(),
387
- });
388
-
389
- var NOTHING = Symbol.for("immer-nothing");
390
- var DRAFTABLE = Symbol.for("immer-draftable");
391
- var DRAFT_STATE = Symbol.for("immer-state");
392
- function die(error, ...args) {
393
- throw new Error(
394
- `[Immer] minified error nr: ${error}. Full error at: https://bit.ly/3cXEKWf`
395
- );
396
- }
397
- var getPrototypeOf = Object.getPrototypeOf;
398
- function isDraft(value) {
399
- return !!value && !!value[DRAFT_STATE];
400
- }
401
- function isDraftable(value) {
402
- if (!value)
403
- return false;
404
- return isPlainObject(value) || Array.isArray(value) || !!value[DRAFTABLE] || !!value.constructor?.[DRAFTABLE] || isMap(value) || isSet(value);
405
- }
406
- var objectCtorString = Object.prototype.constructor.toString();
407
- function isPlainObject(value) {
408
- if (!value || typeof value !== "object")
409
- return false;
410
- const proto = getPrototypeOf(value);
411
- if (proto === null) {
412
- return true;
413
- }
414
- const Ctor = Object.hasOwnProperty.call(proto, "constructor") && proto.constructor;
415
- if (Ctor === Object)
416
- return true;
417
- return typeof Ctor == "function" && Function.toString.call(Ctor) === objectCtorString;
418
- }
419
- function each(obj, iter) {
420
- if (getArchtype(obj) === 0) {
421
- Reflect.ownKeys(obj).forEach((key) => {
422
- iter(key, obj[key], obj);
423
- });
424
- } else {
425
- obj.forEach((entry, index) => iter(index, entry, obj));
426
- }
427
- }
428
- function getArchtype(thing) {
429
- const state = thing[DRAFT_STATE];
430
- return state ? state.type_ : Array.isArray(thing) ? 1 : isMap(thing) ? 2 : isSet(thing) ? 3 : 0;
431
- }
432
- function has(thing, prop) {
433
- return getArchtype(thing) === 2 ? thing.has(prop) : Object.prototype.hasOwnProperty.call(thing, prop);
434
- }
435
- function set(thing, propOrOldValue, value) {
436
- const t = getArchtype(thing);
437
- if (t === 2)
438
- thing.set(propOrOldValue, value);
439
- else if (t === 3) {
440
- thing.add(value);
441
- } else
442
- thing[propOrOldValue] = value;
443
- }
444
- function is(x, y) {
445
- if (x === y) {
446
- return x !== 0 || 1 / x === 1 / y;
447
- } else {
448
- return x !== x && y !== y;
449
- }
450
- }
451
- function isMap(target) {
452
- return target instanceof Map;
453
- }
454
- function isSet(target) {
455
- return target instanceof Set;
456
- }
457
- function latest(state) {
458
- return state.copy_ || state.base_;
459
- }
460
- function shallowCopy(base, strict) {
461
- if (isMap(base)) {
462
- return new Map(base);
463
- }
464
- if (isSet(base)) {
465
- return new Set(base);
466
- }
467
- if (Array.isArray(base))
468
- return Array.prototype.slice.call(base);
469
- const isPlain = isPlainObject(base);
470
- if (strict === true || strict === "class_only" && !isPlain) {
471
- const descriptors = Object.getOwnPropertyDescriptors(base);
472
- delete descriptors[DRAFT_STATE];
473
- let keys = Reflect.ownKeys(descriptors);
474
- for (let i = 0; i < keys.length; i++) {
475
- const key = keys[i];
476
- const desc = descriptors[key];
477
- if (desc.writable === false) {
478
- desc.writable = true;
479
- desc.configurable = true;
480
- }
481
- if (desc.get || desc.set)
482
- descriptors[key] = {
483
- configurable: true,
484
- writable: true,
485
- // could live with !!desc.set as well here...
486
- enumerable: desc.enumerable,
487
- value: base[key]
488
- };
489
- }
490
- return Object.create(getPrototypeOf(base), descriptors);
491
- } else {
492
- const proto = getPrototypeOf(base);
493
- if (proto !== null && isPlain) {
494
- return { ...base };
495
- }
496
- const obj = Object.create(proto);
497
- return Object.assign(obj, base);
498
- }
499
- }
500
- function freeze(obj, deep = false) {
501
- if (isFrozen(obj) || isDraft(obj) || !isDraftable(obj))
502
- return obj;
503
- if (getArchtype(obj) > 1) {
504
- obj.set = obj.add = obj.clear = obj.delete = dontMutateFrozenCollections;
505
- }
506
- Object.freeze(obj);
507
- if (deep)
508
- Object.entries(obj).forEach(([key, value]) => freeze(value, true));
509
- return obj;
510
- }
511
- function dontMutateFrozenCollections() {
512
- die(2);
513
- }
514
- function isFrozen(obj) {
515
- return Object.isFrozen(obj);
516
- }
517
- var plugins = {};
518
- function getPlugin(pluginKey) {
519
- const plugin = plugins[pluginKey];
520
- if (!plugin) {
521
- die(0, pluginKey);
522
- }
523
- return plugin;
524
- }
525
- var currentScope;
526
- function getCurrentScope() {
527
- return currentScope;
528
- }
529
- function createScope(parent_, immer_) {
530
- return {
531
- drafts_: [],
532
- parent_,
533
- immer_,
534
- // Whenever the modified draft contains a draft from another scope, we
535
- // need to prevent auto-freezing so the unowned draft can be finalized.
536
- canAutoFreeze_: true,
537
- unfinalizedDrafts_: 0
538
- };
539
- }
540
- function usePatchesInScope(scope, patchListener) {
541
- if (patchListener) {
542
- getPlugin("Patches");
543
- scope.patches_ = [];
544
- scope.inversePatches_ = [];
545
- scope.patchListener_ = patchListener;
546
- }
547
- }
548
- function revokeScope(scope) {
549
- leaveScope(scope);
550
- scope.drafts_.forEach(revokeDraft);
551
- scope.drafts_ = null;
552
- }
553
- function leaveScope(scope) {
554
- if (scope === currentScope) {
555
- currentScope = scope.parent_;
556
- }
557
- }
558
- function enterScope(immer2) {
559
- return currentScope = createScope(currentScope, immer2);
560
- }
561
- function revokeDraft(draft) {
562
- const state = draft[DRAFT_STATE];
563
- if (state.type_ === 0 || state.type_ === 1)
564
- state.revoke_();
565
- else
566
- state.revoked_ = true;
567
- }
568
- function processResult(result, scope) {
569
- scope.unfinalizedDrafts_ = scope.drafts_.length;
570
- const baseDraft = scope.drafts_[0];
571
- const isReplaced = result !== void 0 && result !== baseDraft;
572
- if (isReplaced) {
573
- if (baseDraft[DRAFT_STATE].modified_) {
574
- revokeScope(scope);
575
- die(4);
576
- }
577
- if (isDraftable(result)) {
578
- result = finalize(scope, result);
579
- if (!scope.parent_)
580
- maybeFreeze(scope, result);
581
- }
582
- if (scope.patches_) {
583
- getPlugin("Patches").generateReplacementPatches_(
584
- baseDraft[DRAFT_STATE].base_,
585
- result,
586
- scope.patches_,
587
- scope.inversePatches_
588
- );
589
- }
590
- } else {
591
- result = finalize(scope, baseDraft, []);
592
- }
593
- revokeScope(scope);
594
- if (scope.patches_) {
595
- scope.patchListener_(scope.patches_, scope.inversePatches_);
596
- }
597
- return result !== NOTHING ? result : void 0;
598
- }
599
- function finalize(rootScope, value, path) {
600
- if (isFrozen(value))
601
- return value;
602
- const state = value[DRAFT_STATE];
603
- if (!state) {
604
- each(
605
- value,
606
- (key, childValue) => finalizeProperty(rootScope, state, value, key, childValue, path)
607
- );
608
- return value;
609
- }
610
- if (state.scope_ !== rootScope)
611
- return value;
612
- if (!state.modified_) {
613
- maybeFreeze(rootScope, state.base_, true);
614
- return state.base_;
615
- }
616
- if (!state.finalized_) {
617
- state.finalized_ = true;
618
- state.scope_.unfinalizedDrafts_--;
619
- const result = state.copy_;
620
- let resultEach = result;
621
- let isSet2 = false;
622
- if (state.type_ === 3) {
623
- resultEach = new Set(result);
624
- result.clear();
625
- isSet2 = true;
626
- }
627
- each(
628
- resultEach,
629
- (key, childValue) => finalizeProperty(rootScope, state, result, key, childValue, path, isSet2)
630
- );
631
- maybeFreeze(rootScope, result, false);
632
- if (path && rootScope.patches_) {
633
- getPlugin("Patches").generatePatches_(
634
- state,
635
- path,
636
- rootScope.patches_,
637
- rootScope.inversePatches_
638
- );
639
- }
640
- }
641
- return state.copy_;
642
- }
643
- function finalizeProperty(rootScope, parentState, targetObject, prop, childValue, rootPath, targetIsSet) {
644
- if (isDraft(childValue)) {
645
- const path = rootPath && parentState && parentState.type_ !== 3 && // Set objects are atomic since they have no keys.
646
- !has(parentState.assigned_, prop) ? rootPath.concat(prop) : void 0;
647
- const res = finalize(rootScope, childValue, path);
648
- set(targetObject, prop, res);
649
- if (isDraft(res)) {
650
- rootScope.canAutoFreeze_ = false;
651
- } else
652
- return;
653
- } else if (targetIsSet) {
654
- targetObject.add(childValue);
655
- }
656
- if (isDraftable(childValue) && !isFrozen(childValue)) {
657
- if (!rootScope.immer_.autoFreeze_ && rootScope.unfinalizedDrafts_ < 1) {
658
- return;
659
- }
660
- finalize(rootScope, childValue);
661
- if ((!parentState || !parentState.scope_.parent_) && typeof prop !== "symbol" && Object.prototype.propertyIsEnumerable.call(targetObject, prop))
662
- maybeFreeze(rootScope, childValue);
663
- }
664
- }
665
- function maybeFreeze(scope, value, deep = false) {
666
- if (!scope.parent_ && scope.immer_.autoFreeze_ && scope.canAutoFreeze_) {
667
- freeze(value, deep);
668
- }
669
- }
670
- function createProxyProxy(base, parent) {
671
- const isArray = Array.isArray(base);
672
- const state = {
673
- type_: isArray ? 1 : 0,
674
- // Track which produce call this is associated with.
675
- scope_: parent ? parent.scope_ : getCurrentScope(),
676
- // True for both shallow and deep changes.
677
- modified_: false,
678
- // Used during finalization.
679
- finalized_: false,
680
- // Track which properties have been assigned (true) or deleted (false).
681
- assigned_: {},
682
- // The parent draft state.
683
- parent_: parent,
684
- // The base state.
685
- base_: base,
686
- // The base proxy.
687
- draft_: null,
688
- // set below
689
- // The base copy with any updated values.
690
- copy_: null,
691
- // Called by the `produce` function.
692
- revoke_: null,
693
- isManual_: false
694
- };
695
- let target = state;
696
- let traps = objectTraps;
697
- if (isArray) {
698
- target = [state];
699
- traps = arrayTraps;
700
- }
701
- const { revoke, proxy } = Proxy.revocable(target, traps);
702
- state.draft_ = proxy;
703
- state.revoke_ = revoke;
704
- return proxy;
705
- }
706
- var objectTraps = {
707
- get(state, prop) {
708
- if (prop === DRAFT_STATE)
709
- return state;
710
- const source = latest(state);
711
- if (!has(source, prop)) {
712
- return readPropFromProto(state, source, prop);
713
- }
714
- const value = source[prop];
715
- if (state.finalized_ || !isDraftable(value)) {
716
- return value;
717
- }
718
- if (value === peek(state.base_, prop)) {
719
- prepareCopy(state);
720
- return state.copy_[prop] = createProxy(value, state);
721
- }
722
- return value;
723
- },
724
- has(state, prop) {
725
- return prop in latest(state);
726
- },
727
- ownKeys(state) {
728
- return Reflect.ownKeys(latest(state));
729
- },
730
- set(state, prop, value) {
731
- const desc = getDescriptorFromProto(latest(state), prop);
732
- if (desc?.set) {
733
- desc.set.call(state.draft_, value);
734
- return true;
735
- }
736
- if (!state.modified_) {
737
- const current2 = peek(latest(state), prop);
738
- const currentState = current2?.[DRAFT_STATE];
739
- if (currentState && currentState.base_ === value) {
740
- state.copy_[prop] = value;
741
- state.assigned_[prop] = false;
742
- return true;
743
- }
744
- if (is(value, current2) && (value !== void 0 || has(state.base_, prop)))
745
- return true;
746
- prepareCopy(state);
747
- markChanged(state);
748
- }
749
- if (state.copy_[prop] === value && // special case: handle new props with value 'undefined'
750
- (value !== void 0 || prop in state.copy_) || // special case: NaN
751
- Number.isNaN(value) && Number.isNaN(state.copy_[prop]))
752
- return true;
753
- state.copy_[prop] = value;
754
- state.assigned_[prop] = true;
755
- return true;
756
- },
757
- deleteProperty(state, prop) {
758
- if (peek(state.base_, prop) !== void 0 || prop in state.base_) {
759
- state.assigned_[prop] = false;
760
- prepareCopy(state);
761
- markChanged(state);
762
- } else {
763
- delete state.assigned_[prop];
764
- }
765
- if (state.copy_) {
766
- delete state.copy_[prop];
767
- }
768
- return true;
769
- },
770
- // Note: We never coerce `desc.value` into an Immer draft, because we can't make
771
- // the same guarantee in ES5 mode.
772
- getOwnPropertyDescriptor(state, prop) {
773
- const owner = latest(state);
774
- const desc = Reflect.getOwnPropertyDescriptor(owner, prop);
775
- if (!desc)
776
- return desc;
777
- return {
778
- writable: true,
779
- configurable: state.type_ !== 1 || prop !== "length",
780
- enumerable: desc.enumerable,
781
- value: owner[prop]
782
- };
783
- },
784
- defineProperty() {
785
- die(11);
786
- },
787
- getPrototypeOf(state) {
788
- return getPrototypeOf(state.base_);
789
- },
790
- setPrototypeOf() {
791
- die(12);
792
- }
793
- };
794
- var arrayTraps = {};
795
- each(objectTraps, (key, fn) => {
796
- arrayTraps[key] = function() {
797
- arguments[0] = arguments[0][0];
798
- return fn.apply(this, arguments);
799
- };
800
- });
801
- arrayTraps.deleteProperty = function(state, prop) {
802
- return arrayTraps.set.call(this, state, prop, void 0);
803
- };
804
- arrayTraps.set = function(state, prop, value) {
805
- return objectTraps.set.call(this, state[0], prop, value, state[0]);
806
- };
807
- function peek(draft, prop) {
808
- const state = draft[DRAFT_STATE];
809
- const source = state ? latest(state) : draft;
810
- return source[prop];
811
- }
812
- function readPropFromProto(state, source, prop) {
813
- const desc = getDescriptorFromProto(source, prop);
814
- return desc ? `value` in desc ? desc.value : (
815
- // This is a very special case, if the prop is a getter defined by the
816
- // prototype, we should invoke it with the draft as context!
817
- desc.get?.call(state.draft_)
818
- ) : void 0;
819
- }
820
- function getDescriptorFromProto(source, prop) {
821
- if (!(prop in source))
822
- return void 0;
823
- let proto = getPrototypeOf(source);
824
- while (proto) {
825
- const desc = Object.getOwnPropertyDescriptor(proto, prop);
826
- if (desc)
827
- return desc;
828
- proto = getPrototypeOf(proto);
829
- }
830
- return void 0;
831
- }
832
- function markChanged(state) {
833
- if (!state.modified_) {
834
- state.modified_ = true;
835
- if (state.parent_) {
836
- markChanged(state.parent_);
837
- }
838
- }
839
- }
840
- function prepareCopy(state) {
841
- if (!state.copy_) {
842
- state.copy_ = shallowCopy(
843
- state.base_,
844
- state.scope_.immer_.useStrictShallowCopy_
845
- );
846
- }
847
- }
848
- var Immer2 = class {
849
- constructor(config) {
850
- this.autoFreeze_ = true;
851
- this.useStrictShallowCopy_ = false;
852
- this.produce = (base, recipe, patchListener) => {
853
- if (typeof base === "function" && typeof recipe !== "function") {
854
- const defaultBase = recipe;
855
- recipe = base;
856
- const self = this;
857
- return function curriedProduce(base2 = defaultBase, ...args) {
858
- return self.produce(base2, (draft) => recipe.call(this, draft, ...args));
859
- };
860
- }
861
- if (typeof recipe !== "function")
862
- die(6);
863
- if (patchListener !== void 0 && typeof patchListener !== "function")
864
- die(7);
865
- let result;
866
- if (isDraftable(base)) {
867
- const scope = enterScope(this);
868
- const proxy = createProxy(base, void 0);
869
- let hasError = true;
870
- try {
871
- result = recipe(proxy);
872
- hasError = false;
873
- } finally {
874
- if (hasError)
875
- revokeScope(scope);
876
- else
877
- leaveScope(scope);
878
- }
879
- usePatchesInScope(scope, patchListener);
880
- return processResult(result, scope);
881
- } else if (!base || typeof base !== "object") {
882
- result = recipe(base);
883
- if (result === void 0)
884
- result = base;
885
- if (result === NOTHING)
886
- result = void 0;
887
- if (this.autoFreeze_)
888
- freeze(result, true);
889
- if (patchListener) {
890
- const p = [];
891
- const ip = [];
892
- getPlugin("Patches").generateReplacementPatches_(base, result, p, ip);
893
- patchListener(p, ip);
894
- }
895
- return result;
896
- } else
897
- die(1, base);
898
- };
899
- this.produceWithPatches = (base, recipe) => {
900
- if (typeof base === "function") {
901
- return (state, ...args) => this.produceWithPatches(state, (draft) => base(draft, ...args));
902
- }
903
- let patches, inversePatches;
904
- const result = this.produce(base, recipe, (p, ip) => {
905
- patches = p;
906
- inversePatches = ip;
907
- });
908
- return [result, patches, inversePatches];
909
- };
910
- if (typeof config?.autoFreeze === "boolean")
911
- this.setAutoFreeze(config.autoFreeze);
912
- if (typeof config?.useStrictShallowCopy === "boolean")
913
- this.setUseStrictShallowCopy(config.useStrictShallowCopy);
914
- }
915
- createDraft(base) {
916
- if (!isDraftable(base))
917
- die(8);
918
- if (isDraft(base))
919
- base = current(base);
920
- const scope = enterScope(this);
921
- const proxy = createProxy(base, void 0);
922
- proxy[DRAFT_STATE].isManual_ = true;
923
- leaveScope(scope);
924
- return proxy;
925
- }
926
- finishDraft(draft, patchListener) {
927
- const state = draft && draft[DRAFT_STATE];
928
- if (!state || !state.isManual_)
929
- die(9);
930
- const { scope_: scope } = state;
931
- usePatchesInScope(scope, patchListener);
932
- return processResult(void 0, scope);
933
- }
934
- /**
935
- * Pass true to automatically freeze all copies created by Immer.
936
- *
937
- * By default, auto-freezing is enabled.
938
- */
939
- setAutoFreeze(value) {
940
- this.autoFreeze_ = value;
941
- }
942
- /**
943
- * Pass true to enable strict shallow copy.
944
- *
945
- * By default, immer does not copy the object descriptors such as getter, setter and non-enumrable properties.
946
- */
947
- setUseStrictShallowCopy(value) {
948
- this.useStrictShallowCopy_ = value;
949
- }
950
- applyPatches(base, patches) {
951
- let i;
952
- for (i = patches.length - 1; i >= 0; i--) {
953
- const patch = patches[i];
954
- if (patch.path.length === 0 && patch.op === "replace") {
955
- base = patch.value;
956
- break;
957
- }
958
- }
959
- if (i > -1) {
960
- patches = patches.slice(i + 1);
961
- }
962
- const applyPatchesImpl = getPlugin("Patches").applyPatches_;
963
- if (isDraft(base)) {
964
- return applyPatchesImpl(base, patches);
965
- }
966
- return this.produce(
967
- base,
968
- (draft) => applyPatchesImpl(draft, patches)
969
- );
970
- }
971
- };
972
- function createProxy(value, parent) {
973
- const draft = isMap(value) ? getPlugin("MapSet").proxyMap_(value, parent) : isSet(value) ? getPlugin("MapSet").proxySet_(value, parent) : createProxyProxy(value, parent);
974
- const scope = parent ? parent.scope_ : getCurrentScope();
975
- scope.drafts_.push(draft);
976
- return draft;
977
- }
978
- function current(value) {
979
- if (!isDraft(value))
980
- die(10, value);
981
- return currentImpl(value);
982
- }
983
- function currentImpl(value) {
984
- if (!isDraftable(value) || isFrozen(value))
985
- return value;
986
- const state = value[DRAFT_STATE];
987
- let copy;
988
- if (state) {
989
- if (!state.modified_)
990
- return state.base_;
991
- state.finalized_ = true;
992
- copy = shallowCopy(value, state.scope_.immer_.useStrictShallowCopy_);
993
- } else {
994
- copy = shallowCopy(value, true);
995
- }
996
- each(copy, (key, childValue) => {
997
- set(copy, key, currentImpl(childValue));
998
- });
999
- if (state) {
1000
- state.finalized_ = false;
1001
- }
1002
- return copy;
1003
- }
1004
- var immer = new Immer2();
1005
- var produce = immer.produce;
1006
- immer.produceWithPatches.bind(
1007
- immer
1008
- );
1009
- immer.setAutoFreeze.bind(immer);
1010
- immer.setUseStrictShallowCopy.bind(immer);
1011
- immer.applyPatches.bind(immer);
1012
- immer.createDraft.bind(immer);
1013
- immer.finishDraft.bind(immer);
1014
-
1015
- const pluginEntityType = createEntityType('plugin');
1016
-
1017
- function sortAndValidateMigrations(migrations) {
1018
- // make sure migrations are sorted by version and they are all unique
1019
- const sortedMigrations = [...migrations].sort((a, b) => a.version - b.version);
1020
- if (sortedMigrations.some((m) => m.version <= 0)) {
1021
- throw new Error(`Migration version must be a positive integer`);
1022
- }
1023
- for (let i = 0; i < sortedMigrations.length - 1; i++) {
1024
- if (sortedMigrations[i].version === sortedMigrations[i + 1].version) {
1025
- throw new Error(`Migration versions must be unique`);
1026
- }
1027
- }
1028
- return sortedMigrations;
1029
- }
1030
- function createPluginConfigImplementation() {
1031
- const schemas = new Map();
1032
- const migrationsMap = new Map();
1033
- return {
1034
- registerSchemaCreator(pluginKey, schemaCreator) {
1035
- if (schemas.has(pluginKey)) {
1036
- throw new Error(`Schema for plugin ${pluginKey} is already registered`);
1037
- }
1038
- schemas.set(pluginKey, schemaCreator);
1039
- },
1040
- registerMigrations(pluginKey, migrations) {
1041
- if (migrationsMap.has(pluginKey)) {
1042
- throw new Error(`Migrations for plugin ${pluginKey} are already registered`);
1043
- }
1044
- const sortedMigrations = sortAndValidateMigrations(migrations);
1045
- migrationsMap.set(pluginKey, sortedMigrations);
1046
- },
1047
- getSchemaCreator(pluginKey) {
1048
- return schemas.get(pluginKey);
1049
- },
1050
- getMigrations(pluginKey) {
1051
- return migrationsMap.get(pluginKey);
1052
- },
1053
- getLastMigrationVersion(pluginKey) {
1054
- const migrations = migrationsMap.get(pluginKey);
1055
- return migrations?.[migrations.length - 1]?.version;
1056
- },
1057
- };
1058
- }
1059
- /**
1060
- * Spec for adding config for the plugin in the core plugin e.g.
1061
- * {
1062
- * "plugins": [{
1063
- * "id": "...",
1064
- * "config": {
1065
- * ...PluginConfig schema
1066
- * }
1067
- * }]
1068
- * }
1069
- */
1070
- const pluginConfigSpec = createPluginSpec('core/plugin-config', {
1071
- defaultInitializer: createPluginConfigImplementation,
1072
- });
1073
-
1074
- function runPluginMigrations(projectDefinition, pluginImplementationStore) {
1075
- const pluginConfigService = pluginImplementationStore.getPluginSpec(pluginConfigSpec);
1076
- return produce(projectDefinition, (draft) => {
1077
- for (const pluginDefinition of draft.plugins ?? []) {
1078
- const pluginMigrations = pluginConfigService.getMigrations(pluginEntityType.keyFromId(pluginDefinition.id));
1079
- const currentSchemaVersion = pluginDefinition.configSchemaVersion ?? -1;
1080
- if (!pluginMigrations)
1081
- continue;
1082
- const lastPluginMigration = pluginMigrations.at(-1);
1083
- if (!lastPluginMigration)
1084
- continue;
1085
- for (const migration of pluginMigrations) {
1086
- if (migration.version > currentSchemaVersion) {
1087
- try {
1088
- const migrationResult = migration.migrate(pluginDefinition.config, draft);
1089
- if (migrationResult.updatedConfig !== undefined) {
1090
- pluginDefinition.config = migrationResult.updatedConfig;
1091
- }
1092
- if (migrationResult.updateProjectDefinition) {
1093
- migrationResult.updateProjectDefinition(draft);
1094
- }
1095
- }
1096
- catch (error) {
1097
- throw new Error(`Error migrating plugin ${pluginDefinition.id} to version ${migration.version}: ${String(error)}`);
1098
- }
1099
- }
1100
- }
1101
- pluginDefinition.configSchemaVersion = lastPluginMigration.version;
1102
- }
1103
- });
1104
- }
1105
-
1106
- /**
1107
- * Spec for adding config component for plugin
1108
- */
1109
- const authConfigSpec = createPluginSpec('core/auth-config', {});
1110
-
1111
- /**
1112
- * Spec for adding user model config component for plugin
1113
- */
1114
- const authModelConfigSpec = createPluginSpec('core/auth-model-config', {});
1115
-
1116
- function createWebConfigImplementation() {
1117
- const components = new Map();
1118
- return {
1119
- registerWebConfigComponent(pluginKey, ConfigComponent) {
1120
- if (components.has(pluginKey)) {
1121
- throw new Error(`Web config component for plugin ${pluginKey} is already registered`);
1122
- }
1123
- components.set(pluginKey, ConfigComponent);
1124
- },
1125
- getWebConfigComponent(pluginKey) {
1126
- return components.get(pluginKey);
1127
- },
1128
- };
1129
- }
1130
- /**
1131
- * Spec for adding config component for plugin
1132
- */
1133
- const webConfigSpec = createPluginSpec('core/web-config', {
1134
- platforms: 'web',
1135
- defaultInitializer: createWebConfigImplementation,
1136
- });
1137
-
1138
- const {safeMerge} = await importShared('@baseplate-dev/utils');
1139
- function createAppCompiler() {
1140
- const children = {};
1141
- let rootChildren = {};
1142
- return {
1143
- addChildrenToFeature(featureId, newChildren) {
1144
- children[featureId] = safeMerge(children[featureId] ?? {}, newChildren);
1145
- },
1146
- getChildrenForFeature(featureId) {
1147
- return children[featureId] ?? {};
1148
- },
1149
- addRootChildren(newChildren) {
1150
- rootChildren = safeMerge(rootChildren, newChildren);
1151
- },
1152
- getRootChildren() {
1153
- return rootChildren;
1154
- },
1155
- };
1156
- }
1157
- function createAppCompilerPlugin() {
1158
- const compilers = new Map();
1159
- return {
1160
- registerAppCompiler(compiler) {
1161
- const appCompilers = compilers.get(compiler.appType) ?? [];
1162
- if (!compilers.has(compiler.appType)) {
1163
- compilers.set(compiler.appType, appCompilers);
1164
- }
1165
- appCompilers.push(compiler);
1166
- },
1167
- getAppCompilers(appType) {
1168
- return compilers.get(appType) ?? [];
1169
- },
1170
- };
1171
- }
1172
- /**
1173
- * Spec for modifying the app compiler
1174
- */
1175
- const appCompilerSpec = createPluginSpec('AppCompiler', {
1176
- defaultInitializer: createAppCompilerPlugin,
1177
- });
1178
-
1179
- function createModelTransformerCompilerImplementation() {
1180
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1181
- const transformers = new Map();
1182
- return {
1183
- registerTransformerCompiler(transformer) {
1184
- if (transformers.has(transformer.name)) {
1185
- throw new Error(`Model transformer with name ${transformer.name} is already registered`);
1186
- }
1187
- transformers.set(transformer.name, transformer);
1188
- },
1189
- getModelTransformerCompiler(name, builtInTransformers = []) {
1190
- const builtInTransformer = builtInTransformers.find((b) => b.name === name);
1191
- if (builtInTransformer) {
1192
- return builtInTransformer;
1193
- }
1194
- const transformer = transformers.get(name);
1195
- if (!transformer) {
1196
- throw new Error(`Unable to find transformer with name ${name}`);
1197
- }
1198
- return transformer;
1199
- },
1200
- };
1201
- }
1202
- /**
1203
- * Spec for adding config component for plugin
1204
- */
1205
- const modelTransformerCompilerSpec = createPluginSpec('core/model-transformer-compiler', { defaultInitializer: createModelTransformerCompilerImplementation });
68
+ const modelTransformerCompilerSpec = createFieldMapSpec('core/model-transformer-compiler', (t) => ({
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- plugins register varying transformer types at runtime
70
+ transformers: t.namedArrayToMap(),
71
+ }));
1206
72
 
1207
73
  // obtained from Tailwind (https://github.com/tailwindlabs/tailwindcss/blob/master/src/public/colors.js)
1208
74
  const PALETTE_SHADES = [
@@ -1756,595 +622,1270 @@ const THEME_COLORS = {
1756
622
  category: 'utility',
1757
623
  },
1758
624
  };
1759
- const THEME_COLOR_KEYS = Object.keys(THEME_COLORS);
625
+ const THEME_COLOR_KEYS = Object.keys(THEME_COLORS);
626
+
627
+ function cleanAndSplitPath(path) {
628
+ return path
629
+ .replace(/^\./, '')
630
+ .split('/')
631
+ .filter((segment) => segment !== '');
632
+ }
633
+ /**
634
+ * Computes the relative path from one path to another.
635
+ */
636
+ function computeRelativePath(fromPath, toPath) {
637
+ const fromSegments = cleanAndSplitPath(fromPath);
638
+ const toSegments = cleanAndSplitPath(toPath);
639
+ // Remove the common segments from the beginning
640
+ while (fromSegments.length > 0 &&
641
+ toSegments.length > 0 &&
642
+ fromSegments[0] === toSegments[0]) {
643
+ fromSegments.shift();
644
+ toSegments.shift();
645
+ }
646
+ // Add the necessary number of '../' to go up the directory hierarchy
647
+ const numParentDirs = fromSegments.length;
648
+ const parentDirs = Array.from({ length: numParentDirs }).fill('..');
649
+ // Construct the relative path
650
+ const relativePath = [...parentDirs, ...toSegments].join('/');
651
+ return relativePath;
652
+ }
653
+
654
+ function byId$2(projectDefinition, id) {
655
+ const config = projectDefinition.apps.find((app) => app.id === id);
656
+ if (!config) {
657
+ throw new Error(`Unable to find app with ID ${id}`);
658
+ }
659
+ return config;
660
+ }
661
+ function getBackendApp(projectDefinition) {
662
+ const backendApps = projectDefinition.apps.filter((a) => a.type === 'backend');
663
+ if (backendApps.length > 1 || backendApps.length === 0) {
664
+ throw new Error(`Only one backend app is supported and must exist`);
665
+ }
666
+ const backendApp = backendApps[0];
667
+ return backendApp;
668
+ }
669
+ /**
670
+ * Given an app config, get the relative directory of the app
671
+ *
672
+ * @param appConfig The app config
673
+ * @param monorepoSettings Optional monorepo settings to determine apps folder location
674
+ * @returns The directory of the app
675
+ */
676
+ function getAppDirectory(appConfig, monorepoSettings) {
677
+ const appsFolder = monorepoSettings?.appsFolder ?? 'apps';
678
+ return `${appsFolder}/${appConfig.name}`;
679
+ }
680
+ function getBackendRelativePath(appConfig, backendApp, monorepoSettings) {
681
+ const backendRelativePath = computeRelativePath(getAppDirectory(appConfig, monorepoSettings), getAppDirectory(backendApp, monorepoSettings));
682
+ return backendRelativePath;
683
+ }
684
+ const AppUtils = {
685
+ byId: byId$2,
686
+ getBackendApp,
687
+ getBackendRelativePath,
688
+ getAppDirectory,
689
+ };
690
+
691
+ function groupBy(arr, getKeyFromItem) {
692
+ const result = {};
693
+ for (let i = 0; i < arr.length; i++) {
694
+ const item = arr[i];
695
+ const key = getKeyFromItem(item);
696
+ if (!Object.hasOwn(result, key)) {
697
+ result[key] = [];
698
+ }
699
+ result[key].push(item);
700
+ }
701
+ return result;
702
+ }
703
+
704
+ function keyBy(arr, getKeyFromItem) {
705
+ const result = {};
706
+ for (let i = 0; i < arr.length; i++) {
707
+ const item = arr[i];
708
+ const key = getKeyFromItem(item);
709
+ result[key] = item;
710
+ }
711
+ return result;
712
+ }
713
+
714
+ function uniq(arr) {
715
+ return Array.from(new Set(arr));
716
+ }
717
+
718
+ function pickBy(obj, shouldPick) {
719
+ const result = {};
720
+ const keys = Object.keys(obj);
721
+ for (let i = 0; i < keys.length; i++) {
722
+ const key = keys[i];
723
+ const value = obj[key];
724
+ if (shouldPick(value, key)) {
725
+ result[key] = value;
726
+ }
727
+ }
728
+ return result;
729
+ }
730
+
731
+ function flow(...funcs) {
732
+ return function (...args) {
733
+ let result = funcs.length ? funcs[0].apply(this, args) : args[0];
734
+ for (let i = 1; i < funcs.length; i++) {
735
+ result = funcs[i].call(this, result);
736
+ }
737
+ return result;
738
+ };
739
+ }
740
+
741
+ const appEntityType = createEntityType('app');
742
+ function createAppEntryType(name) {
743
+ return name;
744
+ }
745
+
746
+ const {CASE_VALIDATORS: CASE_VALIDATORS$3} = await importShared('@baseplate-dev/utils');
747
+
748
+ const {z: z$v} = await importShared('zod');
749
+ const baseAppValidators = {
750
+ id: z$v.string().default(appEntityType.generateNewId()),
751
+ name: CASE_VALIDATORS$3.KEBAB_CASE,
752
+ type: z$v.string(),
753
+ };
754
+ const baseAppSchema = z$v.object(baseAppValidators);
755
+
756
+ const {z: z$u} = await importShared('zod');
757
+ const createBackendAppSchema = definitionSchemaWithSlots({ appSlot: appEntityType }, () => z$u.object({
758
+ ...baseAppValidators,
759
+ type: z$u.literal('backend'),
760
+ enableStripe: z$u.boolean().optional(),
761
+ enableSubscriptions: z$u.boolean().optional(),
762
+ enableAxios: z$u.boolean().optional(),
763
+ }));
764
+ const backendAppEntryType = createAppEntryType('backend');
765
+
766
+ const authRoleEntityType = createEntityType('role');
767
+
768
+ /**
769
+ * Creates a definition entity name resolver.
770
+ * @param entityNameResolver - The entity name resolver.
771
+ * @returns The definition entity name resolver.
772
+ */
773
+ function createDefinitionEntityNameResolver(entityNameResolver) {
774
+ return entityNameResolver;
775
+ }
776
+
777
+ function collectRefAnnotationsRecursive(pathPrefix, value) {
778
+ if (value === undefined || value === null)
779
+ return undefined;
780
+ if (value instanceof DefinitionReferenceMarker) {
781
+ return {
782
+ entities: [],
783
+ references: [
784
+ { ...value.reference, path: [...pathPrefix, ...value.reference.path] },
785
+ ],
786
+ slots: [],
787
+ };
788
+ }
789
+ const collected = {
790
+ entities: [],
791
+ references: [],
792
+ slots: [],
793
+ };
794
+ if (Array.isArray(value)) {
795
+ for (const [i, element] of value.entries()) {
796
+ const childCollected = collectRefAnnotationsRecursive([...pathPrefix, i], element);
797
+ if (childCollected) {
798
+ collected.entities.push(...childCollected.entities);
799
+ collected.references.push(...childCollected.references);
800
+ collected.slots.push(...childCollected.slots);
801
+ }
802
+ }
803
+ return collected;
804
+ }
805
+ if (typeof value === 'object') {
806
+ if (REF_ANNOTATIONS_MARKER_SYMBOL in value) {
807
+ const annotations = value[REF_ANNOTATIONS_MARKER_SYMBOL];
808
+ collected.entities.push(...annotations.entities.map((entity) => ({
809
+ ...entity,
810
+ path: [...pathPrefix, ...entity.path],
811
+ })));
812
+ collected.references.push(...annotations.references.map((reference) => ({
813
+ ...reference,
814
+ path: [...pathPrefix, ...reference.path],
815
+ })));
816
+ collected.slots.push(...annotations.slots.map((slot) => ({
817
+ ...slot,
818
+ path: [...pathPrefix, ...slot.path],
819
+ })));
820
+ }
821
+ for (const [key, childValue] of Object.entries(value)) {
822
+ if (typeof key !== 'string')
823
+ continue;
824
+ const childCollected = collectRefAnnotationsRecursive([...pathPrefix, key], childValue);
825
+ if (childCollected) {
826
+ collected.entities.push(...childCollected.entities);
827
+ collected.references.push(...childCollected.references);
828
+ collected.slots.push(...childCollected.slots);
829
+ }
830
+ }
831
+ return collected;
832
+ }
833
+ return undefined;
834
+ }
835
+ function collectRefs(value) {
836
+ return (collectRefAnnotationsRecursive([], value) ?? {
837
+ entities: [],
838
+ references: [],
839
+ slots: [],
840
+ });
841
+ }
842
+
843
+ const {mapGroupBy} = await importShared('@baseplate-dev/utils');
844
+
845
+ /**
846
+ * Calculates the length of the common prefix of two paths.
847
+ *
848
+ * @param a - The first path
849
+ * @param b - The second path
850
+ * @returns The length of the common prefix of the two paths
851
+ */
852
+ function commonPrefixLength(a, b) {
853
+ let length = 0;
854
+ const maxLength = Math.min(a.length, b.length);
855
+ for (let i = 0; i < maxLength; i++) {
856
+ if (a[i] !== b[i])
857
+ break;
858
+ length++;
859
+ }
860
+ return length;
861
+ }
862
+ /**
863
+ * Finds the nearest ancestor slot for a given target path.
864
+ *
865
+ * @param candidateSlots - The candidate slots to search through.
866
+ * @param targetPath - The target path to find the nearest ancestor slot for.
867
+ * @returns The nearest ancestor slot, or undefined if no slot is found.
868
+ */
869
+ function findNearestAncestorSlot(candidateSlots = [], targetPath) {
870
+ let bestMatch;
871
+ for (const candidateSlot of candidateSlots) {
872
+ const prefixLength = commonPrefixLength(candidateSlot.path, targetPath);
873
+ // A slot at path [] (root) is a valid ancestor of any path
874
+ // For non-root slots, require at least 1 common prefix element
875
+ const isValidAncestor = candidateSlot.path.length === 0 || prefixLength > 0;
876
+ if (isValidAncestor &&
877
+ (!bestMatch || prefixLength > bestMatch.prefixLength)) {
878
+ bestMatch = { prefixLength, slot: candidateSlot };
879
+ }
880
+ }
881
+ return bestMatch?.slot;
882
+ }
883
+ /**
884
+ * Resolves all slot references to actual paths.
885
+ *
886
+ * This function takes the collected refs (which have `parentSlot` references)
887
+ * and resolves them to `parentPath` values using the slotPaths map.
888
+ *
889
+ * For scoped slots (where the same slot can be registered multiple times),
890
+ * we find the registration whose path is the nearest ancestor of the entity/reference.
891
+ *
892
+ * @param collected - The collected refs with unresolved slots.
893
+ * @returns The resolved refs with parentPath instead of parentSlot.
894
+ * @throws If a required slot is not found in the slotPaths map.
895
+ */
896
+ function resolveSlots(collected) {
897
+ const { entities, references, slots } = collected;
898
+ // Collect all slots by path
899
+ const slotsByType = mapGroupBy(slots, (slot) => slot.slot.id);
900
+ const resolvedSlotsByType = new Map();
901
+ function registerSlot(slot, resolvedPath) {
902
+ const slotId = slot.id;
903
+ const candidateSlots = slotsByType.get(slotId) ?? [];
904
+ const nearestAncestorSlot = findNearestAncestorSlot(candidateSlots, resolvedPath);
905
+ if (!nearestAncestorSlot) {
906
+ throw new Error(`Could not find slot "${slotId.description ?? 'unknown'}" ` +
907
+ `within path ${resolvedPath.join('.')}. Make sure the slot is registered for this path.`);
908
+ }
909
+ const existingSlots = resolvedSlotsByType.get(slotId) ?? [];
910
+ resolvedSlotsByType.set(slotId, [
911
+ ...existingSlots,
912
+ { resolvedPath, path: nearestAncestorSlot.path },
913
+ ]);
914
+ }
915
+ // Collect entity provides
916
+ for (const entity of entities) {
917
+ if (entity.provides) {
918
+ registerSlot(entity.provides, [...entity.path, ...entity.idPath]);
919
+ }
920
+ }
921
+ // Collect reference provides
922
+ for (const reference of references) {
923
+ if (reference.provides) {
924
+ registerSlot(reference.provides, reference.path);
925
+ }
926
+ }
927
+ return resolvedSlotsByType;
928
+ }
1760
929
 
1761
- function cleanAndSplitPath(path) {
1762
- return path
1763
- .replace(/^\./, '')
1764
- .split('/')
1765
- .filter((segment) => segment !== '');
930
+ /**
931
+ * Extracts definition refs from a parsed value using functional approach.
932
+ *
933
+ * Flow:
934
+ * 1. Collect all refs (entities, references, slots) recursively
935
+ * 2. Resolve all slot references to actual paths
936
+ * 3. Strip ref markers from the data
937
+ * 4. Validate no duplicate IDs
938
+ *
939
+ * @param value - The parsed value from Zod schema
940
+ * @returns The extracted refs with clean data
941
+ */
942
+ function extractDefinitionRefs(value) {
943
+ // Step 1: Collect all refs without resolving slots
944
+ const collected = collectRefs(value);
945
+ // Step 2: Resolve all slots to paths
946
+ const resolvedSlots = resolveSlots(collected);
947
+ // Step 3: Strip markers from data
948
+ const cleanData = stripRefMarkers(value);
949
+ // Step 4: Resolve entity and reference parent paths
950
+ function resolveParentPath(parentSlot, path) {
951
+ const resolvedSlot = findNearestAncestorSlot(resolvedSlots.get(parentSlot.id), path);
952
+ if (!resolvedSlot) {
953
+ throw new Error(`Could not resolve parent path from ${path.join('.')} for slot ${parentSlot.id.description}`);
954
+ }
955
+ return resolvedSlot.resolvedPath;
956
+ }
957
+ const entitiesWithNameResolver = collected.entities.map((entity) => ({
958
+ id: entity.id,
959
+ idPath: entity.idPath,
960
+ nameResolver: entity.nameResolver,
961
+ type: entity.type,
962
+ path: entity.path,
963
+ parentPath: entity.parentSlot
964
+ ? resolveParentPath(entity.parentSlot, entity.path)
965
+ : undefined,
966
+ }));
967
+ const references = collected.references.map((reference) => ({
968
+ type: reference.type,
969
+ path: reference.path,
970
+ onDelete: reference.onDelete,
971
+ parentPath: reference.parentSlot
972
+ ? resolveParentPath(reference.parentSlot, reference.path)
973
+ : undefined,
974
+ }));
975
+ // Step 4: Validate no duplicate IDs
976
+ const idSet = new Set();
977
+ for (const entity of collected.entities) {
978
+ if (idSet.has(entity.id)) {
979
+ throw new Error(`Duplicate ID found: ${entity.id}`);
980
+ }
981
+ idSet.add(entity.id);
982
+ }
983
+ return {
984
+ data: cleanData,
985
+ references,
986
+ entitiesWithNameResolver,
987
+ };
1766
988
  }
989
+
990
+ const {toposort: toposort$1} = await importShared('@baseplate-dev/utils');
1767
991
  /**
1768
- * Computes the relative path from one path to another.
992
+ * Resolves entity names in a ZodRefPayload.
993
+ *
994
+ * @param payload - The ZodRefPayload to resolve.
995
+ * @param options - The options for resolving entity names.
996
+ *
997
+ * @template T - The type of the payload.
1769
998
  */
1770
- function computeRelativePath(fromPath, toPath) {
1771
- const fromSegments = cleanAndSplitPath(fromPath);
1772
- const toSegments = cleanAndSplitPath(toPath);
1773
- // Remove the common segments from the beginning
1774
- while (fromSegments.length > 0 &&
1775
- toSegments.length > 0 &&
1776
- fromSegments[0] === toSegments[0]) {
1777
- fromSegments.shift();
1778
- toSegments.shift();
999
+ function resolveZodRefPayloadNames(payload, { skipReferenceNameResolution = false, allowInvalidReferences = false, } = {}) {
1000
+ const { entitiesWithNameResolver, references, data } = payload;
1001
+ const entitiesById = keyBy(entitiesWithNameResolver, (entity) => entity.id);
1002
+ const resolvedEntitiesById = new Map();
1003
+ // sort entities by dependency order
1004
+ const orderedEntities = toposort$1(entitiesWithNameResolver.map((entity) => entity.id), entitiesWithNameResolver.flatMap((entity) => {
1005
+ if (typeof entity.nameResolver !== 'object') {
1006
+ return [];
1007
+ }
1008
+ const entityIds = entity.nameResolver.idsToResolve ?? {};
1009
+ return Object.values(entityIds)
1010
+ .flat()
1011
+ .filter((id) => id in entitiesById)
1012
+ .map((id) => [id, entity.id]);
1013
+ }));
1014
+ function resolveIdToName(id) {
1015
+ if (skipReferenceNameResolution) {
1016
+ return id;
1017
+ }
1018
+ const entity = resolvedEntitiesById.get(id);
1019
+ if (!entity) {
1020
+ if (allowInvalidReferences) {
1021
+ return id;
1022
+ }
1023
+ throw new Error(`Could not resolve entity name for id: ${id}`);
1024
+ }
1025
+ return entity.name;
1779
1026
  }
1780
- // Add the necessary number of '../' to go up the directory hierarchy
1781
- const numParentDirs = fromSegments.length;
1782
- const parentDirs = Array.from({ length: numParentDirs }).fill('..');
1783
- // Construct the relative path
1784
- const relativePath = [...parentDirs, ...toSegments].join('/');
1785
- return relativePath;
1027
+ for (const id of orderedEntities) {
1028
+ const { nameResolver, ...rest } = entitiesById[id];
1029
+ if (typeof nameResolver === 'string') {
1030
+ resolvedEntitiesById.set(rest.id, {
1031
+ ...rest,
1032
+ name: nameResolver,
1033
+ });
1034
+ }
1035
+ else {
1036
+ const resolvedIds = mapValues(nameResolver.idsToResolve ?? {}, (idOrIds) => Array.isArray(idOrIds)
1037
+ ? idOrIds.map((id) => resolveIdToName(id))
1038
+ : resolveIdToName(idOrIds));
1039
+ resolvedEntitiesById.set(rest.id, {
1040
+ ...rest,
1041
+ name: nameResolver.resolveName(resolvedIds),
1042
+ });
1043
+ }
1044
+ }
1045
+ return {
1046
+ entities: [...resolvedEntitiesById.values()],
1047
+ references,
1048
+ data,
1049
+ };
1050
+ }
1051
+
1052
+ /**
1053
+ * Parses a schema with references.
1054
+ *
1055
+ * @param schema - The schema to parse.
1056
+ * @param input - The input to parse.
1057
+ * @param options - The options for parsing the schema.
1058
+ *
1059
+ * @returns The parsed data.
1060
+ */
1061
+ function parseSchemaWithTransformedReferences(schemaCreator, input, schemaCreatorOptions, options) {
1062
+ const schemaContext = createDefinitionSchemaParserContext({
1063
+ ...schemaCreatorOptions,
1064
+ transformReferences: true,
1065
+ });
1066
+ const schema = schemaCreator(schemaContext);
1067
+ const value = schema.parse(input);
1068
+ const refPayload = extractDefinitionRefs(value);
1069
+ return resolveZodRefPayloadNames(refPayload, options);
1070
+ }
1071
+
1072
+ const {toposort} = await importShared('@baseplate-dev/utils');
1073
+ function referenceToNameParentId(name, parentId) {
1074
+ return JSON.stringify({ name, parentId });
1075
+ }
1076
+ /**
1077
+ * Deserialize a schema with references using the new transform-based approach.
1078
+ * This function converts human-readable names back to entity IDs.
1079
+ *
1080
+ * @template T - The schema creator type
1081
+ * @param schemaCreator - The schema creator function
1082
+ * @param input - The input data with names instead of IDs
1083
+ * @param options - Options for the schema creator (excluding transformReferences)
1084
+ * @returns The resolved payload with IDs instead of names
1085
+ */
1086
+ function deserializeSchemaWithTransformedReferences(schemaCreator, input, options) {
1087
+ const payload = parseSchemaWithTransformedReferences(schemaCreator, input, options, {
1088
+ skipReferenceNameResolution: true,
1089
+ });
1090
+ // Use the same resolution logic as the original function
1091
+ return resolveReferencesToIds(payload);
1092
+ }
1093
+ /**
1094
+ * Internal function to resolve entity names to IDs in the payload.
1095
+ * This is shared logic between the old and new approaches.
1096
+ *
1097
+ * @param payload - The parsed payload with entities and references
1098
+ * @returns The payload with references resolved to IDs
1099
+ */
1100
+ function resolveReferencesToIds(payload) {
1101
+ const { references, entities, data } = payload;
1102
+ if (typeof data !== 'object' || data === null) {
1103
+ throw new TypeError('Data is not an object');
1104
+ }
1105
+ // check we don't have more entities than IDs
1106
+ const entitiesById = groupBy(entities, (entity) => entity.id);
1107
+ const duplicateEntityIds = Object.values(entitiesById).filter((e) => e.length > 1);
1108
+ if (duplicateEntityIds.length > 0) {
1109
+ throw new Error(`Found multiple duplicate entity IDs: ${duplicateEntityIds
1110
+ .map((ents) => `${ents[0].id} (${ents.map((e) => e.path.join('.')).join(',')})`)
1111
+ .join(', ')}`);
1112
+ }
1113
+ const uniqueEntityIds = uniq(entities.map((e) => e.id));
1114
+ if (uniqueEntityIds.length !== entities.length) {
1115
+ throw new Error(`Found duplicate entity IDs`);
1116
+ }
1117
+ // collect reference entity types
1118
+ const entityTypes = uniq(entities.map((e) => e.type));
1119
+ const entityTypeNames = uniq(entityTypes.map((t) => t.name));
1120
+ if (entityTypeNames.length !== entityTypes.length) {
1121
+ throw new Error(`Found more entity types than entity type names implying duplicate entity type name`);
1122
+ }
1123
+ const entityTypeOrder = toposort(entityTypeNames, entityTypes
1124
+ .filter((entityType) => !!entityType.parentType)
1125
+ .map((entityType) => [
1126
+ entityType.parentType?.name ?? '',
1127
+ entityType.name,
1128
+ ]));
1129
+ const entitiesByType = groupBy(entities, (e) => e.type.name);
1130
+ const referencesByType = groupBy(references, (r) => r.type.name);
1131
+ for (const name of entityTypeOrder) {
1132
+ const entities = entitiesByType[name] ?? [];
1133
+ const references = referencesByType[name] ?? [];
1134
+ // resolve references to their ID
1135
+ const entitiesByParentIdName = keyBy(entities, (e) => {
1136
+ const { parentPath } = e;
1137
+ const parentId = parentPath
1138
+ ? get(data, parentPath)
1139
+ : undefined;
1140
+ if (parentPath && typeof parentId !== 'string') {
1141
+ throw new Error(`Could not resolve parent path: ${parentPath.join('.')}`);
1142
+ }
1143
+ return referenceToNameParentId(e.name, parentId);
1144
+ });
1145
+ for (const ref of references) {
1146
+ const name = get(data, ref.path);
1147
+ // parent ID should have already been resolved due to order of resolving references
1148
+ const parentId = ref.parentPath && get(data, ref.parentPath);
1149
+ const parentIdName = referenceToNameParentId(name, parentId);
1150
+ const resolvedEntity = entitiesByParentIdName[parentIdName];
1151
+ if (!resolvedEntity) {
1152
+ throw new Error(`Unable to resolve reference: ${ref.path.join('.')} (${ref.type.name} ${parentIdName})`);
1153
+ }
1154
+ set$1(data, ref.path, resolvedEntity.id);
1155
+ }
1156
+ }
1157
+ return payload;
1786
1158
  }
1787
1159
 
1788
- function byId$2(projectDefinition, id) {
1789
- const config = projectDefinition.apps.find((app) => app.id === id);
1790
- if (!config) {
1791
- throw new Error(`Unable to find app with ID ${id}`);
1160
+ // sentinel ID to signify the reference has been flagged for deletion
1161
+ const DELETED_SENTINEL_ID = 'deleted-sentinel-id';
1162
+ /**
1163
+ * Fixes any reference deletions by performing the appropriate action for the reference
1164
+ */
1165
+ function fixRefDeletions(schemaCreator, value, schemaCreatorOptions) {
1166
+ const issues = [];
1167
+ // find all references that do not have a corresponding entity
1168
+ let iterations;
1169
+ let valueToEdit = value;
1170
+ for (iterations = 0; iterations < 100; iterations++) {
1171
+ const parseResult = parseSchemaWithTransformedReferences(schemaCreator, valueToEdit, schemaCreatorOptions, {
1172
+ allowInvalidReferences: true,
1173
+ });
1174
+ const { references, entities } = parseResult;
1175
+ valueToEdit = parseResult.data;
1176
+ const entitiesById = new Map(entities.map((e) => [e.id, e]));
1177
+ const referencesMissingEntity = references.filter((r) => {
1178
+ const id = get(valueToEdit, r.path);
1179
+ return id !== DELETED_SENTINEL_ID && !entitiesById.has(id);
1180
+ });
1181
+ if (referencesMissingEntity.length === 0) {
1182
+ if (issues.length > 0) {
1183
+ return {
1184
+ type: 'failure',
1185
+ issues,
1186
+ };
1187
+ }
1188
+ return {
1189
+ type: 'success',
1190
+ value: valueToEdit,
1191
+ refPayload: parseResult,
1192
+ };
1193
+ }
1194
+ const objectsToDeleteInArray = [];
1195
+ function tryDeleteParent(path) {
1196
+ if (path.length === 0) {
1197
+ return false;
1198
+ }
1199
+ const parentPath = path.slice(0, -1);
1200
+ const parent = get(valueToEdit, parentPath);
1201
+ if (!Array.isArray(parent)) {
1202
+ return false;
1203
+ }
1204
+ objectsToDeleteInArray.push({
1205
+ path: parentPath,
1206
+ idx: path.at(-1),
1207
+ });
1208
+ return true;
1209
+ }
1210
+ // attempt to fix reference
1211
+ for (const ref of referencesMissingEntity) {
1212
+ const id = get(valueToEdit, ref.path);
1213
+ switch (ref.onDelete) {
1214
+ case 'SET_UNDEFINED': {
1215
+ // Check if reference is inside an array
1216
+ if (ref.path.length > 0) {
1217
+ const parentPath = ref.path.slice(0, -1);
1218
+ const parent = get(valueToEdit, parentPath);
1219
+ if (Array.isArray(parent)) {
1220
+ throw new TypeError(`SET_UNDEFINED cannot be used for references inside arrays at path ${ref.path.join('.')}. Use DELETE instead to remove the array element.`);
1221
+ }
1222
+ }
1223
+ set$1(valueToEdit, ref.path, undefined);
1224
+ break;
1225
+ }
1226
+ case 'RESTRICT': {
1227
+ issues.push({ ref, entityId: id });
1228
+ set$1(valueToEdit, ref.path, DELETED_SENTINEL_ID);
1229
+ break;
1230
+ }
1231
+ case 'DELETE': {
1232
+ if (!tryDeleteParent(ref.path)) {
1233
+ throw new Error(`Unable to find ref to cascade delete to`);
1234
+ }
1235
+ break;
1236
+ }
1237
+ case 'DELETE_PARENT': {
1238
+ if (!tryDeleteParent(ref.path.slice(0, -1))) {
1239
+ throw new Error(`Unable to find ref to cascade delete to`);
1240
+ }
1241
+ break;
1242
+ }
1243
+ default: {
1244
+ throw new Error(`Unknown onDelete action ${ref.onDelete}`);
1245
+ }
1246
+ }
1247
+ }
1248
+ const objectsToDeleteByPath = groupBy(objectsToDeleteInArray, (o) => o.path.join('.'));
1249
+ // delete objects in reverse order to avoid index shifting
1250
+ for (const [, objects] of Object.entries(objectsToDeleteByPath)) {
1251
+ const sortedObjects = sortBy(objects, [(o) => -o.idx]);
1252
+ for (const o of sortedObjects) {
1253
+ const parent = get(valueToEdit, o.path);
1254
+ if (!Array.isArray(parent)) {
1255
+ throw new TypeError(`Expected parent to be an array at path ${o.path.join('.')}`);
1256
+ }
1257
+ parent.splice(o.idx, 1);
1258
+ }
1259
+ }
1792
1260
  }
1793
- return config;
1261
+ throw new Error(`Exceeded max iterations fixing deletions`);
1794
1262
  }
1795
- function getBackendApp(projectDefinition) {
1796
- const backendApps = projectDefinition.apps.filter((a) => a.type === 'backend');
1797
- if (backendApps.length > 1 || backendApps.length === 0) {
1798
- throw new Error(`Only one backend app is supported and must exist`);
1799
- }
1800
- const backendApp = backendApps[0];
1801
- return backendApp;
1263
+
1264
+ var NOTHING = Symbol.for("immer-nothing");
1265
+ var DRAFTABLE = Symbol.for("immer-draftable");
1266
+ var DRAFT_STATE = Symbol.for("immer-state");
1267
+ function die(error, ...args) {
1268
+ throw new Error(
1269
+ `[Immer] minified error nr: ${error}. Full error at: https://bit.ly/3cXEKWf`
1270
+ );
1802
1271
  }
1803
- /**
1804
- * Given an app config, get the relative directory of the app
1805
- *
1806
- * @param appConfig The app config
1807
- * @param monorepoSettings Optional monorepo settings to determine apps folder location
1808
- * @returns The directory of the app
1809
- */
1810
- function getAppDirectory(appConfig, monorepoSettings) {
1811
- const appsFolder = monorepoSettings?.appsFolder ?? 'apps';
1812
- return `${appsFolder}/${appConfig.name}`;
1272
+ var getPrototypeOf = Object.getPrototypeOf;
1273
+ function isDraft(value) {
1274
+ return !!value && !!value[DRAFT_STATE];
1813
1275
  }
1814
- function getBackendRelativePath(appConfig, backendApp, monorepoSettings) {
1815
- const backendRelativePath = computeRelativePath(getAppDirectory(appConfig, monorepoSettings), getAppDirectory(backendApp, monorepoSettings));
1816
- return backendRelativePath;
1276
+ function isDraftable(value) {
1277
+ if (!value)
1278
+ return false;
1279
+ return isPlainObject(value) || Array.isArray(value) || !!value[DRAFTABLE] || !!value.constructor?.[DRAFTABLE] || isMap(value) || isSet(value);
1817
1280
  }
1818
- const AppUtils = {
1819
- byId: byId$2,
1820
- getBackendApp,
1821
- getBackendRelativePath,
1822
- getAppDirectory,
1823
- };
1824
-
1825
- const appEntityType = createEntityType('app');
1826
- function createAppEntryType(name) {
1827
- return name;
1281
+ var objectCtorString = Object.prototype.constructor.toString();
1282
+ function isPlainObject(value) {
1283
+ if (!value || typeof value !== "object")
1284
+ return false;
1285
+ const proto = getPrototypeOf(value);
1286
+ if (proto === null) {
1287
+ return true;
1288
+ }
1289
+ const Ctor = Object.hasOwnProperty.call(proto, "constructor") && proto.constructor;
1290
+ if (Ctor === Object)
1291
+ return true;
1292
+ return typeof Ctor == "function" && Function.toString.call(Ctor) === objectCtorString;
1828
1293
  }
1829
-
1830
- const {CASE_VALIDATORS: CASE_VALIDATORS$3} = await importShared('@baseplate-dev/utils');
1831
-
1832
- const {z: z$t} = await importShared('zod');
1833
- const baseAppValidators = {
1834
- id: z$t.string().default(appEntityType.generateNewId()),
1835
- name: CASE_VALIDATORS$3.KEBAB_CASE,
1836
- type: z$t.string(),
1837
- };
1838
- const baseAppSchema = z$t.object(baseAppValidators);
1839
-
1840
- const {z: z$s} = await importShared('zod');
1841
- const createBackendAppSchema = definitionSchemaWithSlots({ appSlot: appEntityType }, () => z$s.object({
1842
- ...baseAppValidators,
1843
- type: z$s.literal('backend'),
1844
- enableStripe: z$s.boolean().optional(),
1845
- enablePostmark: z$s.boolean().optional(),
1846
- enableSubscriptions: z$s.boolean().optional(),
1847
- enableAxios: z$s.boolean().optional(),
1848
- }));
1849
- const backendAppEntryType = createAppEntryType('backend');
1850
-
1851
- const authRoleEntityType = createEntityType('role');
1852
-
1853
- /**
1854
- * Creates a definition entity name resolver.
1855
- * @param entityNameResolver - The entity name resolver.
1856
- * @returns The definition entity name resolver.
1857
- */
1858
- function createDefinitionEntityNameResolver(entityNameResolver) {
1859
- return entityNameResolver;
1294
+ function each(obj, iter) {
1295
+ if (getArchtype(obj) === 0) {
1296
+ Reflect.ownKeys(obj).forEach((key) => {
1297
+ iter(key, obj[key], obj);
1298
+ });
1299
+ } else {
1300
+ obj.forEach((entry, index) => iter(index, entry, obj));
1301
+ }
1860
1302
  }
1861
-
1862
- function collectRefAnnotationsRecursive(pathPrefix, value) {
1863
- if (value === undefined || value === null)
1864
- return undefined;
1865
- if (value instanceof DefinitionReferenceMarker) {
1866
- return {
1867
- entities: [],
1868
- references: [
1869
- { ...value.reference, path: [...pathPrefix, ...value.reference.path] },
1870
- ],
1871
- slots: [],
1303
+ function getArchtype(thing) {
1304
+ const state = thing[DRAFT_STATE];
1305
+ return state ? state.type_ : Array.isArray(thing) ? 1 : isMap(thing) ? 2 : isSet(thing) ? 3 : 0;
1306
+ }
1307
+ function has(thing, prop) {
1308
+ return getArchtype(thing) === 2 ? thing.has(prop) : Object.prototype.hasOwnProperty.call(thing, prop);
1309
+ }
1310
+ function set(thing, propOrOldValue, value) {
1311
+ const t = getArchtype(thing);
1312
+ if (t === 2)
1313
+ thing.set(propOrOldValue, value);
1314
+ else if (t === 3) {
1315
+ thing.add(value);
1316
+ } else
1317
+ thing[propOrOldValue] = value;
1318
+ }
1319
+ function is(x, y) {
1320
+ if (x === y) {
1321
+ return x !== 0 || 1 / x === 1 / y;
1322
+ } else {
1323
+ return x !== x && y !== y;
1324
+ }
1325
+ }
1326
+ function isMap(target) {
1327
+ return target instanceof Map;
1328
+ }
1329
+ function isSet(target) {
1330
+ return target instanceof Set;
1331
+ }
1332
+ function latest(state) {
1333
+ return state.copy_ || state.base_;
1334
+ }
1335
+ function shallowCopy(base, strict) {
1336
+ if (isMap(base)) {
1337
+ return new Map(base);
1338
+ }
1339
+ if (isSet(base)) {
1340
+ return new Set(base);
1341
+ }
1342
+ if (Array.isArray(base))
1343
+ return Array.prototype.slice.call(base);
1344
+ const isPlain = isPlainObject(base);
1345
+ if (strict === true || strict === "class_only" && !isPlain) {
1346
+ const descriptors = Object.getOwnPropertyDescriptors(base);
1347
+ delete descriptors[DRAFT_STATE];
1348
+ let keys = Reflect.ownKeys(descriptors);
1349
+ for (let i = 0; i < keys.length; i++) {
1350
+ const key = keys[i];
1351
+ const desc = descriptors[key];
1352
+ if (desc.writable === false) {
1353
+ desc.writable = true;
1354
+ desc.configurable = true;
1355
+ }
1356
+ if (desc.get || desc.set)
1357
+ descriptors[key] = {
1358
+ configurable: true,
1359
+ writable: true,
1360
+ // could live with !!desc.set as well here...
1361
+ enumerable: desc.enumerable,
1362
+ value: base[key]
1872
1363
  };
1873
1364
  }
1874
- const collected = {
1875
- entities: [],
1876
- references: [],
1877
- slots: [],
1878
- };
1879
- if (Array.isArray(value)) {
1880
- for (const [i, element] of value.entries()) {
1881
- const childCollected = collectRefAnnotationsRecursive([...pathPrefix, i], element);
1882
- if (childCollected) {
1883
- collected.entities.push(...childCollected.entities);
1884
- collected.references.push(...childCollected.references);
1885
- collected.slots.push(...childCollected.slots);
1886
- }
1887
- }
1888
- return collected;
1889
- }
1890
- if (typeof value === 'object') {
1891
- if (REF_ANNOTATIONS_MARKER_SYMBOL in value) {
1892
- const annotations = value[REF_ANNOTATIONS_MARKER_SYMBOL];
1893
- collected.entities.push(...annotations.entities.map((entity) => ({
1894
- ...entity,
1895
- path: [...pathPrefix, ...entity.path],
1896
- })));
1897
- collected.references.push(...annotations.references.map((reference) => ({
1898
- ...reference,
1899
- path: [...pathPrefix, ...reference.path],
1900
- })));
1901
- collected.slots.push(...annotations.slots.map((slot) => ({
1902
- ...slot,
1903
- path: [...pathPrefix, ...slot.path],
1904
- })));
1905
- }
1906
- for (const [key, childValue] of Object.entries(value)) {
1907
- if (typeof key !== 'string')
1908
- continue;
1909
- const childCollected = collectRefAnnotationsRecursive([...pathPrefix, key], childValue);
1910
- if (childCollected) {
1911
- collected.entities.push(...childCollected.entities);
1912
- collected.references.push(...childCollected.references);
1913
- collected.slots.push(...childCollected.slots);
1914
- }
1915
- }
1916
- return collected;
1365
+ return Object.create(getPrototypeOf(base), descriptors);
1366
+ } else {
1367
+ const proto = getPrototypeOf(base);
1368
+ if (proto !== null && isPlain) {
1369
+ return { ...base };
1917
1370
  }
1918
- return undefined;
1371
+ const obj = Object.create(proto);
1372
+ return Object.assign(obj, base);
1373
+ }
1919
1374
  }
1920
- function collectRefs(value) {
1921
- return (collectRefAnnotationsRecursive([], value) ?? {
1922
- entities: [],
1923
- references: [],
1924
- slots: [],
1925
- });
1375
+ function freeze(obj, deep = false) {
1376
+ if (isFrozen(obj) || isDraft(obj) || !isDraftable(obj))
1377
+ return obj;
1378
+ if (getArchtype(obj) > 1) {
1379
+ obj.set = obj.add = obj.clear = obj.delete = dontMutateFrozenCollections;
1380
+ }
1381
+ Object.freeze(obj);
1382
+ if (deep)
1383
+ Object.entries(obj).forEach(([key, value]) => freeze(value, true));
1384
+ return obj;
1926
1385
  }
1927
-
1928
- const {mapGroupBy} = await importShared('@baseplate-dev/utils');
1929
-
1930
- /**
1931
- * Calculates the length of the common prefix of two paths.
1932
- *
1933
- * @param a - The first path
1934
- * @param b - The second path
1935
- * @returns The length of the common prefix of the two paths
1936
- */
1937
- function commonPrefixLength(a, b) {
1938
- let length = 0;
1939
- const maxLength = Math.min(a.length, b.length);
1940
- for (let i = 0; i < maxLength; i++) {
1941
- if (a[i] !== b[i])
1942
- break;
1943
- length++;
1944
- }
1945
- return length;
1386
+ function dontMutateFrozenCollections() {
1387
+ die(2);
1946
1388
  }
1947
- /**
1948
- * Finds the nearest ancestor slot for a given target path.
1949
- *
1950
- * @param candidateSlots - The candidate slots to search through.
1951
- * @param targetPath - The target path to find the nearest ancestor slot for.
1952
- * @returns The nearest ancestor slot, or undefined if no slot is found.
1953
- */
1954
- function findNearestAncestorSlot(candidateSlots = [], targetPath) {
1955
- let bestMatch;
1956
- for (const candidateSlot of candidateSlots) {
1957
- const prefixLength = commonPrefixLength(candidateSlot.path, targetPath);
1958
- // A slot at path [] (root) is a valid ancestor of any path
1959
- // For non-root slots, require at least 1 common prefix element
1960
- const isValidAncestor = candidateSlot.path.length === 0 || prefixLength > 0;
1961
- if (isValidAncestor &&
1962
- (!bestMatch || prefixLength > bestMatch.prefixLength)) {
1963
- bestMatch = { prefixLength, slot: candidateSlot };
1964
- }
1965
- }
1966
- return bestMatch?.slot;
1389
+ function isFrozen(obj) {
1390
+ return Object.isFrozen(obj);
1967
1391
  }
1968
- /**
1969
- * Resolves all slot references to actual paths.
1970
- *
1971
- * This function takes the collected refs (which have `parentSlot` references)
1972
- * and resolves them to `parentPath` values using the slotPaths map.
1973
- *
1974
- * For scoped slots (where the same slot can be registered multiple times),
1975
- * we find the registration whose path is the nearest ancestor of the entity/reference.
1976
- *
1977
- * @param collected - The collected refs with unresolved slots.
1978
- * @returns The resolved refs with parentPath instead of parentSlot.
1979
- * @throws If a required slot is not found in the slotPaths map.
1980
- */
1981
- function resolveSlots(collected) {
1982
- const { entities, references, slots } = collected;
1983
- // Collect all slots by path
1984
- const slotsByType = mapGroupBy(slots, (slot) => slot.slot.id);
1985
- const resolvedSlotsByType = new Map();
1986
- function registerSlot(slot, resolvedPath) {
1987
- const slotId = slot.id;
1988
- const candidateSlots = slotsByType.get(slotId) ?? [];
1989
- const nearestAncestorSlot = findNearestAncestorSlot(candidateSlots, resolvedPath);
1990
- if (!nearestAncestorSlot) {
1991
- throw new Error(`Could not find slot "${slotId.description ?? 'unknown'}" ` +
1992
- `within path ${resolvedPath.join('.')}. Make sure the slot is registered for this path.`);
1993
- }
1994
- const existingSlots = resolvedSlotsByType.get(slotId) ?? [];
1995
- resolvedSlotsByType.set(slotId, [
1996
- ...existingSlots,
1997
- { resolvedPath, path: nearestAncestorSlot.path },
1998
- ]);
1999
- }
2000
- // Collect entity provides
2001
- for (const entity of entities) {
2002
- if (entity.provides) {
2003
- registerSlot(entity.provides, [...entity.path, ...entity.idPath]);
2004
- }
2005
- }
2006
- // Collect reference provides
2007
- for (const reference of references) {
2008
- if (reference.provides) {
2009
- registerSlot(reference.provides, reference.path);
2010
- }
2011
- }
2012
- return resolvedSlotsByType;
1392
+ var plugins = {};
1393
+ function getPlugin(pluginKey) {
1394
+ const plugin = plugins[pluginKey];
1395
+ if (!plugin) {
1396
+ die(0, pluginKey);
1397
+ }
1398
+ return plugin;
2013
1399
  }
2014
-
2015
- /**
2016
- * Extracts definition refs from a parsed value using functional approach.
2017
- *
2018
- * Flow:
2019
- * 1. Collect all refs (entities, references, slots) recursively
2020
- * 2. Resolve all slot references to actual paths
2021
- * 3. Strip ref markers from the data
2022
- * 4. Validate no duplicate IDs
2023
- *
2024
- * @param value - The parsed value from Zod schema
2025
- * @returns The extracted refs with clean data
2026
- */
2027
- function extractDefinitionRefs(value) {
2028
- // Step 1: Collect all refs without resolving slots
2029
- const collected = collectRefs(value);
2030
- // Step 2: Resolve all slots to paths
2031
- const resolvedSlots = resolveSlots(collected);
2032
- // Step 3: Strip markers from data
2033
- const cleanData = stripRefMarkers(value);
2034
- // Step 4: Resolve entity and reference parent paths
2035
- function resolveParentPath(parentSlot, path) {
2036
- const resolvedSlot = findNearestAncestorSlot(resolvedSlots.get(parentSlot.id), path);
2037
- if (!resolvedSlot) {
2038
- throw new Error(`Could not resolve parent path from ${path.join('.')} for slot ${parentSlot.id.description}`);
2039
- }
2040
- return resolvedSlot.resolvedPath;
1400
+ var currentScope;
1401
+ function getCurrentScope() {
1402
+ return currentScope;
1403
+ }
1404
+ function createScope(parent_, immer_) {
1405
+ return {
1406
+ drafts_: [],
1407
+ parent_,
1408
+ immer_,
1409
+ // Whenever the modified draft contains a draft from another scope, we
1410
+ // need to prevent auto-freezing so the unowned draft can be finalized.
1411
+ canAutoFreeze_: true,
1412
+ unfinalizedDrafts_: 0
1413
+ };
1414
+ }
1415
+ function usePatchesInScope(scope, patchListener) {
1416
+ if (patchListener) {
1417
+ getPlugin("Patches");
1418
+ scope.patches_ = [];
1419
+ scope.inversePatches_ = [];
1420
+ scope.patchListener_ = patchListener;
1421
+ }
1422
+ }
1423
+ function revokeScope(scope) {
1424
+ leaveScope(scope);
1425
+ scope.drafts_.forEach(revokeDraft);
1426
+ scope.drafts_ = null;
1427
+ }
1428
+ function leaveScope(scope) {
1429
+ if (scope === currentScope) {
1430
+ currentScope = scope.parent_;
1431
+ }
1432
+ }
1433
+ function enterScope(immer2) {
1434
+ return currentScope = createScope(currentScope, immer2);
1435
+ }
1436
+ function revokeDraft(draft) {
1437
+ const state = draft[DRAFT_STATE];
1438
+ if (state.type_ === 0 || state.type_ === 1)
1439
+ state.revoke_();
1440
+ else
1441
+ state.revoked_ = true;
1442
+ }
1443
+ function processResult(result, scope) {
1444
+ scope.unfinalizedDrafts_ = scope.drafts_.length;
1445
+ const baseDraft = scope.drafts_[0];
1446
+ const isReplaced = result !== void 0 && result !== baseDraft;
1447
+ if (isReplaced) {
1448
+ if (baseDraft[DRAFT_STATE].modified_) {
1449
+ revokeScope(scope);
1450
+ die(4);
1451
+ }
1452
+ if (isDraftable(result)) {
1453
+ result = finalize(scope, result);
1454
+ if (!scope.parent_)
1455
+ maybeFreeze(scope, result);
2041
1456
  }
2042
- const entitiesWithNameResolver = collected.entities.map((entity) => ({
2043
- id: entity.id,
2044
- idPath: entity.idPath,
2045
- nameResolver: entity.nameResolver,
2046
- type: entity.type,
2047
- path: entity.path,
2048
- parentPath: entity.parentSlot
2049
- ? resolveParentPath(entity.parentSlot, entity.path)
2050
- : undefined,
2051
- }));
2052
- const references = collected.references.map((reference) => ({
2053
- type: reference.type,
2054
- path: reference.path,
2055
- onDelete: reference.onDelete,
2056
- parentPath: reference.parentSlot
2057
- ? resolveParentPath(reference.parentSlot, reference.path)
2058
- : undefined,
2059
- }));
2060
- // Step 4: Validate no duplicate IDs
2061
- const idSet = new Set();
2062
- for (const entity of collected.entities) {
2063
- if (idSet.has(entity.id)) {
2064
- throw new Error(`Duplicate ID found: ${entity.id}`);
2065
- }
2066
- idSet.add(entity.id);
1457
+ if (scope.patches_) {
1458
+ getPlugin("Patches").generateReplacementPatches_(
1459
+ baseDraft[DRAFT_STATE].base_,
1460
+ result,
1461
+ scope.patches_,
1462
+ scope.inversePatches_
1463
+ );
2067
1464
  }
2068
- return {
2069
- data: cleanData,
2070
- references,
2071
- entitiesWithNameResolver,
2072
- };
1465
+ } else {
1466
+ result = finalize(scope, baseDraft, []);
1467
+ }
1468
+ revokeScope(scope);
1469
+ if (scope.patches_) {
1470
+ scope.patchListener_(scope.patches_, scope.inversePatches_);
1471
+ }
1472
+ return result !== NOTHING ? result : void 0;
2073
1473
  }
2074
-
2075
- const {toposort: toposort$1} = await importShared('@baseplate-dev/utils');
2076
- /**
2077
- * Resolves entity names in a ZodRefPayload.
2078
- *
2079
- * @param payload - The ZodRefPayload to resolve.
2080
- * @param options - The options for resolving entity names.
2081
- *
2082
- * @template T - The type of the payload.
2083
- */
2084
- function resolveZodRefPayloadNames(payload, { skipReferenceNameResolution = false, allowInvalidReferences = false, } = {}) {
2085
- const { entitiesWithNameResolver, references, data } = payload;
2086
- const entitiesById = keyBy(entitiesWithNameResolver, (entity) => entity.id);
2087
- const resolvedEntitiesById = new Map();
2088
- // sort entities by dependency order
2089
- const orderedEntities = toposort$1(entitiesWithNameResolver.map((entity) => entity.id), entitiesWithNameResolver.flatMap((entity) => {
2090
- if (typeof entity.nameResolver !== 'object') {
2091
- return [];
2092
- }
2093
- const entityIds = entity.nameResolver.idsToResolve ?? {};
2094
- return Object.values(entityIds)
2095
- .flat()
2096
- .filter((id) => id in entitiesById)
2097
- .map((id) => [id, entity.id]);
2098
- }));
2099
- function resolveIdToName(id) {
2100
- if (skipReferenceNameResolution) {
2101
- return id;
2102
- }
2103
- const entity = resolvedEntitiesById.get(id);
2104
- if (!entity) {
2105
- if (allowInvalidReferences) {
2106
- return id;
2107
- }
2108
- throw new Error(`Could not resolve entity name for id: ${id}`);
2109
- }
2110
- return entity.name;
1474
+ function finalize(rootScope, value, path) {
1475
+ if (isFrozen(value))
1476
+ return value;
1477
+ const state = value[DRAFT_STATE];
1478
+ if (!state) {
1479
+ each(
1480
+ value,
1481
+ (key, childValue) => finalizeProperty(rootScope, state, value, key, childValue, path)
1482
+ );
1483
+ return value;
1484
+ }
1485
+ if (state.scope_ !== rootScope)
1486
+ return value;
1487
+ if (!state.modified_) {
1488
+ maybeFreeze(rootScope, state.base_, true);
1489
+ return state.base_;
1490
+ }
1491
+ if (!state.finalized_) {
1492
+ state.finalized_ = true;
1493
+ state.scope_.unfinalizedDrafts_--;
1494
+ const result = state.copy_;
1495
+ let resultEach = result;
1496
+ let isSet2 = false;
1497
+ if (state.type_ === 3) {
1498
+ resultEach = new Set(result);
1499
+ result.clear();
1500
+ isSet2 = true;
2111
1501
  }
2112
- for (const id of orderedEntities) {
2113
- const { nameResolver, ...rest } = entitiesById[id];
2114
- if (typeof nameResolver === 'string') {
2115
- resolvedEntitiesById.set(rest.id, {
2116
- ...rest,
2117
- name: nameResolver,
2118
- });
2119
- }
2120
- else {
2121
- const resolvedIds = mapValues(nameResolver.idsToResolve ?? {}, (idOrIds) => Array.isArray(idOrIds)
2122
- ? idOrIds.map((id) => resolveIdToName(id))
2123
- : resolveIdToName(idOrIds));
2124
- resolvedEntitiesById.set(rest.id, {
2125
- ...rest,
2126
- name: nameResolver.resolveName(resolvedIds),
2127
- });
2128
- }
1502
+ each(
1503
+ resultEach,
1504
+ (key, childValue) => finalizeProperty(rootScope, state, result, key, childValue, path, isSet2)
1505
+ );
1506
+ maybeFreeze(rootScope, result, false);
1507
+ if (path && rootScope.patches_) {
1508
+ getPlugin("Patches").generatePatches_(
1509
+ state,
1510
+ path,
1511
+ rootScope.patches_,
1512
+ rootScope.inversePatches_
1513
+ );
2129
1514
  }
2130
- return {
2131
- entities: [...resolvedEntitiesById.values()],
2132
- references,
2133
- data,
2134
- };
1515
+ }
1516
+ return state.copy_;
2135
1517
  }
2136
-
2137
- /**
2138
- * Parses a schema with references.
2139
- *
2140
- * @param schema - The schema to parse.
2141
- * @param input - The input to parse.
2142
- * @param options - The options for parsing the schema.
2143
- *
2144
- * @returns The parsed data.
2145
- */
2146
- function parseSchemaWithTransformedReferences(schemaCreator, input, schemaCreatorOptions, options) {
2147
- const schemaContext = createDefinitionSchemaParserContext({
2148
- ...schemaCreatorOptions,
2149
- transformReferences: true,
2150
- });
2151
- const schema = schemaCreator(schemaContext);
2152
- const value = schema.parse(input);
2153
- const refPayload = extractDefinitionRefs(value);
2154
- return resolveZodRefPayloadNames(refPayload, options);
1518
+ function finalizeProperty(rootScope, parentState, targetObject, prop, childValue, rootPath, targetIsSet) {
1519
+ if (isDraft(childValue)) {
1520
+ const path = rootPath && parentState && parentState.type_ !== 3 && // Set objects are atomic since they have no keys.
1521
+ !has(parentState.assigned_, prop) ? rootPath.concat(prop) : void 0;
1522
+ const res = finalize(rootScope, childValue, path);
1523
+ set(targetObject, prop, res);
1524
+ if (isDraft(res)) {
1525
+ rootScope.canAutoFreeze_ = false;
1526
+ } else
1527
+ return;
1528
+ } else if (targetIsSet) {
1529
+ targetObject.add(childValue);
1530
+ }
1531
+ if (isDraftable(childValue) && !isFrozen(childValue)) {
1532
+ if (!rootScope.immer_.autoFreeze_ && rootScope.unfinalizedDrafts_ < 1) {
1533
+ return;
1534
+ }
1535
+ finalize(rootScope, childValue);
1536
+ if ((!parentState || !parentState.scope_.parent_) && typeof prop !== "symbol" && Object.prototype.propertyIsEnumerable.call(targetObject, prop))
1537
+ maybeFreeze(rootScope, childValue);
1538
+ }
2155
1539
  }
2156
-
2157
- const {toposort} = await importShared('@baseplate-dev/utils');
2158
- function referenceToNameParentId(name, parentId) {
2159
- return JSON.stringify({ name, parentId });
1540
+ function maybeFreeze(scope, value, deep = false) {
1541
+ if (!scope.parent_ && scope.immer_.autoFreeze_ && scope.canAutoFreeze_) {
1542
+ freeze(value, deep);
1543
+ }
2160
1544
  }
2161
- /**
2162
- * Deserialize a schema with references using the new transform-based approach.
2163
- * This function converts human-readable names back to entity IDs.
2164
- *
2165
- * @template T - The schema creator type
2166
- * @param schemaCreator - The schema creator function
2167
- * @param input - The input data with names instead of IDs
2168
- * @param options - Options for the schema creator (excluding transformReferences)
2169
- * @returns The resolved payload with IDs instead of names
2170
- */
2171
- function deserializeSchemaWithTransformedReferences(schemaCreator, input, options) {
2172
- const payload = parseSchemaWithTransformedReferences(schemaCreator, input, options, {
2173
- skipReferenceNameResolution: true,
2174
- });
2175
- // Use the same resolution logic as the original function
2176
- return resolveReferencesToIds(payload);
1545
+ function createProxyProxy(base, parent) {
1546
+ const isArray = Array.isArray(base);
1547
+ const state = {
1548
+ type_: isArray ? 1 : 0,
1549
+ // Track which produce call this is associated with.
1550
+ scope_: parent ? parent.scope_ : getCurrentScope(),
1551
+ // True for both shallow and deep changes.
1552
+ modified_: false,
1553
+ // Used during finalization.
1554
+ finalized_: false,
1555
+ // Track which properties have been assigned (true) or deleted (false).
1556
+ assigned_: {},
1557
+ // The parent draft state.
1558
+ parent_: parent,
1559
+ // The base state.
1560
+ base_: base,
1561
+ // The base proxy.
1562
+ draft_: null,
1563
+ // set below
1564
+ // The base copy with any updated values.
1565
+ copy_: null,
1566
+ // Called by the `produce` function.
1567
+ revoke_: null,
1568
+ isManual_: false
1569
+ };
1570
+ let target = state;
1571
+ let traps = objectTraps;
1572
+ if (isArray) {
1573
+ target = [state];
1574
+ traps = arrayTraps;
1575
+ }
1576
+ const { revoke, proxy } = Proxy.revocable(target, traps);
1577
+ state.draft_ = proxy;
1578
+ state.revoke_ = revoke;
1579
+ return proxy;
2177
1580
  }
2178
- /**
2179
- * Internal function to resolve entity names to IDs in the payload.
2180
- * This is shared logic between the old and new approaches.
2181
- *
2182
- * @param payload - The parsed payload with entities and references
2183
- * @returns The payload with references resolved to IDs
2184
- */
2185
- function resolveReferencesToIds(payload) {
2186
- const { references, entities, data } = payload;
2187
- if (typeof data !== 'object' || data === null) {
2188
- throw new TypeError('Data is not an object');
1581
+ var objectTraps = {
1582
+ get(state, prop) {
1583
+ if (prop === DRAFT_STATE)
1584
+ return state;
1585
+ const source = latest(state);
1586
+ if (!has(source, prop)) {
1587
+ return readPropFromProto(state, source, prop);
2189
1588
  }
2190
- // check we don't have more entities than IDs
2191
- const entitiesById = groupBy(entities, (entity) => entity.id);
2192
- const duplicateEntityIds = Object.values(entitiesById).filter((e) => e.length > 1);
2193
- if (duplicateEntityIds.length > 0) {
2194
- throw new Error(`Found multiple duplicate entity IDs: ${duplicateEntityIds
2195
- .map((ents) => `${ents[0].id} (${ents.map((e) => e.path.join('.')).join(',')})`)
2196
- .join(', ')}`);
1589
+ const value = source[prop];
1590
+ if (state.finalized_ || !isDraftable(value)) {
1591
+ return value;
2197
1592
  }
2198
- const uniqueEntityIds = uniq(entities.map((e) => e.id));
2199
- if (uniqueEntityIds.length !== entities.length) {
2200
- throw new Error(`Found duplicate entity IDs`);
1593
+ if (value === peek(state.base_, prop)) {
1594
+ prepareCopy(state);
1595
+ return state.copy_[prop] = createProxy(value, state);
2201
1596
  }
2202
- // collect reference entity types
2203
- const entityTypes = uniq(entities.map((e) => e.type));
2204
- const entityTypeNames = uniq(entityTypes.map((t) => t.name));
2205
- if (entityTypeNames.length !== entityTypes.length) {
2206
- throw new Error(`Found more entity types than entity type names implying duplicate entity type name`);
1597
+ return value;
1598
+ },
1599
+ has(state, prop) {
1600
+ return prop in latest(state);
1601
+ },
1602
+ ownKeys(state) {
1603
+ return Reflect.ownKeys(latest(state));
1604
+ },
1605
+ set(state, prop, value) {
1606
+ const desc = getDescriptorFromProto(latest(state), prop);
1607
+ if (desc?.set) {
1608
+ desc.set.call(state.draft_, value);
1609
+ return true;
2207
1610
  }
2208
- const entityTypeOrder = toposort(entityTypeNames, entityTypes
2209
- .filter((entityType) => !!entityType.parentType)
2210
- .map((entityType) => [
2211
- entityType.parentType?.name ?? '',
2212
- entityType.name,
2213
- ]));
2214
- const entitiesByType = groupBy(entities, (e) => e.type.name);
2215
- const referencesByType = groupBy(references, (r) => r.type.name);
2216
- for (const name of entityTypeOrder) {
2217
- const entities = entitiesByType[name] ?? [];
2218
- const references = referencesByType[name] ?? [];
2219
- // resolve references to their ID
2220
- const entitiesByParentIdName = keyBy(entities, (e) => {
2221
- const { parentPath } = e;
2222
- const parentId = parentPath
2223
- ? get(data, parentPath)
2224
- : undefined;
2225
- if (parentPath && typeof parentId !== 'string') {
2226
- throw new Error(`Could not resolve parent path: ${parentPath.join('.')}`);
2227
- }
2228
- return referenceToNameParentId(e.name, parentId);
2229
- });
2230
- for (const ref of references) {
2231
- const name = get(data, ref.path);
2232
- // parent ID should have already been resolved due to order of resolving references
2233
- const parentId = ref.parentPath && get(data, ref.parentPath);
2234
- const parentIdName = referenceToNameParentId(name, parentId);
2235
- const resolvedEntity = entitiesByParentIdName[parentIdName];
2236
- if (!resolvedEntity) {
2237
- throw new Error(`Unable to resolve reference: ${ref.path.join('.')} (${ref.type.name} ${parentIdName})`);
2238
- }
2239
- set$1(data, ref.path, resolvedEntity.id);
2240
- }
1611
+ if (!state.modified_) {
1612
+ const current2 = peek(latest(state), prop);
1613
+ const currentState = current2?.[DRAFT_STATE];
1614
+ if (currentState && currentState.base_ === value) {
1615
+ state.copy_[prop] = value;
1616
+ state.assigned_[prop] = false;
1617
+ return true;
1618
+ }
1619
+ if (is(value, current2) && (value !== void 0 || has(state.base_, prop)))
1620
+ return true;
1621
+ prepareCopy(state);
1622
+ markChanged(state);
2241
1623
  }
2242
- return payload;
1624
+ if (state.copy_[prop] === value && // special case: handle new props with value 'undefined'
1625
+ (value !== void 0 || prop in state.copy_) || // special case: NaN
1626
+ Number.isNaN(value) && Number.isNaN(state.copy_[prop]))
1627
+ return true;
1628
+ state.copy_[prop] = value;
1629
+ state.assigned_[prop] = true;
1630
+ return true;
1631
+ },
1632
+ deleteProperty(state, prop) {
1633
+ if (peek(state.base_, prop) !== void 0 || prop in state.base_) {
1634
+ state.assigned_[prop] = false;
1635
+ prepareCopy(state);
1636
+ markChanged(state);
1637
+ } else {
1638
+ delete state.assigned_[prop];
1639
+ }
1640
+ if (state.copy_) {
1641
+ delete state.copy_[prop];
1642
+ }
1643
+ return true;
1644
+ },
1645
+ // Note: We never coerce `desc.value` into an Immer draft, because we can't make
1646
+ // the same guarantee in ES5 mode.
1647
+ getOwnPropertyDescriptor(state, prop) {
1648
+ const owner = latest(state);
1649
+ const desc = Reflect.getOwnPropertyDescriptor(owner, prop);
1650
+ if (!desc)
1651
+ return desc;
1652
+ return {
1653
+ writable: true,
1654
+ configurable: state.type_ !== 1 || prop !== "length",
1655
+ enumerable: desc.enumerable,
1656
+ value: owner[prop]
1657
+ };
1658
+ },
1659
+ defineProperty() {
1660
+ die(11);
1661
+ },
1662
+ getPrototypeOf(state) {
1663
+ return getPrototypeOf(state.base_);
1664
+ },
1665
+ setPrototypeOf() {
1666
+ die(12);
1667
+ }
1668
+ };
1669
+ var arrayTraps = {};
1670
+ each(objectTraps, (key, fn) => {
1671
+ arrayTraps[key] = function() {
1672
+ arguments[0] = arguments[0][0];
1673
+ return fn.apply(this, arguments);
1674
+ };
1675
+ });
1676
+ arrayTraps.deleteProperty = function(state, prop) {
1677
+ return arrayTraps.set.call(this, state, prop, void 0);
1678
+ };
1679
+ arrayTraps.set = function(state, prop, value) {
1680
+ return objectTraps.set.call(this, state[0], prop, value, state[0]);
1681
+ };
1682
+ function peek(draft, prop) {
1683
+ const state = draft[DRAFT_STATE];
1684
+ const source = state ? latest(state) : draft;
1685
+ return source[prop];
2243
1686
  }
2244
-
2245
- // sentinel ID to signify the reference has been flagged for deletion
2246
- const DELETED_SENTINEL_ID = 'deleted-sentinel-id';
2247
- /**
2248
- * Fixes any reference deletions by performing the appropriate action for the reference
2249
- */
2250
- function fixRefDeletions(schemaCreator, value, schemaCreatorOptions) {
2251
- const issues = [];
2252
- // find all references that do not have a corresponding entity
2253
- let iterations;
2254
- let valueToEdit = value;
2255
- for (iterations = 0; iterations < 100; iterations++) {
2256
- const parseResult = parseSchemaWithTransformedReferences(schemaCreator, valueToEdit, schemaCreatorOptions, {
2257
- allowInvalidReferences: true,
2258
- });
2259
- const { references, entities } = parseResult;
2260
- valueToEdit = parseResult.data;
2261
- const entitiesById = new Map(entities.map((e) => [e.id, e]));
2262
- const referencesMissingEntity = references.filter((r) => {
2263
- const id = get(valueToEdit, r.path);
2264
- return id !== DELETED_SENTINEL_ID && !entitiesById.has(id);
2265
- });
2266
- if (referencesMissingEntity.length === 0) {
2267
- if (issues.length > 0) {
2268
- return {
2269
- type: 'failure',
2270
- issues,
2271
- };
2272
- }
2273
- return {
2274
- type: 'success',
2275
- value: valueToEdit,
2276
- refPayload: parseResult,
2277
- };
2278
- }
2279
- const objectsToDeleteInArray = [];
2280
- function tryDeleteParent(path) {
2281
- if (path.length === 0) {
2282
- return false;
2283
- }
2284
- const parentPath = path.slice(0, -1);
2285
- const parent = get(valueToEdit, parentPath);
2286
- if (!Array.isArray(parent)) {
2287
- return false;
2288
- }
2289
- objectsToDeleteInArray.push({
2290
- path: parentPath,
2291
- idx: path.at(-1),
2292
- });
2293
- return true;
2294
- }
2295
- // attempt to fix reference
2296
- for (const ref of referencesMissingEntity) {
2297
- const id = get(valueToEdit, ref.path);
2298
- switch (ref.onDelete) {
2299
- case 'SET_UNDEFINED': {
2300
- // Check if reference is inside an array
2301
- if (ref.path.length > 0) {
2302
- const parentPath = ref.path.slice(0, -1);
2303
- const parent = get(valueToEdit, parentPath);
2304
- if (Array.isArray(parent)) {
2305
- throw new TypeError(`SET_UNDEFINED cannot be used for references inside arrays at path ${ref.path.join('.')}. Use DELETE instead to remove the array element.`);
2306
- }
2307
- }
2308
- set$1(valueToEdit, ref.path, undefined);
2309
- break;
2310
- }
2311
- case 'RESTRICT': {
2312
- issues.push({ ref, entityId: id });
2313
- set$1(valueToEdit, ref.path, DELETED_SENTINEL_ID);
2314
- break;
2315
- }
2316
- case 'DELETE': {
2317
- if (!tryDeleteParent(ref.path)) {
2318
- throw new Error(`Unable to find ref to cascade delete to`);
2319
- }
2320
- break;
2321
- }
2322
- case 'DELETE_PARENT': {
2323
- if (!tryDeleteParent(ref.path.slice(0, -1))) {
2324
- throw new Error(`Unable to find ref to cascade delete to`);
2325
- }
2326
- break;
2327
- }
2328
- default: {
2329
- throw new Error(`Unknown onDelete action ${ref.onDelete}`);
2330
- }
2331
- }
1687
+ function readPropFromProto(state, source, prop) {
1688
+ const desc = getDescriptorFromProto(source, prop);
1689
+ return desc ? `value` in desc ? desc.value : (
1690
+ // This is a very special case, if the prop is a getter defined by the
1691
+ // prototype, we should invoke it with the draft as context!
1692
+ desc.get?.call(state.draft_)
1693
+ ) : void 0;
1694
+ }
1695
+ function getDescriptorFromProto(source, prop) {
1696
+ if (!(prop in source))
1697
+ return void 0;
1698
+ let proto = getPrototypeOf(source);
1699
+ while (proto) {
1700
+ const desc = Object.getOwnPropertyDescriptor(proto, prop);
1701
+ if (desc)
1702
+ return desc;
1703
+ proto = getPrototypeOf(proto);
1704
+ }
1705
+ return void 0;
1706
+ }
1707
+ function markChanged(state) {
1708
+ if (!state.modified_) {
1709
+ state.modified_ = true;
1710
+ if (state.parent_) {
1711
+ markChanged(state.parent_);
1712
+ }
1713
+ }
1714
+ }
1715
+ function prepareCopy(state) {
1716
+ if (!state.copy_) {
1717
+ state.copy_ = shallowCopy(
1718
+ state.base_,
1719
+ state.scope_.immer_.useStrictShallowCopy_
1720
+ );
1721
+ }
1722
+ }
1723
+ var Immer2 = class {
1724
+ constructor(config) {
1725
+ this.autoFreeze_ = true;
1726
+ this.useStrictShallowCopy_ = false;
1727
+ this.produce = (base, recipe, patchListener) => {
1728
+ if (typeof base === "function" && typeof recipe !== "function") {
1729
+ const defaultBase = recipe;
1730
+ recipe = base;
1731
+ const self = this;
1732
+ return function curriedProduce(base2 = defaultBase, ...args) {
1733
+ return self.produce(base2, (draft) => recipe.call(this, draft, ...args));
1734
+ };
1735
+ }
1736
+ if (typeof recipe !== "function")
1737
+ die(6);
1738
+ if (patchListener !== void 0 && typeof patchListener !== "function")
1739
+ die(7);
1740
+ let result;
1741
+ if (isDraftable(base)) {
1742
+ const scope = enterScope(this);
1743
+ const proxy = createProxy(base, void 0);
1744
+ let hasError = true;
1745
+ try {
1746
+ result = recipe(proxy);
1747
+ hasError = false;
1748
+ } finally {
1749
+ if (hasError)
1750
+ revokeScope(scope);
1751
+ else
1752
+ leaveScope(scope);
2332
1753
  }
2333
- const objectsToDeleteByPath = groupBy(objectsToDeleteInArray, (o) => o.path.join('.'));
2334
- // delete objects in reverse order to avoid index shifting
2335
- for (const [, objects] of Object.entries(objectsToDeleteByPath)) {
2336
- const sortedObjects = sortBy(objects, [(o) => -o.idx]);
2337
- for (const o of sortedObjects) {
2338
- const parent = get(valueToEdit, o.path);
2339
- if (!Array.isArray(parent)) {
2340
- throw new TypeError(`Expected parent to be an array at path ${o.path.join('.')}`);
2341
- }
2342
- parent.splice(o.idx, 1);
2343
- }
1754
+ usePatchesInScope(scope, patchListener);
1755
+ return processResult(result, scope);
1756
+ } else if (!base || typeof base !== "object") {
1757
+ result = recipe(base);
1758
+ if (result === void 0)
1759
+ result = base;
1760
+ if (result === NOTHING)
1761
+ result = void 0;
1762
+ if (this.autoFreeze_)
1763
+ freeze(result, true);
1764
+ if (patchListener) {
1765
+ const p = [];
1766
+ const ip = [];
1767
+ getPlugin("Patches").generateReplacementPatches_(base, result, p, ip);
1768
+ patchListener(p, ip);
2344
1769
  }
1770
+ return result;
1771
+ } else
1772
+ die(1, base);
1773
+ };
1774
+ this.produceWithPatches = (base, recipe) => {
1775
+ if (typeof base === "function") {
1776
+ return (state, ...args) => this.produceWithPatches(state, (draft) => base(draft, ...args));
1777
+ }
1778
+ let patches, inversePatches;
1779
+ const result = this.produce(base, recipe, (p, ip) => {
1780
+ patches = p;
1781
+ inversePatches = ip;
1782
+ });
1783
+ return [result, patches, inversePatches];
1784
+ };
1785
+ if (typeof config?.autoFreeze === "boolean")
1786
+ this.setAutoFreeze(config.autoFreeze);
1787
+ if (typeof config?.useStrictShallowCopy === "boolean")
1788
+ this.setUseStrictShallowCopy(config.useStrictShallowCopy);
1789
+ }
1790
+ createDraft(base) {
1791
+ if (!isDraftable(base))
1792
+ die(8);
1793
+ if (isDraft(base))
1794
+ base = current(base);
1795
+ const scope = enterScope(this);
1796
+ const proxy = createProxy(base, void 0);
1797
+ proxy[DRAFT_STATE].isManual_ = true;
1798
+ leaveScope(scope);
1799
+ return proxy;
1800
+ }
1801
+ finishDraft(draft, patchListener) {
1802
+ const state = draft && draft[DRAFT_STATE];
1803
+ if (!state || !state.isManual_)
1804
+ die(9);
1805
+ const { scope_: scope } = state;
1806
+ usePatchesInScope(scope, patchListener);
1807
+ return processResult(void 0, scope);
1808
+ }
1809
+ /**
1810
+ * Pass true to automatically freeze all copies created by Immer.
1811
+ *
1812
+ * By default, auto-freezing is enabled.
1813
+ */
1814
+ setAutoFreeze(value) {
1815
+ this.autoFreeze_ = value;
1816
+ }
1817
+ /**
1818
+ * Pass true to enable strict shallow copy.
1819
+ *
1820
+ * By default, immer does not copy the object descriptors such as getter, setter and non-enumrable properties.
1821
+ */
1822
+ setUseStrictShallowCopy(value) {
1823
+ this.useStrictShallowCopy_ = value;
1824
+ }
1825
+ applyPatches(base, patches) {
1826
+ let i;
1827
+ for (i = patches.length - 1; i >= 0; i--) {
1828
+ const patch = patches[i];
1829
+ if (patch.path.length === 0 && patch.op === "replace") {
1830
+ base = patch.value;
1831
+ break;
1832
+ }
2345
1833
  }
2346
- throw new Error(`Exceeded max iterations fixing deletions`);
1834
+ if (i > -1) {
1835
+ patches = patches.slice(i + 1);
1836
+ }
1837
+ const applyPatchesImpl = getPlugin("Patches").applyPatches_;
1838
+ if (isDraft(base)) {
1839
+ return applyPatchesImpl(base, patches);
1840
+ }
1841
+ return this.produce(
1842
+ base,
1843
+ (draft) => applyPatchesImpl(draft, patches)
1844
+ );
1845
+ }
1846
+ };
1847
+ function createProxy(value, parent) {
1848
+ const draft = isMap(value) ? getPlugin("MapSet").proxyMap_(value, parent) : isSet(value) ? getPlugin("MapSet").proxySet_(value, parent) : createProxyProxy(value, parent);
1849
+ const scope = parent ? parent.scope_ : getCurrentScope();
1850
+ scope.drafts_.push(draft);
1851
+ return draft;
1852
+ }
1853
+ function current(value) {
1854
+ if (!isDraft(value))
1855
+ die(10, value);
1856
+ return currentImpl(value);
2347
1857
  }
1858
+ function currentImpl(value) {
1859
+ if (!isDraftable(value) || isFrozen(value))
1860
+ return value;
1861
+ const state = value[DRAFT_STATE];
1862
+ let copy;
1863
+ if (state) {
1864
+ if (!state.modified_)
1865
+ return state.base_;
1866
+ state.finalized_ = true;
1867
+ copy = shallowCopy(value, state.scope_.immer_.useStrictShallowCopy_);
1868
+ } else {
1869
+ copy = shallowCopy(value, true);
1870
+ }
1871
+ each(copy, (key, childValue) => {
1872
+ set(copy, key, currentImpl(childValue));
1873
+ });
1874
+ if (state) {
1875
+ state.finalized_ = false;
1876
+ }
1877
+ return copy;
1878
+ }
1879
+ var immer = new Immer2();
1880
+ var produce = immer.produce;
1881
+ immer.produceWithPatches.bind(
1882
+ immer
1883
+ );
1884
+ immer.setAutoFreeze.bind(immer);
1885
+ immer.setUseStrictShallowCopy.bind(immer);
1886
+ immer.applyPatches.bind(immer);
1887
+ immer.createDraft.bind(immer);
1888
+ immer.finishDraft.bind(immer);
2348
1889
 
2349
1890
  function serializeSchemaFromRefPayload(payload) {
2350
1891
  const { references, entities, data } = payload;
@@ -2381,103 +1922,103 @@ const SCALAR_FIELD_TYPES = [
2381
1922
  'enum',
2382
1923
  ];
2383
1924
 
2384
- const {z: z$r} = await importShared('zod');
1925
+ const {z: z$t} = await importShared('zod');
2385
1926
 
2386
1927
  const VALIDATORS = {
2387
- PASCAL_CASE_STRING: z$r
1928
+ PASCAL_CASE_STRING: z$t
2388
1929
  .string()
2389
1930
  .regex(/^[A-Z][a-zA-Z0-9]*$/, "Should be PascalCase, e.g. 'MyModel'"),
2390
- CAMEL_CASE_STRING: z$r
1931
+ CAMEL_CASE_STRING: z$t
2391
1932
  .string()
2392
1933
  .regex(/^[a-z][a-zA-Z0-9]*$/, "Should be camelCase, e.g. 'myField'"),
2393
- CONSTANT_CASE_STRING: z$r
1934
+ CONSTANT_CASE_STRING: z$t
2394
1935
  .string()
2395
1936
  .regex(/^[A-Z][A-Z0-9_]*$/, "Should be CONSTANT_CASE, e.g. 'MY_CONSTANT'"),
2396
- OPTIONAL_CONSTANT_CASE_STRING: z$r
1937
+ OPTIONAL_CONSTANT_CASE_STRING: z$t
2397
1938
  .string()
2398
1939
  .regex(/^[A-Z][A-Z0-9_]*$/, "Should be CONSTANT_CASE, e.g. 'MY_CONSTANT'")
2399
- .or(z$r.literal(''))
1940
+ .or(z$t.literal(''))
2400
1941
  .optional(),
2401
1942
  };
2402
1943
 
2403
- const {z: z$q} = await importShared('zod');
2404
- const createRoleArray = definitionSchema((ctx) => ctx.withDefault(z$q.array(ctx.withRef({
1944
+ const {z: z$s} = await importShared('zod');
1945
+ const createRoleArray = definitionSchema((ctx) => ctx.withDefault(z$s.array(ctx.withRef({
2405
1946
  type: authRoleEntityType,
2406
1947
  onDelete: 'DELETE',
2407
1948
  })), []));
2408
1949
  const createModelGraphqlSchema = definitionSchemaWithSlots({
2409
1950
  modelSlot: modelEntityType,
2410
- }, (ctx, { modelSlot }) => z$q.object({
2411
- objectType: ctx.withDefault(z$q.object({
2412
- enabled: ctx.withDefault(z$q.boolean(), false),
2413
- fields: ctx.withDefault(z$q.array(ctx.withRef({
1951
+ }, (ctx, { modelSlot }) => z$s.object({
1952
+ objectType: ctx.withDefault(z$s.object({
1953
+ enabled: ctx.withDefault(z$s.boolean(), false),
1954
+ fields: ctx.withDefault(z$s.array(ctx.withRef({
2414
1955
  type: modelScalarFieldEntityType,
2415
1956
  onDelete: 'DELETE',
2416
1957
  parentSlot: modelSlot,
2417
1958
  })), []),
2418
- localRelations: ctx.withDefault(z$q.array(ctx.withRef({
1959
+ localRelations: ctx.withDefault(z$s.array(ctx.withRef({
2419
1960
  type: modelLocalRelationEntityType,
2420
1961
  onDelete: 'DELETE',
2421
1962
  parentSlot: modelSlot,
2422
1963
  })), []),
2423
- foreignRelations: ctx.withDefault(z$q.array(ctx.withRef({
1964
+ foreignRelations: ctx.withDefault(z$s.array(ctx.withRef({
2424
1965
  type: modelForeignRelationEntityType,
2425
1966
  onDelete: 'DELETE',
2426
1967
  parentSlot: modelSlot,
2427
1968
  })), []),
2428
1969
  }), {}),
2429
- queries: ctx.withDefault(z$q.object({
2430
- get: ctx.withDefault(z$q.object({
2431
- enabled: ctx.withDefault(z$q.boolean(), false),
1970
+ queries: ctx.withDefault(z$s.object({
1971
+ get: ctx.withDefault(z$s.object({
1972
+ enabled: ctx.withDefault(z$s.boolean(), false),
2432
1973
  roles: createRoleArray(ctx),
2433
1974
  }), {}),
2434
- list: ctx.withDefault(z$q.object({
2435
- enabled: ctx.withDefault(z$q.boolean(), false),
1975
+ list: ctx.withDefault(z$s.object({
1976
+ enabled: ctx.withDefault(z$s.boolean(), false),
2436
1977
  roles: createRoleArray(ctx),
2437
1978
  }), {}),
2438
1979
  }), {}),
2439
- mutations: ctx.withDefault(z$q.object({
2440
- create: ctx.withDefault(z$q.object({
2441
- enabled: ctx.withDefault(z$q.boolean(), false),
1980
+ mutations: ctx.withDefault(z$s.object({
1981
+ create: ctx.withDefault(z$s.object({
1982
+ enabled: ctx.withDefault(z$s.boolean(), false),
2442
1983
  roles: createRoleArray(ctx),
2443
1984
  }), {}),
2444
- update: ctx.withDefault(z$q.object({
2445
- enabled: ctx.withDefault(z$q.boolean(), false),
1985
+ update: ctx.withDefault(z$s.object({
1986
+ enabled: ctx.withDefault(z$s.boolean(), false),
2446
1987
  roles: createRoleArray(ctx),
2447
1988
  }), {}),
2448
- delete: ctx.withDefault(z$q.object({
2449
- enabled: ctx.withDefault(z$q.boolean(), false),
1989
+ delete: ctx.withDefault(z$s.object({
1990
+ enabled: ctx.withDefault(z$s.boolean(), false),
2450
1991
  roles: createRoleArray(ctx),
2451
1992
  }), {}),
2452
1993
  }), {}),
2453
1994
  }));
2454
1995
 
2455
- const {z: z$p} = await importShared('zod');
1996
+ const {z: z$r} = await importShared('zod');
2456
1997
 
2457
1998
  const baseTransformerFields = {
2458
- id: z$p.string(),
2459
- type: z$p.string().min(1),
1999
+ id: z$r.string(),
2000
+ type: z$r.string().min(1),
2460
2001
  };
2461
- const baseTransformerSchema = z$p.looseObject(baseTransformerFields);
2002
+ const baseTransformerSchema = z$r.looseObject(baseTransformerFields);
2462
2003
  function createModelTransformerType(payload) {
2463
2004
  return payload;
2464
2005
  }
2465
2006
 
2466
- const {z: z$o} = await importShared('zod');
2467
- const createEmbeddedRelationTransformerSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => ctx.refContext({ embeddedModelSlot: modelEntityType }, ({ embeddedModelSlot }) => ctx.withEnt(z$o.object({
2007
+ const {z: z$q} = await importShared('zod');
2008
+ const createEmbeddedRelationTransformerSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => ctx.refContext({ embeddedModelSlot: modelEntityType }, ({ embeddedModelSlot }) => ctx.withEnt(z$q.object({
2468
2009
  ...baseTransformerFields,
2469
2010
  foreignRelationRef: ctx.withRef({
2470
2011
  type: modelForeignRelationEntityType,
2471
2012
  onDelete: 'DELETE_PARENT',
2472
2013
  parentSlot: modelSlot,
2473
2014
  }),
2474
- type: z$o.literal('embeddedRelation'),
2475
- embeddedFieldNames: z$o.array(ctx.withRef({
2015
+ type: z$q.literal('embeddedRelation'),
2016
+ embeddedFieldNames: z$q.array(ctx.withRef({
2476
2017
  type: modelScalarFieldEntityType,
2477
2018
  onDelete: 'RESTRICT',
2478
2019
  parentSlot: embeddedModelSlot,
2479
2020
  })),
2480
- embeddedTransformerNames: z$o
2021
+ embeddedTransformerNames: z$q
2481
2022
  .array(ctx.withRef({
2482
2023
  type: modelTransformerEntityType,
2483
2024
  onDelete: 'RESTRICT',
@@ -2505,86 +2046,59 @@ const BUILT_IN_TRANSFORMERS = [
2505
2046
  }),
2506
2047
  ];
2507
2048
 
2508
- function createModelTransformerImplementation() {
2509
- const transformers = {};
2510
- for (const transformer of BUILT_IN_TRANSFORMERS) {
2511
- transformers[transformer.name] =
2512
- transformer;
2513
- }
2514
- return {
2515
- registerModelTransformer(transformer) {
2516
- if (transformer.name in transformers) {
2517
- throw new Error(`Model transformer with name ${transformer.name} is already registered`);
2518
- }
2519
- transformers[transformer.name] =
2520
- transformer;
2521
- },
2522
- getModelTransformers() {
2523
- return transformers;
2524
- },
2525
- getModelTransformer(name) {
2526
- if (!(name in transformers)) {
2527
- throw new Error(`Unable to find transformer with name ${name}`);
2528
- }
2529
- return transformers[name];
2530
- },
2531
- };
2532
- }
2533
2049
  /**
2534
- * Spec for adding config component for plugin
2050
+ * Spec for registering additional model transformer types
2535
2051
  */
2536
- const modelTransformerSpec = createPluginSpec('core/model-transformer', {
2537
- defaultInitializer: createModelTransformerImplementation,
2538
- });
2052
+ const modelTransformerSpec = createFieldMapSpec('core/model-transformer', (t) => ({
2053
+ transformers: t.namedArrayToMap(BUILT_IN_TRANSFORMERS),
2054
+ }));
2539
2055
 
2540
- const z$n = await importShared('zod');
2056
+ const z$p = await importShared('zod');
2541
2057
  const createTransformerSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, slots) => {
2542
- const transformers = ctx.plugins
2543
- .getPluginSpec(modelTransformerSpec)
2544
- .getModelTransformers();
2545
- return z$n.discriminatedUnion('type', Object.values(transformers).map((transformer) => transformer.createSchema(ctx, slots)));
2058
+ const { transformers } = ctx.plugins.use(modelTransformerSpec);
2059
+ return z$p.discriminatedUnion('type', [...transformers.values()].map((transformer) => transformer.createSchema(ctx, slots)));
2546
2060
  });
2547
2061
 
2548
- const {z: z$m} = await importShared('zod');
2549
- const createEnumValueSchema = definitionSchemaWithSlots({ enumSlot: modelEnumEntityType }, (ctx, { enumSlot }) => ctx.withEnt(z$m.object({
2550
- id: z$m.string(),
2551
- name: z$m.string().min(1),
2552
- friendlyName: z$m.string().min(1),
2062
+ const {z: z$o} = await importShared('zod');
2063
+ const createEnumValueSchema = definitionSchemaWithSlots({ enumSlot: modelEnumEntityType }, (ctx, { enumSlot }) => ctx.withEnt(z$o.object({
2064
+ id: z$o.string(),
2065
+ name: z$o.string().min(1),
2066
+ friendlyName: z$o.string().min(1),
2553
2067
  }), {
2554
2068
  type: modelEnumValueEntityType,
2555
2069
  parentSlot: enumSlot,
2556
2070
  }));
2557
- const createEnumBaseSchema = definitionSchemaWithSlots({ enumSlot: modelEnumEntityType }, (ctx, { enumSlot }) => z$m.object({
2558
- id: z$m.string(),
2559
- name: z$m.string().min(1),
2071
+ const createEnumBaseSchema = definitionSchemaWithSlots({ enumSlot: modelEnumEntityType }, (ctx, { enumSlot }) => z$o.object({
2072
+ id: z$o.string(),
2073
+ name: z$o.string().min(1),
2560
2074
  featureRef: ctx.withRef({
2561
2075
  type: featureEntityType,
2562
2076
  onDelete: 'RESTRICT',
2563
2077
  }),
2564
- values: z$m.array(createEnumValueSchema(ctx, { enumSlot })),
2565
- isExposed: z$m.boolean(),
2078
+ values: z$o.array(createEnumValueSchema(ctx, { enumSlot })),
2079
+ isExposed: z$o.boolean(),
2566
2080
  }));
2567
2081
  const createEnumSchema = definitionSchema((ctx) => ctx.refContext({ enumSlot: modelEnumEntityType }, ({ enumSlot }) => ctx.withEnt(createEnumBaseSchema(ctx, { enumSlot }), {
2568
2082
  type: modelEnumEntityType,
2569
2083
  provides: enumSlot,
2570
2084
  })));
2571
2085
 
2572
- const {z: z$l} = await importShared('zod');
2086
+ const {z: z$n} = await importShared('zod');
2573
2087
  const createModelScalarFieldSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => ctx
2574
- .withEnt(z$l.object({
2575
- id: z$l.string(),
2088
+ .withEnt(z$n.object({
2089
+ id: z$n.string(),
2576
2090
  name: VALIDATORS.CAMEL_CASE_STRING,
2577
- type: z$l.enum(SCALAR_FIELD_TYPES),
2578
- isOptional: z$l.boolean().default(false),
2579
- options: ctx.refContext({ enumSlot: modelEnumEntityType }, ({ enumSlot }) => z$l
2091
+ type: z$n.enum(SCALAR_FIELD_TYPES),
2092
+ isOptional: z$n.boolean().default(false),
2093
+ options: ctx.refContext({ enumSlot: modelEnumEntityType }, ({ enumSlot }) => z$n
2580
2094
  .object({
2581
2095
  // string options
2582
- default: z$l.string().default(''),
2096
+ default: z$n.string().default(''),
2583
2097
  // uuid options
2584
- genUuid: z$l.boolean().optional(),
2098
+ genUuid: z$n.boolean().optional(),
2585
2099
  // date options
2586
- updatedAt: z$l.boolean().optional(),
2587
- defaultToNow: z$l.boolean().optional(),
2100
+ updatedAt: z$n.boolean().optional(),
2101
+ defaultToNow: z$n.boolean().optional(),
2588
2102
  // enum options
2589
2103
  enumRef: ctx
2590
2104
  .withRef({
@@ -2644,13 +2158,13 @@ const REFERENTIAL_ACTIONS = [
2644
2158
  'SetNull',
2645
2159
  'SetDefault',
2646
2160
  ];
2647
- const createModelRelationFieldSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => ctx.refContext({ foreignModelSlot: modelEntityType }, ({ foreignModelSlot }) => ctx.withEnt(ctx.withEnt(z$l.object({
2648
- id: z$l.string(),
2649
- foreignId: z$l
2161
+ const createModelRelationFieldSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => ctx.refContext({ foreignModelSlot: modelEntityType }, ({ foreignModelSlot }) => ctx.withEnt(ctx.withEnt(z$n.object({
2162
+ id: z$n.string(),
2163
+ foreignId: z$n
2650
2164
  .string()
2651
2165
  .default(() => modelForeignRelationEntityType.generateNewId()),
2652
2166
  name: VALIDATORS.CAMEL_CASE_STRING,
2653
- references: z$l.array(z$l.object({
2167
+ references: z$n.array(z$n.object({
2654
2168
  localRef: ctx.withRef({
2655
2169
  type: modelScalarFieldEntityType,
2656
2170
  onDelete: 'RESTRICT',
@@ -2668,8 +2182,8 @@ const createModelRelationFieldSchema = definitionSchemaWithSlots({ modelSlot: mo
2668
2182
  provides: foreignModelSlot,
2669
2183
  }),
2670
2184
  foreignRelationName: VALIDATORS.CAMEL_CASE_STRING,
2671
- onDelete: z$l.enum(REFERENTIAL_ACTIONS).default('Cascade'),
2672
- onUpdate: z$l.enum(REFERENTIAL_ACTIONS).default('Restrict'),
2185
+ onDelete: z$n.enum(REFERENTIAL_ACTIONS).default('Cascade'),
2186
+ onUpdate: z$n.enum(REFERENTIAL_ACTIONS).default('Restrict'),
2673
2187
  }), {
2674
2188
  type: modelLocalRelationEntityType,
2675
2189
  parentSlot: modelSlot,
@@ -2679,9 +2193,9 @@ const createModelRelationFieldSchema = definitionSchemaWithSlots({ modelSlot: mo
2679
2193
  getNameResolver: (entity) => entity.foreignRelationName,
2680
2194
  parentSlot: foreignModelSlot,
2681
2195
  })));
2682
- const createModelUniqueConstraintSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => ctx.withEnt(z$l.object({
2683
- id: z$l.string(),
2684
- fields: z$l.array(z$l.object({
2196
+ const createModelUniqueConstraintSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => ctx.withEnt(z$n.object({
2197
+ id: z$n.string(),
2198
+ fields: z$n.array(z$n.object({
2685
2199
  fieldRef: ctx.withRef({
2686
2200
  type: modelScalarFieldEntityType,
2687
2201
  onDelete: 'RESTRICT',
@@ -2698,18 +2212,18 @@ const createModelUniqueConstraintSchema = definitionSchemaWithSlots({ modelSlot:
2698
2212
  });
2699
2213
  },
2700
2214
  }));
2701
- const createModelServiceSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => z$l.object({
2702
- create: z$l
2215
+ const createModelServiceSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => z$n.object({
2216
+ create: z$n
2703
2217
  .object({
2704
- enabled: z$l.boolean().default(false),
2705
- fields: z$l
2218
+ enabled: z$n.boolean().default(false),
2219
+ fields: z$n
2706
2220
  .array(ctx.withRef({
2707
2221
  type: modelScalarFieldEntityType,
2708
2222
  onDelete: 'DELETE',
2709
2223
  parentSlot: modelSlot,
2710
2224
  }))
2711
2225
  .optional(),
2712
- transformerNames: z$l
2226
+ transformerNames: z$n
2713
2227
  .array(ctx.withRef({
2714
2228
  type: modelTransformerEntityType,
2715
2229
  onDelete: 'DELETE',
@@ -2718,17 +2232,17 @@ const createModelServiceSchema = definitionSchemaWithSlots({ modelSlot: modelEnt
2718
2232
  .optional(),
2719
2233
  })
2720
2234
  .default({ enabled: false }),
2721
- update: z$l
2235
+ update: z$n
2722
2236
  .object({
2723
- enabled: z$l.boolean().default(false),
2724
- fields: z$l
2237
+ enabled: z$n.boolean().default(false),
2238
+ fields: z$n
2725
2239
  .array(ctx.withRef({
2726
2240
  type: modelScalarFieldEntityType,
2727
2241
  onDelete: 'DELETE',
2728
2242
  parentSlot: modelSlot,
2729
2243
  }))
2730
2244
  .optional(),
2731
- transformerNames: z$l
2245
+ transformerNames: z$n
2732
2246
  .array(ctx.withRef({
2733
2247
  type: modelTransformerEntityType,
2734
2248
  onDelete: 'DELETE',
@@ -2737,37 +2251,37 @@ const createModelServiceSchema = definitionSchemaWithSlots({ modelSlot: modelEnt
2737
2251
  .optional(),
2738
2252
  })
2739
2253
  .default({ enabled: false }),
2740
- delete: z$l
2254
+ delete: z$n
2741
2255
  .object({
2742
- enabled: z$l.boolean().default(false),
2256
+ enabled: z$n.boolean().default(false),
2743
2257
  })
2744
2258
  .default({
2745
2259
  enabled: false,
2746
2260
  }),
2747
- transformers: z$l
2261
+ transformers: z$n
2748
2262
  .array(createTransformerSchema(ctx, { modelSlot }))
2749
2263
  .default([]),
2750
2264
  }));
2751
- const createModelBaseSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, slots) => z$l.object({
2752
- id: z$l.string(),
2265
+ const createModelBaseSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, slots) => z$n.object({
2266
+ id: z$n.string(),
2753
2267
  name: VALIDATORS.PASCAL_CASE_STRING,
2754
2268
  featureRef: ctx.withRef({
2755
2269
  type: featureEntityType,
2756
2270
  onDelete: 'RESTRICT',
2757
2271
  }),
2758
- model: z$l.object({
2759
- fields: z$l.array(createModelScalarFieldSchema(ctx, slots)),
2760
- relations: z$l
2272
+ model: z$n.object({
2273
+ fields: z$n.array(createModelScalarFieldSchema(ctx, slots)),
2274
+ relations: z$n
2761
2275
  .array(createModelRelationFieldSchema(ctx, slots))
2762
2276
  .optional(),
2763
- primaryKeyFieldRefs: z$l
2277
+ primaryKeyFieldRefs: z$n
2764
2278
  .array(ctx.withRef({
2765
2279
  type: modelScalarFieldEntityType,
2766
2280
  onDelete: 'RESTRICT',
2767
2281
  parentSlot: slots.modelSlot,
2768
2282
  }))
2769
2283
  .min(1),
2770
- uniqueConstraints: z$l
2284
+ uniqueConstraints: z$n
2771
2285
  .array(createModelUniqueConstraintSchema(ctx, slots))
2772
2286
  .optional(),
2773
2287
  }),
@@ -2791,26 +2305,26 @@ const adminCrudSectionColumnEntityType = createEntityType('admin-crud-section-co
2791
2305
  parentType: adminSectionEntityType,
2792
2306
  });
2793
2307
 
2794
- const {z: z$k} = await importShared('zod');
2795
- const createBaseAdminSectionValidators = definitionSchema((ctx) => z$k.object({
2796
- id: z$k.string().default(adminSectionEntityType.generateNewId()),
2797
- name: z$k.string().min(1),
2308
+ const {z: z$m} = await importShared('zod');
2309
+ const createBaseAdminSectionValidators = definitionSchema((ctx) => z$m.object({
2310
+ id: z$m.string().default(adminSectionEntityType.generateNewId()),
2311
+ name: z$m.string().min(1),
2798
2312
  featureRef: ctx.withRef({
2799
2313
  type: featureEntityType,
2800
2314
  onDelete: 'RESTRICT',
2801
2315
  }),
2802
- icon: z$k.string().optional(),
2803
- type: z$k.string().min(1),
2316
+ icon: z$m.string().optional(),
2317
+ type: z$m.string().min(1),
2804
2318
  }));
2805
2319
 
2806
- const {z: z$j} = await importShared('zod');
2807
- const baseAdminCrudActionSchema = z$j.looseObject({
2808
- id: z$j
2320
+ const {z: z$l} = await importShared('zod');
2321
+ const baseAdminCrudActionSchema = z$l.looseObject({
2322
+ id: z$l
2809
2323
  .string()
2810
2324
  .min(1)
2811
2325
  .default(() => adminCrudActionEntityType.generateNewId()),
2812
- type: z$j.string().min(1),
2813
- position: z$j.enum(['inline', 'dropdown']).default('dropdown'),
2326
+ type: z$l.string().min(1),
2327
+ position: z$l.enum(['inline', 'dropdown']).default('dropdown'),
2814
2328
  });
2815
2329
  function createAdminCrudActionType(payload) {
2816
2330
  return payload;
@@ -2819,16 +2333,16 @@ const adminCrudActionEntityType = createEntityType('admin-crud-action', {
2819
2333
  parentType: adminSectionEntityType,
2820
2334
  });
2821
2335
 
2822
- const {z: z$i} = await importShared('zod');
2336
+ const {z: z$k} = await importShared('zod');
2823
2337
  const createAdminCrudEditActionSchema = definitionSchema(() => baseAdminCrudActionSchema.extend({
2824
- type: z$i.literal('edit'),
2338
+ type: z$k.literal('edit'),
2825
2339
  }));
2826
2340
  const adminCrudEditActionType = createAdminCrudActionType({
2827
2341
  name: 'edit',
2828
2342
  createSchema: createAdminCrudEditActionSchema,
2829
2343
  });
2830
2344
  const createAdminCrudDeleteActionSchema = definitionSchema(() => baseAdminCrudActionSchema.extend({
2831
- type: z$i.literal('delete'),
2345
+ type: z$k.literal('delete'),
2832
2346
  }));
2833
2347
  const adminCrudDeleteActionType = createAdminCrudActionType({
2834
2348
  name: 'delete',
@@ -2839,38 +2353,15 @@ const BUILT_IN_ADMIN_CRUD_ACTIONS = [
2839
2353
  adminCrudDeleteActionType,
2840
2354
  ];
2841
2355
 
2842
- function createAdminCrudActionImplementation() {
2843
- const adminCrudActions = new Map(BUILT_IN_ADMIN_CRUD_ACTIONS.map((action) => [action.name, action]));
2844
- return {
2845
- registerAdminCrudAction(action) {
2846
- if (adminCrudActions.has(action.name)) {
2847
- throw new Error(`Admin CRUD action with name ${action.name} is already registered`);
2848
- }
2849
- adminCrudActions.set(action.name, action);
2850
- },
2851
- getAdminCrudActions() {
2852
- return adminCrudActions;
2853
- },
2854
- getAdminCrudAction(name) {
2855
- const action = adminCrudActions.get(name);
2856
- if (!action) {
2857
- throw new Error(`Unable to find action with name ${name}`);
2858
- }
2859
- return action;
2860
- },
2861
- };
2862
- }
2863
2356
  /**
2864
- * Spec for adding admin CRUD actions
2357
+ * Spec for registering additional admin CRUD table actions
2865
2358
  */
2866
- const adminCrudActionSpec = createPluginSpec('core/admin-crud-action', {
2867
- defaultInitializer: createAdminCrudActionImplementation,
2868
- });
2359
+ const adminCrudActionSpec = createFieldMapSpec('core/admin-crud-action', (t) => ({
2360
+ actions: t.namedArrayToMap(BUILT_IN_ADMIN_CRUD_ACTIONS),
2361
+ }));
2869
2362
 
2870
2363
  const createAdminCrudActionSchema = definitionSchema((ctx) => {
2871
- const adminCrudActions = ctx.plugins
2872
- .getPluginSpec(adminCrudActionSpec)
2873
- .getAdminCrudActions();
2364
+ const adminCrudActions = ctx.plugins.use(adminCrudActionSpec).actions;
2874
2365
  return baseAdminCrudActionSchema.transform((data) => {
2875
2366
  const actionDef = adminCrudActions.get(data.type);
2876
2367
  if (!actionDef)
@@ -2879,14 +2370,14 @@ const createAdminCrudActionSchema = definitionSchema((ctx) => {
2879
2370
  });
2880
2371
  });
2881
2372
 
2882
- const {z: z$h} = await importShared('zod');
2883
- const baseAdminCrudColumnSchema = z$h.looseObject({
2884
- id: z$h
2373
+ const {z: z$j} = await importShared('zod');
2374
+ const baseAdminCrudColumnSchema = z$j.looseObject({
2375
+ id: z$j
2885
2376
  .string()
2886
2377
  .min(1)
2887
2378
  .default(() => adminCrudColumnEntityType.generateNewId()),
2888
- type: z$h.string().min(1),
2889
- label: z$h.string().min(1),
2379
+ type: z$j.string().min(1),
2380
+ label: z$j.string().min(1),
2890
2381
  });
2891
2382
  function createAdminCrudColumnType(payload) {
2892
2383
  return payload;
@@ -2895,10 +2386,10 @@ const adminCrudColumnEntityType = createEntityType('admin-crud-column', {
2895
2386
  parentType: adminSectionEntityType,
2896
2387
  });
2897
2388
 
2898
- const {z: z$g} = await importShared('zod');
2389
+ const {z: z$i} = await importShared('zod');
2899
2390
  // Text Column
2900
2391
  const createAdminCrudTextColumnSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => baseAdminCrudColumnSchema.extend({
2901
- type: z$g.literal('text'),
2392
+ type: z$i.literal('text'),
2902
2393
  modelFieldRef: ctx.withRef({
2903
2394
  type: modelScalarFieldEntityType,
2904
2395
  onDelete: 'RESTRICT',
@@ -2911,14 +2402,14 @@ const adminCrudTextColumnType = createAdminCrudColumnType({
2911
2402
  });
2912
2403
  // Foreign Column
2913
2404
  const createAdminCrudForeignColumnSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => baseAdminCrudColumnSchema.extend({
2914
- type: z$g.literal('foreign'),
2405
+ type: z$i.literal('foreign'),
2915
2406
  localRelationRef: ctx.withRef({
2916
2407
  type: modelLocalRelationEntityType,
2917
2408
  onDelete: 'RESTRICT',
2918
2409
  parentSlot: modelSlot,
2919
2410
  }),
2920
- labelExpression: z$g.string().min(1),
2921
- valueExpression: z$g.string().min(1),
2411
+ labelExpression: z$i.string().min(1),
2412
+ valueExpression: z$i.string().min(1),
2922
2413
  }));
2923
2414
  const adminCrudForeignColumnType = createAdminCrudColumnType({
2924
2415
  name: 'foreign',
@@ -2928,39 +2419,16 @@ const BUILT_IN_ADMIN_CRUD_COLUMNS = [
2928
2419
  adminCrudTextColumnType,
2929
2420
  adminCrudForeignColumnType,
2930
2421
  ];
2931
-
2932
- function createAdminCrudColumnImplementation() {
2933
- const adminCrudColumns = new Map(BUILT_IN_ADMIN_CRUD_COLUMNS.map((column) => [column.name, column]));
2934
- return {
2935
- registerAdminCrudColumn(column) {
2936
- if (adminCrudColumns.has(column.name)) {
2937
- throw new Error(`Admin CRUD column with name ${column.name} is already registered`);
2938
- }
2939
- adminCrudColumns.set(column.name, column);
2940
- },
2941
- getAdminCrudColumns() {
2942
- return adminCrudColumns;
2943
- },
2944
- getAdminCrudColumn(name) {
2945
- const column = adminCrudColumns.get(name);
2946
- if (!column) {
2947
- throw new Error(`Unable to find column with name ${name}`);
2948
- }
2949
- return column;
2950
- },
2951
- };
2952
- }
2422
+
2953
2423
  /**
2954
- * Spec for adding admin CRUD columns
2424
+ * Spec for registering additional admin CRUD table columns
2955
2425
  */
2956
- const adminCrudColumnSpec = createPluginSpec('core/admin-crud-column', {
2957
- defaultInitializer: createAdminCrudColumnImplementation,
2958
- });
2426
+ const adminCrudColumnSpec = createFieldMapSpec('core/admin-crud-column', (t) => ({
2427
+ columns: t.namedArrayToMap(BUILT_IN_ADMIN_CRUD_COLUMNS),
2428
+ }));
2959
2429
 
2960
2430
  const createAdminCrudColumnSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, slots) => {
2961
- const adminCrudColumns = ctx.plugins
2962
- .getPluginSpec(adminCrudColumnSpec)
2963
- .getAdminCrudColumns();
2431
+ const adminCrudColumns = ctx.plugins.use(adminCrudColumnSpec).columns;
2964
2432
  return baseAdminCrudColumnSchema.transform((data) => {
2965
2433
  const columnDef = adminCrudColumns.get(data.type);
2966
2434
  if (!columnDef)
@@ -2969,14 +2437,14 @@ const createAdminCrudColumnSchema = definitionSchemaWithSlots({ modelSlot: model
2969
2437
  });
2970
2438
  });
2971
2439
 
2972
- const {z: z$f} = await importShared('zod');
2973
- const baseAdminCrudInputSchema = z$f.looseObject({
2974
- id: z$f
2440
+ const {z: z$h} = await importShared('zod');
2441
+ const baseAdminCrudInputSchema = z$h.looseObject({
2442
+ id: z$h
2975
2443
  .string()
2976
2444
  .min(1)
2977
2445
  .default(() => adminCrudInputEntityType.generateNewId()),
2978
- type: z$f.string().min(1),
2979
- label: z$f.string().min(1),
2446
+ type: z$h.string().min(1),
2447
+ label: z$h.string().min(1),
2980
2448
  });
2981
2449
  function createAdminCrudInputType(payload) {
2982
2450
  return payload;
@@ -2988,41 +2456,41 @@ const adminCrudInputEntityType = createEntityType('admin-crud-input', {
2988
2456
  parentType: adminSectionEntityType,
2989
2457
  });
2990
2458
 
2991
- const {z: z$e} = await importShared('zod');
2459
+ const {z: z$g} = await importShared('zod');
2992
2460
  const createAdminCrudTextInputSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, { modelSlot }) => baseAdminCrudInputSchema.extend({
2993
- type: z$e.literal('text'),
2994
- label: z$e.string().min(1),
2461
+ type: z$g.literal('text'),
2462
+ label: z$g.string().min(1),
2995
2463
  modelFieldRef: ctx.withRef({
2996
2464
  type: modelScalarFieldEntityType,
2997
2465
  onDelete: 'RESTRICT',
2998
2466
  parentSlot: modelSlot,
2999
2467
  }),
3000
- validation: z$e.string().optional(),
2468
+ validation: z$g.string().optional(),
3001
2469
  }));
3002
2470
  const adminCrudTextInputType = createAdminCrudInputType({
3003
2471
  name: 'text',
3004
2472
  createSchema: createAdminCrudTextInputSchema,
3005
2473
  });
3006
2474
  const createAdminCrudForeignInputSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, { modelSlot }) => baseAdminCrudInputSchema.extend({
3007
- type: z$e.literal('foreign'),
3008
- label: z$e.string().min(1),
2475
+ type: z$g.literal('foreign'),
2476
+ label: z$g.string().min(1),
3009
2477
  localRelationRef: ctx.withRef({
3010
2478
  type: modelLocalRelationEntityType,
3011
2479
  onDelete: 'RESTRICT',
3012
2480
  parentSlot: modelSlot,
3013
2481
  }),
3014
- labelExpression: z$e.string().min(1),
3015
- valueExpression: z$e.string().min(1),
3016
- defaultLabel: z$e.string().optional(),
3017
- nullLabel: z$e.string().optional(),
2482
+ labelExpression: z$g.string().min(1),
2483
+ valueExpression: z$g.string().min(1),
2484
+ defaultLabel: z$g.string().optional(),
2485
+ nullLabel: z$g.string().optional(),
3018
2486
  }));
3019
2487
  const adminCrudForeignInputType = createAdminCrudInputType({
3020
2488
  name: 'foreign',
3021
2489
  createSchema: createAdminCrudForeignInputSchema,
3022
2490
  });
3023
2491
  const createAdminCrudEnumInputSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, { modelSlot }) => baseAdminCrudInputSchema.extend({
3024
- type: z$e.literal('enum'),
3025
- label: z$e.string().min(1),
2492
+ type: z$g.literal('enum'),
2493
+ label: z$g.string().min(1),
3026
2494
  modelFieldRef: ctx.withRef({
3027
2495
  type: modelScalarFieldEntityType,
3028
2496
  onDelete: 'RESTRICT',
@@ -3034,8 +2502,8 @@ const adminCrudEnumInputType = createAdminCrudInputType({
3034
2502
  createSchema: createAdminCrudEnumInputSchema,
3035
2503
  });
3036
2504
  const createAdminCrudEmbeddedInputSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, { modelSlot, adminSectionSlot }) => baseAdminCrudInputSchema.extend({
3037
- type: z$e.literal('embedded'),
3038
- label: z$e.string().min(1),
2505
+ type: z$g.literal('embedded'),
2506
+ label: z$g.string().min(1),
3039
2507
  modelRelationRef: ctx.withRef({
3040
2508
  type: modelForeignRelationEntityType,
3041
2509
  onDelete: 'RESTRICT',
@@ -3052,8 +2520,8 @@ const adminCrudEmbeddedInputType = createAdminCrudInputType({
3052
2520
  createSchema: createAdminCrudEmbeddedInputSchema,
3053
2521
  });
3054
2522
  const createAdminCrudEmbeddedLocalInputSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, { modelSlot, adminSectionSlot }) => baseAdminCrudInputSchema.extend({
3055
- type: z$e.literal('embeddedLocal'),
3056
- label: z$e.string().min(1),
2523
+ type: z$g.literal('embeddedLocal'),
2524
+ label: z$g.string().min(1),
3057
2525
  localRelationRef: ctx.withRef({
3058
2526
  type: modelLocalRelationEntityType,
3059
2527
  onDelete: 'RESTRICT',
@@ -3070,200 +2538,520 @@ const adminCrudEmbeddedLocalInputType = createAdminCrudInputType({
3070
2538
  createSchema: createAdminCrudEmbeddedLocalInputSchema,
3071
2539
  });
3072
2540
  const createAdminCrudPasswordInputSchema = definitionSchema(() => baseAdminCrudInputSchema.extend({
3073
- type: z$e.literal('password'),
3074
- label: z$e.string().min(1),
2541
+ type: z$g.literal('password'),
2542
+ label: z$g.string().min(1),
3075
2543
  }));
3076
2544
  const adminCrudPasswordInputType = createAdminCrudInputType({
3077
2545
  name: 'password',
3078
2546
  createSchema: createAdminCrudPasswordInputSchema,
3079
2547
  });
3080
- const BUILT_IN_ADMIN_CRUD_INPUTS = [
3081
- adminCrudTextInputType,
3082
- adminCrudForeignInputType,
3083
- adminCrudEnumInputType,
3084
- adminCrudEmbeddedInputType,
3085
- adminCrudEmbeddedLocalInputType,
3086
- adminCrudPasswordInputType,
3087
- ];
2548
+ const BUILT_IN_ADMIN_CRUD_INPUTS = [
2549
+ adminCrudTextInputType,
2550
+ adminCrudForeignInputType,
2551
+ adminCrudEnumInputType,
2552
+ adminCrudEmbeddedInputType,
2553
+ adminCrudEmbeddedLocalInputType,
2554
+ adminCrudPasswordInputType,
2555
+ ];
2556
+
2557
+ /**
2558
+ * Spec for registering additional admin CRUD form inputs
2559
+ */
2560
+ const adminCrudInputSpec = createFieldMapSpec('core/admin-crud-input', (t) => ({
2561
+ inputs: t.namedArrayToMap(BUILT_IN_ADMIN_CRUD_INPUTS),
2562
+ }));
2563
+
2564
+ const createAdminCrudInputSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, slots) => {
2565
+ const adminCrudInputs = ctx.plugins.use(adminCrudInputSpec).inputs;
2566
+ return baseAdminCrudInputSchema.transform((data) => {
2567
+ const inputDef = adminCrudInputs.get(data.type);
2568
+ if (!inputDef)
2569
+ return data;
2570
+ return inputDef.createSchema(ctx, slots).parse(data);
2571
+ });
2572
+ });
2573
+
2574
+ const {z: z$f} = await importShared('zod');
2575
+ // Embedded Crud
2576
+ const createAdminCrudEmbeddedObjectSchemaInternal = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, { modelSlot, adminSectionSlot }) => z$f.object({
2577
+ id: z$f.string().min(1),
2578
+ name: z$f.string().min(1),
2579
+ modelRef: ctx.withRef({
2580
+ type: modelEntityType,
2581
+ onDelete: 'RESTRICT',
2582
+ provides: modelSlot,
2583
+ }),
2584
+ includeIdField: z$f.boolean().optional(),
2585
+ type: z$f.literal('object'),
2586
+ form: z$f.object({
2587
+ fields: z$f.array(createAdminCrudInputSchema(ctx, { modelSlot, adminSectionSlot })),
2588
+ }),
2589
+ }));
2590
+ const createAdminCrudEmbeddedListSchemaInternal = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, { modelSlot, adminSectionSlot }) => z$f.object({
2591
+ id: z$f.string().min(1),
2592
+ name: z$f.string().min(1),
2593
+ modelRef: ctx.withRef({
2594
+ type: modelEntityType,
2595
+ onDelete: 'RESTRICT',
2596
+ provides: modelSlot,
2597
+ }),
2598
+ includeIdField: z$f.boolean().optional(),
2599
+ type: z$f.literal('list'),
2600
+ table: z$f.object({
2601
+ columns: z$f.array(createAdminCrudColumnSchema(ctx, { modelSlot })),
2602
+ }),
2603
+ form: z$f.object({
2604
+ fields: z$f.array(createAdminCrudInputSchema(ctx, { modelSlot, adminSectionSlot })),
2605
+ }),
2606
+ }));
2607
+ const createAdminCrudEmbeddedFormSchema = definitionSchemaWithSlots({ adminSectionSlot: adminSectionEntityType }, (ctx, { adminSectionSlot }) => ctx.refContext({ modelSlot: modelEntityType }, ({ modelSlot }) => ctx.withEnt(z$f.discriminatedUnion('type', [
2608
+ createAdminCrudEmbeddedObjectSchemaInternal(ctx, {
2609
+ modelSlot,
2610
+ adminSectionSlot,
2611
+ }),
2612
+ createAdminCrudEmbeddedListSchemaInternal(ctx, {
2613
+ modelSlot,
2614
+ adminSectionSlot,
2615
+ }),
2616
+ ]), {
2617
+ type: adminCrudEmbeddedFormEntityType,
2618
+ parentSlot: adminSectionSlot,
2619
+ })));
2620
+ // Admin Section
2621
+ const createAdminCrudSectionSchema = definitionSchemaWithSlots({ adminSectionSlot: adminSectionEntityType }, (ctx, { adminSectionSlot }) => ctx.refContext({ modelSlot: modelEntityType }, ({ modelSlot }) => createBaseAdminSectionValidators(ctx).and(z$f.object({
2622
+ type: z$f.literal('crud'),
2623
+ modelRef: ctx.withRef({
2624
+ type: modelEntityType,
2625
+ onDelete: 'RESTRICT',
2626
+ provides: modelSlot,
2627
+ }),
2628
+ /* The field that will be used to display the name of the entity in the form */
2629
+ nameFieldRef: ctx.withRef({
2630
+ type: modelScalarFieldEntityType,
2631
+ onDelete: 'RESTRICT',
2632
+ parentSlot: modelSlot,
2633
+ }),
2634
+ disableCreate: ctx.withDefault(z$f.boolean(), false),
2635
+ table: z$f.object({
2636
+ columns: z$f.array(createAdminCrudColumnSchema(ctx, { modelSlot })),
2637
+ actions: ctx.withDefault(z$f.array(createAdminCrudActionSchema(ctx)), [
2638
+ { type: 'edit', position: 'inline' },
2639
+ { type: 'delete', position: 'dropdown' },
2640
+ ]),
2641
+ }),
2642
+ form: z$f.object({
2643
+ fields: z$f.array(createAdminCrudInputSchema(ctx, {
2644
+ modelSlot,
2645
+ adminSectionSlot,
2646
+ })),
2647
+ }),
2648
+ embeddedForms: z$f
2649
+ .array(createAdminCrudEmbeddedFormSchema(ctx, { adminSectionSlot }))
2650
+ .optional(),
2651
+ }))));
2652
+
2653
+ const {z: z$e} = await importShared('zod');
2654
+ const createWebAdminSectionSchema = definitionSchemaWithSlots({ appSlot: appEntityType }, (ctx, { appSlot }) => ctx.refContext({ adminSectionSlot: adminSectionEntityType }, ({ adminSectionSlot }) => ctx.withEnt(createAdminCrudSectionSchema(ctx, { adminSectionSlot }), {
2655
+ type: adminSectionEntityType,
2656
+ parentSlot: appSlot,
2657
+ provides: adminSectionSlot,
2658
+ })));
2659
+ const createAdminAppSchema = definitionSchemaWithSlots({ appSlot: appEntityType }, (ctx, { appSlot }) => ctx.withDefault(z$e.object({
2660
+ enabled: z$e.boolean(),
2661
+ pathPrefix: z$e.string().default('/admin'),
2662
+ allowedRoles: ctx.withDefault(z$e.array(ctx.withRef({
2663
+ type: authRoleEntityType,
2664
+ onDelete: 'DELETE',
2665
+ })), []),
2666
+ sections: ctx.withDefault(z$e.array(createWebAdminSectionSchema(ctx, { appSlot })), []),
2667
+ }), { enabled: false, pathPrefix: '/admin' }));
2668
+
2669
+ const {z: z$d} = await importShared('zod');
2670
+ const createWebAppSchema = definitionSchemaWithSlots({ appSlot: appEntityType }, (ctx, { appSlot }) => z$d.object({
2671
+ ...baseAppValidators,
2672
+ type: z$d.literal('web'),
2673
+ includeAuth: ctx.withDefault(z$d.boolean(), false),
2674
+ title: z$d.string().default(''),
2675
+ description: z$d.string().default(''),
2676
+ includeUploadComponents: ctx.withDefault(z$d.boolean(), false),
2677
+ enableSubscriptions: ctx.withDefault(z$d.boolean(), false),
2678
+ adminApp: createAdminAppSchema(ctx, { appSlot }),
2679
+ }));
2680
+ const webAppEntryType = createAppEntryType('web');
2681
+
2682
+ const libraryEntityType = createEntityType('library');
2683
+
2684
+ const {CASE_VALIDATORS: CASE_VALIDATORS$2} = await importShared('@baseplate-dev/utils');
2685
+
2686
+ const {z: z$c} = await importShared('zod');
2687
+ const baseLibraryValidators = {
2688
+ id: z$c.string().default(libraryEntityType.generateNewId()),
2689
+ name: CASE_VALIDATORS$2.KEBAB_CASE,
2690
+ type: z$c.string(),
2691
+ };
2692
+ const baseLibrarySchema = z$c.object(baseLibraryValidators);
2693
+
2694
+ /**
2695
+ * Strip object of any values that are empty arrays, empty objects, null, or undefined
2696
+ */
2697
+ function stripEmptyGeneratorChildren(children) {
2698
+ return pickBy(children, (value) => value !== undefined && !(Array.isArray(value) && value.length === 0));
2699
+ }
2700
+ /**
2701
+ * Strip object of any values that are undefined
2702
+ */
2703
+ function stripUndefinedValues(obj) {
2704
+ return pickBy(obj, (value) => value !== undefined);
2705
+ }
2706
+ /**
2707
+ * Returns undefined if the value is an empty object (as defined by all values are undefined)/array/null, otherwise return value.
2708
+ */
2709
+ function undefinedIfEmpty(value) {
2710
+ if (value === null)
2711
+ return undefined;
2712
+ if (Array.isArray(value) && value.length === 0) {
2713
+ return undefined;
2714
+ }
2715
+ if (typeof value === 'object' &&
2716
+ Object.keys(value).every((key) => value[key] === undefined)) {
2717
+ return undefined;
2718
+ }
2719
+ return value;
2720
+ }
2721
+ /**
2722
+ * Returns undefined if the value is falsy, otherwise return value.
2723
+ */
2724
+ function undefinedIfFalsy(value) {
2725
+ if (!value)
2726
+ return undefined;
2727
+ return value;
2728
+ }
2729
+
2730
+ /**
2731
+ * Store for managing plugin spec instances with lazy initialization.
2732
+ *
2733
+ * Each spec is initialized once on first access, and both its init and use
2734
+ * interfaces are cached for subsequent access.
2735
+ */
2736
+ class PluginSpecStore {
2737
+ instances;
2738
+ useInstances = new Map();
2739
+ constructor(instances = new Map()) {
2740
+ this.instances = instances;
2741
+ }
2742
+ /**
2743
+ * Gets the use interface for a spec.
2744
+ *
2745
+ * Use this after initialization to access registered items.
2746
+ * The use interface provides read-only methods for consumption.
2747
+ *
2748
+ * @param spec - The plugin spec to get the use interface for
2749
+ * @returns The use interface for the spec
2750
+ */
2751
+ use(spec) {
2752
+ let specInstance = this.instances.get(spec.name);
2753
+ if (!specInstance) {
2754
+ specInstance = spec.initializer();
2755
+ this.instances.set(spec.name, specInstance);
2756
+ }
2757
+ let useInstance = this.useInstances.get(spec.name);
2758
+ if (!useInstance) {
2759
+ useInstance = specInstance.use();
2760
+ this.useInstances.set(spec.name, useInstance);
2761
+ }
2762
+ return useInstance;
2763
+ }
2764
+ }
2765
+
2766
+ const {assertNoDuplicates} = await importShared('@baseplate-dev/utils');
2767
+ /**
2768
+ * Initialize ordered plugin modules.
2769
+ * Each module's initialize function is called within a plugin context.
2770
+ */
2771
+ function initializeOrderedModules(orderedModules) {
2772
+ const instances = new Map();
2773
+ function use(spec) {
2774
+ if (!instances.has(spec.name)) {
2775
+ const instance = spec.initializer();
2776
+ instances.set(spec.name, instance);
2777
+ }
2778
+ return instances.get(spec.name);
2779
+ }
2780
+ for (const { module, key: moduleKey, pluginKey } of orderedModules) {
2781
+ // Resolve dependencies by getting their setup interfaces
2782
+ const dependencies = module.dependencies
2783
+ ? stripUndefinedValues(mapValues(module.dependencies, (spec) => use(spec).init))
2784
+ : {};
2785
+ // Run initialize within plugin context for source tracking
2786
+ runInPluginContext({ moduleKey, pluginKey }, () => {
2787
+ module.initialize(dependencies, { moduleKey, pluginKey });
2788
+ });
2789
+ }
2790
+ return instances;
2791
+ }
2792
+ /**
2793
+ * Initialize the plugins based on their interdependencies.
2794
+ * Returns a store that can be used to access spec implementations.
2795
+ */
2796
+ function initializePlugins(pluginModules) {
2797
+ assertNoDuplicates(pluginModules, 'plugin modules', (m) => m.key);
2798
+ const instances = initializeOrderedModules(pluginModules);
2799
+ return new PluginSpecStore(instances);
2800
+ }
2801
+
2802
+ /**
2803
+ * Creates a plugin module export.
2804
+ *
2805
+ * @example
2806
+ * ```typescript
2807
+ * export default createPluginModule({
2808
+ * name: 'node',
2809
+ * dependencies: {
2810
+ * config: pluginConfigSpec,
2811
+ * },
2812
+ * initialize: ({ config }, ctx) => {
2813
+ * config.registerSchemaCreator(ctx.pluginKey, createSchema);
2814
+ * },
2815
+ * });
2816
+ * ```
2817
+ */
2818
+ function createPluginModule(config) {
2819
+ return config;
2820
+ }
2821
+
2822
+ /**
2823
+ * Gets a plugin metadata object by its key.
2824
+ *
2825
+ * @param pluginStore The plugin store to use
2826
+ * @param key The key of the plugin to get
2827
+ * @returns The plugin metadata object or undefined if the plugin is not found
2828
+ */
2829
+ function getPluginMetadataByKey(pluginStore, key) {
2830
+ return pluginStore.availablePlugins.find((p) => p.metadata.key === key)
2831
+ ?.metadata;
2832
+ }
2833
+ /**
2834
+ * Gets a plugin metadata object by its key.
2835
+ *
2836
+ * @param pluginStore The plugin store to use
2837
+ * @param key The key of the plugin to get
2838
+ * @returns The plugin metadata object
2839
+ * @throws An error if the plugin is not found
2840
+ */
2841
+ function getPluginMetadataByKeyOrThrow(pluginStore, key) {
2842
+ const metadata = getPluginMetadataByKey(pluginStore, key);
2843
+ if (!metadata) {
2844
+ throw new Error(`Could not find plugin with key ${key}`);
2845
+ }
2846
+ return metadata;
2847
+ }
2848
+ function getManagedPluginsForPlugin(pluginStore, pluginKey) {
2849
+ const plugin = getPluginMetadataByKeyOrThrow(pluginStore, pluginKey);
2850
+ return pluginStore.availablePlugins
2851
+ .filter((p) => p.metadata.managedBy === plugin.fullyQualifiedName)
2852
+ .map((p) => p.metadata);
2853
+ }
2854
+
2855
+ const {z: z$b} = await importShared('zod');
2856
+
2857
+ // matches semver
2858
+ const versionSchema = z$b.string().regex(/^(\d+\.\d+\.\d+)$/);
2859
+ const pluginSpecSupportSchema = z$b.object({
2860
+ spec: z$b.string().min(1),
2861
+ version: z$b.string().min(1),
2862
+ });
2863
+ const pluginSpecDependencySchema = z$b.object({
2864
+ spec: z$b.string(),
2865
+ version: z$b.string(),
2866
+ });
2867
+ /**
2868
+ * Schema for the plugin's metadata (plugin.json)
2869
+ */
2870
+ const pluginMetadataSchema = z$b.object({
2871
+ /**
2872
+ * The name of the plugin - must be lowercase and contain only letters, numbers, and hyphens
2873
+ */
2874
+ name: z$b
2875
+ .string()
2876
+ .min(1)
2877
+ .regex(/^[a-z0-9-]+$/),
2878
+ /**
2879
+ * A list of directories with entrypoints in them. Defaults to ['.']
2880
+ */
2881
+ moduleDirectories: z$b.array(z$b.string()).optional(),
2882
+ /**
2883
+ * The display name of the plugin
2884
+ */
2885
+ displayName: z$b.string().min(1),
2886
+ /**
2887
+ * The icon to display for the plugin as a pointer to the icon in the plugin's static folder
2888
+ */
2889
+ icon: z$b.string().optional(),
2890
+ /**
2891
+ * A description of the plugin
2892
+ */
2893
+ description: z$b.string(),
2894
+ /**
2895
+ * The fully qualified name of the plugin that manages this plugin,
2896
+ * e.g. "@baseplate-dev/plugin-auth:auth0" would be managed by the "@baseplate-dev/plugin-auth:auth" plugin.
2897
+ *
2898
+ * Managed plugins do not appear in the plugin list but are managed by the base plugin. If the base
2899
+ * plugin is disabled, the managed plugins will also be disabled.
2900
+ */
2901
+ managedBy: z$b.string().optional(),
2902
+ /**
2903
+ * The version of the plugin using semver
2904
+ */
2905
+ version: versionSchema,
2906
+ /**
2907
+ * Configuration for the specs that the plugin exports/depends on
2908
+ */
2909
+ specs: z$b
2910
+ .object({
2911
+ /**
2912
+ * The specs that the plugin exports
2913
+ */
2914
+ exports: z$b.array(pluginSpecSupportSchema).optional(),
2915
+ /**
2916
+ * The specs that the plugin depends on
2917
+ */
2918
+ dependencies: z$b.array(pluginSpecDependencySchema).optional(),
2919
+ })
2920
+ .optional(),
2921
+ /**
2922
+ * Whether the plugin should be hidden in the project builder UI
2923
+ *
2924
+ * (It can be used once in the definition but cannot be added)
2925
+ */
2926
+ hidden: z$b.boolean().optional(),
2927
+ });
3088
2928
 
3089
- function createAdminCrudInputImplementation() {
3090
- const adminCrudInputs = new Map(BUILT_IN_ADMIN_CRUD_INPUTS.map((input) => [input.name, input]));
3091
- return {
3092
- registerAdminCrudInput(input) {
3093
- if (adminCrudInputs.has(input.name)) {
3094
- throw new Error(`Admin CRUD input with name ${input.name} is already registered`);
3095
- }
3096
- adminCrudInputs.set(input.name, input);
3097
- },
3098
- getAdminCrudInputs() {
3099
- return adminCrudInputs;
3100
- },
3101
- getAdminCrudInput(name) {
3102
- const input = adminCrudInputs.get(name);
3103
- if (!input) {
3104
- throw new Error(`Unable to find input with name ${name}`);
3105
- }
3106
- return input;
3107
- },
3108
- };
2929
+ const pluginEntityType = createEntityType('plugin');
2930
+
2931
+ const {mapValuesOfMap} = await importShared('@baseplate-dev/utils');
2932
+ function sortAndValidateMigrations(migrations, pluginKey) {
2933
+ // make sure migrations are sorted by version and they are all unique
2934
+ const sortedMigrations = [...migrations].sort((a, b) => a.version - b.version);
2935
+ if (sortedMigrations.some((m) => m.version <= 0)) {
2936
+ throw new Error(`All migrations for plugin ${pluginKey} must have a positive version`);
2937
+ }
2938
+ for (let i = 0; i < sortedMigrations.length - 1; i++) {
2939
+ if (sortedMigrations[i].version === sortedMigrations[i + 1].version) {
2940
+ throw new Error(`All migrations for plugin ${pluginKey} must have a unique version`);
2941
+ }
2942
+ }
2943
+ return sortedMigrations;
3109
2944
  }
3110
2945
  /**
3111
- * Spec for adding admin crud input
2946
+ * Spec for adding config for the plugin in the core plugin e.g.
2947
+ * {
2948
+ * "plugins": [{
2949
+ * "id": "...",
2950
+ * "config": {
2951
+ * ...PluginConfig schema
2952
+ * }
2953
+ * }]
2954
+ * }
3112
2955
  */
3113
- const adminCrudInputSpec = createPluginSpec('core/admin-crud-input', {
3114
- defaultInitializer: createAdminCrudInputImplementation,
2956
+ const pluginConfigSpec = createFieldMapSpec('core/plugin-config', (t) => ({
2957
+ schemas: t.map(),
2958
+ migrations: t.map(),
2959
+ }), {
2960
+ use: (values) => {
2961
+ const validatedMigrations = mapValuesOfMap(values.migrations, (migrations, pluginKey) => sortAndValidateMigrations(migrations, pluginKey));
2962
+ return {
2963
+ getSchemaCreator: (pluginKey) => values.schemas.get(pluginKey),
2964
+ getMigrations: (pluginKey) => validatedMigrations.get(pluginKey),
2965
+ getLastMigrationVersion: (pluginKey) => {
2966
+ const migrations = values.migrations.get(pluginKey);
2967
+ return migrations?.[migrations.length - 1]?.version;
2968
+ },
2969
+ };
2970
+ },
3115
2971
  });
3116
2972
 
3117
- const createAdminCrudInputSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, slots) => {
3118
- const adminCrudInputs = ctx.plugins
3119
- .getPluginSpec(adminCrudInputSpec)
3120
- .getAdminCrudInputs();
3121
- return baseAdminCrudInputSchema.transform((data) => {
3122
- const inputDef = adminCrudInputs.get(data.type);
3123
- if (!inputDef)
3124
- return data;
3125
- return inputDef.createSchema(ctx, slots).parse(data);
2973
+ function runPluginMigrations(projectDefinition, pluginSpecStore) {
2974
+ const pluginConfigService = pluginSpecStore.use(pluginConfigSpec);
2975
+ return produce(projectDefinition, (draft) => {
2976
+ for (const pluginDefinition of draft.plugins ?? []) {
2977
+ const pluginMigrations = pluginConfigService.getMigrations(pluginEntityType.keyFromId(pluginDefinition.id));
2978
+ const currentSchemaVersion = pluginDefinition.configSchemaVersion ?? -1;
2979
+ if (!pluginMigrations)
2980
+ continue;
2981
+ const lastPluginMigration = pluginMigrations.at(-1);
2982
+ if (!lastPluginMigration)
2983
+ continue;
2984
+ for (const migration of pluginMigrations) {
2985
+ if (migration.version > currentSchemaVersion) {
2986
+ try {
2987
+ const migrationResult = migration.migrate(pluginDefinition.config, draft);
2988
+ if (migrationResult.updatedConfig !== undefined) {
2989
+ pluginDefinition.config = migrationResult.updatedConfig;
2990
+ }
2991
+ if (migrationResult.updateProjectDefinition) {
2992
+ migrationResult.updateProjectDefinition(draft);
2993
+ }
2994
+ }
2995
+ catch (error) {
2996
+ throw new Error(`Error migrating plugin ${pluginDefinition.id} to version ${migration.version}: ${String(error)}`);
2997
+ }
2998
+ }
2999
+ }
3000
+ pluginDefinition.configSchemaVersion = lastPluginMigration.version;
3001
+ }
3126
3002
  });
3127
- });
3003
+ }
3128
3004
 
3129
- const {z: z$d} = await importShared('zod');
3130
- // Embedded Crud
3131
- const createAdminCrudEmbeddedObjectSchemaInternal = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, { modelSlot, adminSectionSlot }) => z$d.object({
3132
- id: z$d.string().min(1),
3133
- name: z$d.string().min(1),
3134
- modelRef: ctx.withRef({
3135
- type: modelEntityType,
3136
- onDelete: 'RESTRICT',
3137
- provides: modelSlot,
3138
- }),
3139
- includeIdField: z$d.boolean().optional(),
3140
- type: z$d.literal('object'),
3141
- form: z$d.object({
3142
- fields: z$d.array(createAdminCrudInputSchema(ctx, { modelSlot, adminSectionSlot })),
3143
- }),
3144
- }));
3145
- const createAdminCrudEmbeddedListSchemaInternal = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, { modelSlot, adminSectionSlot }) => z$d.object({
3146
- id: z$d.string().min(1),
3147
- name: z$d.string().min(1),
3148
- modelRef: ctx.withRef({
3149
- type: modelEntityType,
3150
- onDelete: 'RESTRICT',
3151
- provides: modelSlot,
3152
- }),
3153
- includeIdField: z$d.boolean().optional(),
3154
- type: z$d.literal('list'),
3155
- table: z$d.object({
3156
- columns: z$d.array(createAdminCrudColumnSchema(ctx, { modelSlot })),
3157
- }),
3158
- form: z$d.object({
3159
- fields: z$d.array(createAdminCrudInputSchema(ctx, { modelSlot, adminSectionSlot })),
3160
- }),
3161
- }));
3162
- const createAdminCrudEmbeddedFormSchema = definitionSchemaWithSlots({ adminSectionSlot: adminSectionEntityType }, (ctx, { adminSectionSlot }) => ctx.refContext({ modelSlot: modelEntityType }, ({ modelSlot }) => ctx.withEnt(z$d.discriminatedUnion('type', [
3163
- createAdminCrudEmbeddedObjectSchemaInternal(ctx, {
3164
- modelSlot,
3165
- adminSectionSlot,
3166
- }),
3167
- createAdminCrudEmbeddedListSchemaInternal(ctx, {
3168
- modelSlot,
3169
- adminSectionSlot,
3170
- }),
3171
- ]), {
3172
- type: adminCrudEmbeddedFormEntityType,
3173
- parentSlot: adminSectionSlot,
3174
- })));
3175
- // Admin Section
3176
- const createAdminCrudSectionSchema = definitionSchemaWithSlots({ adminSectionSlot: adminSectionEntityType }, (ctx, { adminSectionSlot }) => ctx.refContext({ modelSlot: modelEntityType }, ({ modelSlot }) => createBaseAdminSectionValidators(ctx).and(z$d.object({
3177
- type: z$d.literal('crud'),
3178
- modelRef: ctx.withRef({
3179
- type: modelEntityType,
3180
- onDelete: 'RESTRICT',
3181
- provides: modelSlot,
3182
- }),
3183
- /* The field that will be used to display the name of the entity in the form */
3184
- nameFieldRef: ctx.withRef({
3185
- type: modelScalarFieldEntityType,
3186
- onDelete: 'RESTRICT',
3187
- parentSlot: modelSlot,
3188
- }),
3189
- disableCreate: ctx.withDefault(z$d.boolean(), false),
3190
- table: z$d.object({
3191
- columns: z$d.array(createAdminCrudColumnSchema(ctx, { modelSlot })),
3192
- actions: ctx.withDefault(z$d.array(createAdminCrudActionSchema(ctx)), [
3193
- { type: 'edit', position: 'inline' },
3194
- { type: 'delete', position: 'dropdown' },
3195
- ]),
3196
- }),
3197
- form: z$d.object({
3198
- fields: z$d.array(createAdminCrudInputSchema(ctx, {
3199
- modelSlot,
3200
- adminSectionSlot,
3201
- })),
3005
+ /**
3006
+ * Spec for allowing plugins to declare standard auth configurations
3007
+ */
3008
+ const authConfigSpec = createFieldMapSpec('core/auth-config', (t) => ({
3009
+ getAuthConfig: t.scalar(),
3010
+ }), {
3011
+ use: (values) => ({
3012
+ getAuthConfig: (definition) => values.getAuthConfig?.(definition),
3013
+ getAuthConfigOrThrow: (definition) => {
3014
+ const config = values.getAuthConfig?.(definition);
3015
+ if (!config) {
3016
+ throw new Error('Auth config not found');
3017
+ }
3018
+ return config;
3019
+ },
3202
3020
  }),
3203
- embeddedForms: z$d
3204
- .array(createAdminCrudEmbeddedFormSchema(ctx, { adminSectionSlot }))
3205
- .optional(),
3206
- }))));
3021
+ });
3207
3022
 
3208
- const {z: z$c} = await importShared('zod');
3209
- const createWebAdminSectionSchema = definitionSchemaWithSlots({ appSlot: appEntityType }, (ctx, { appSlot }) => ctx.refContext({ adminSectionSlot: adminSectionEntityType }, ({ adminSectionSlot }) => ctx.withEnt(createAdminCrudSectionSchema(ctx, { adminSectionSlot }), {
3210
- type: adminSectionEntityType,
3211
- parentSlot: appSlot,
3212
- provides: adminSectionSlot,
3213
- })));
3214
- const createAdminAppSchema = definitionSchemaWithSlots({ appSlot: appEntityType }, (ctx, { appSlot }) => ctx.withDefault(z$c.object({
3215
- enabled: z$c.boolean(),
3216
- pathPrefix: z$c.string().default('/admin'),
3217
- allowedRoles: ctx.withDefault(z$c.array(ctx.withRef({
3218
- type: authRoleEntityType,
3219
- onDelete: 'DELETE',
3220
- })), []),
3221
- sections: ctx.withDefault(z$c.array(createWebAdminSectionSchema(ctx, { appSlot })), []),
3222
- }), { enabled: false, pathPrefix: '/admin' }));
3023
+ const authModelsSpec = createFieldMapSpec('core/auth-models', (t) => ({
3024
+ getAuthModels: t.scalar(),
3025
+ }), {
3026
+ use: (values) => ({
3027
+ getAuthModels: (definition) => values.getAuthModels?.(definition),
3028
+ getAuthModelsOrThrow: (definition) => {
3029
+ const authModels = values.getAuthModels?.(definition);
3030
+ if (!authModels) {
3031
+ throw new Error('Auth models not found');
3032
+ }
3033
+ return authModels;
3034
+ },
3035
+ }),
3036
+ });
3223
3037
 
3224
- const {z: z$b} = await importShared('zod');
3225
- const createWebAppSchema = definitionSchemaWithSlots({ appSlot: appEntityType }, (ctx, { appSlot }) => z$b.object({
3226
- ...baseAppValidators,
3227
- type: z$b.literal('web'),
3228
- includeAuth: ctx.withDefault(z$b.boolean(), false),
3229
- title: z$b.string().default(''),
3230
- description: z$b.string().default(''),
3231
- includeUploadComponents: ctx.withDefault(z$b.boolean(), false),
3232
- enableSubscriptions: ctx.withDefault(z$b.boolean(), false),
3233
- adminApp: createAdminAppSchema(ctx, { appSlot }),
3038
+ /**
3039
+ * Spec for adding config component for plugin
3040
+ *
3041
+ * Keyed by plugin key, value is the config component.
3042
+ */
3043
+ const webConfigSpec = createFieldMapSpec('core/web-config', (t) => ({
3044
+ components: t.map(),
3234
3045
  }));
3235
- const webAppEntryType = createAppEntryType('web');
3236
-
3237
- const packageEntityType = createEntityType('package');
3238
- function createPackageEntryType(name) {
3239
- return name;
3240
- }
3241
-
3242
- const {CASE_VALIDATORS: CASE_VALIDATORS$2} = await importShared('@baseplate-dev/utils');
3243
3046
 
3244
3047
  const {z: z$a} = await importShared('zod');
3245
- const basePackageValidators = {
3246
- id: z$a.string().default(packageEntityType.generateNewId()),
3247
- name: CASE_VALIDATORS$2.KEBAB_CASE,
3248
- type: z$a.string(),
3249
- };
3250
- const basePackageSchema = z$a.object(basePackageValidators);
3251
-
3252
- const {z: z$9} = await importShared('zod');
3253
- const createNodeLibraryPackageSchema = definitionSchemaWithSlots({ packageSlot: packageEntityType }, () => z$9.object({
3254
- ...basePackageValidators,
3255
- type: z$9.literal('node-library'),
3256
- }));
3257
- const nodeLibraryPackageEntryType = createPackageEntryType('node-library');
3258
-
3259
- const {z: z$8} = await importShared('zod');
3260
- const basePluginDefinitionSchema = z$8.object({
3261
- id: z$8.string(),
3262
- packageName: z$8.string(),
3263
- name: z$8.string(),
3264
- version: z$8.string(),
3265
- config: z$8.unknown(),
3266
- configSchemaVersion: z$8.number().optional(),
3048
+ const basePluginDefinitionSchema = z$a.object({
3049
+ id: z$a.string(),
3050
+ packageName: z$a.string(),
3051
+ name: z$a.string(),
3052
+ version: z$a.string(),
3053
+ config: z$a.unknown(),
3054
+ configSchemaVersion: z$a.number().optional(),
3267
3055
  });
3268
3056
  const createPluginWithConfigSchema = definitionSchema((ctx) => ctx
3269
3057
  .withEnt(basePluginDefinitionSchema, {
@@ -3272,7 +3060,7 @@ const createPluginWithConfigSchema = definitionSchema((ctx) => ctx
3272
3060
  .transform((data) => {
3273
3061
  const pluginKey = pluginEntityType.keyFromId(data.id);
3274
3062
  const createConfigSchema = ctx.plugins
3275
- .getPluginSpec(pluginConfigSpec)
3063
+ .use(pluginConfigSpec)
3276
3064
  .getSchemaCreator(pluginKey);
3277
3065
  if (!createConfigSchema)
3278
3066
  return data;
@@ -3281,7 +3069,45 @@ const createPluginWithConfigSchema = definitionSchema((ctx) => ctx
3281
3069
  config: createConfigSchema(ctx).parse(data.config),
3282
3070
  };
3283
3071
  }));
3284
- const createPluginsSchema = definitionSchema((ctx) => z$8.array(createPluginWithConfigSchema(ctx)));
3072
+ const createPluginsSchema = definitionSchema((ctx) => z$a.array(createPluginWithConfigSchema(ctx)));
3073
+
3074
+ const z$9 = await importShared('zod');
3075
+ const createNodeLibrarySchema = definitionSchemaWithSlots({ librarySlot: libraryEntityType }, () => z$9.object({
3076
+ ...baseLibraryValidators,
3077
+ type: z$9.literal('node-library'),
3078
+ }));
3079
+ const nodeLibraryDefinitionSchemaEntry = {
3080
+ name: 'node-library',
3081
+ definitionSchema: createNodeLibrarySchema,
3082
+ };
3083
+ /**
3084
+ * Creates a typed library web config
3085
+ */
3086
+ function createLibraryWebConfig(config) {
3087
+ return config;
3088
+ }
3089
+ /**
3090
+ * Package type spec for registering package schemas, compilers, and web configs.
3091
+ */
3092
+ const libraryTypeSpec = createFieldMapSpec('core/library-type', (t) => ({
3093
+ schemaCreators: t.namedArrayToMap([
3094
+ nodeLibraryDefinitionSchemaEntry,
3095
+ ]),
3096
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3097
+ compilerCreators: t.namedArrayToMap(),
3098
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3099
+ webConfigs: t.namedArrayToMap(),
3100
+ }));
3101
+
3102
+ const z$8 = await importShared('zod');
3103
+ const createLibrarySchema = definitionSchema((ctx) => ctx.refContext({ librarySlot: libraryEntityType }, ({ librarySlot }) => {
3104
+ const packageTypes = ctx.plugins.use(libraryTypeSpec);
3105
+ const schemas = [...packageTypes.schemaCreators.values()].map((entry) => entry.definitionSchema(ctx, { librarySlot }));
3106
+ return ctx.withEnt(z$8.discriminatedUnion('type', schemas), {
3107
+ type: libraryEntityType,
3108
+ provides: librarySlot,
3109
+ });
3110
+ }));
3285
3111
 
3286
3112
  const {CASE_VALIDATORS: CASE_VALIDATORS$1} = await importShared('@baseplate-dev/utils');
3287
3113
 
@@ -3364,7 +3190,7 @@ const {z: z$5} = await importShared('zod');
3364
3190
  /**
3365
3191
  * Monorepo settings schema
3366
3192
  *
3367
- * Configures the folder structure for monorepo packages.
3193
+ * Configures the folder structure for monorepo apps and libraries.
3368
3194
  */
3369
3195
  const monorepoSettingsSchema = z$5.object({
3370
3196
  /**
@@ -3384,21 +3210,21 @@ const monorepoSettingsSchema = z$5.object({
3384
3210
  })
3385
3211
  .default('apps'),
3386
3212
  /**
3387
- * The folder where library packages are located in the monorepo.
3213
+ * The folder where libraries are located in the monorepo.
3388
3214
  *
3389
3215
  * Must be in kebab-case format (lowercase letters and dashes only).
3390
- * Packages will be placed in {packagesFolder}/{package-name}, e.g. "packages/shared-utils".
3216
+ * Libraries will be placed in {librariesFolder}/{library-name}, e.g. "libs/shared-utils".
3391
3217
  *
3392
- * @default "packages"
3393
- * @example "packages" → packages/shared-utils, packages/common
3218
+ * @default "libs"
3394
3219
  * @example "libs" → libs/shared-utils, libs/common
3220
+ * @example "packages" → packages/shared-utils, packages/common
3395
3221
  */
3396
- packagesFolder: CASE_VALIDATORS.KEBAB_CASE.min(1)
3222
+ librariesFolder: CASE_VALIDATORS.KEBAB_CASE.min(1)
3397
3223
  .max(50)
3398
3224
  .regex(/^[a-z0-9-]+$/, {
3399
- message: 'Packages folder must contain only lowercase letters, numbers, and dashes (no slashes)',
3225
+ message: 'Libraries folder must contain only lowercase letters, numbers, and dashes (no slashes)',
3400
3226
  })
3401
- .default('packages'),
3227
+ .default('libs'),
3402
3228
  });
3403
3229
 
3404
3230
  const {z: z$4} = await importShared('zod');
@@ -3590,17 +3416,10 @@ const createAppSchema = definitionSchema((ctx) => ctx.refContext({ appSlot: appE
3590
3416
  type: appEntityType,
3591
3417
  provides: appSlot,
3592
3418
  })));
3593
- const createPackageSchema = definitionSchema((ctx) => ctx.refContext({ packageSlot: packageEntityType }, ({ packageSlot }) => ctx.withEnt(z$1.discriminatedUnion('type', [
3594
- createNodeLibraryPackageSchema(ctx, { packageSlot }),
3595
- // Future: add more package types here
3596
- ]), {
3597
- type: packageEntityType,
3598
- provides: packageSlot,
3599
- })));
3600
3419
  const createProjectDefinitionSchema = definitionSchema((ctx) => z$1.object({
3601
3420
  cliVersion: z$1.string().nullish(),
3602
3421
  apps: z$1.array(createAppSchema(ctx)).default([]),
3603
- packages: z$1.array(createPackageSchema(ctx)).default([]),
3422
+ libraries: z$1.array(createLibrarySchema(ctx)).default([]),
3604
3423
  features: createFeaturesSchema(ctx),
3605
3424
  models: z$1.array(createModelSchema(ctx)).default([]),
3606
3425
  enums: z$1.array(createEnumSchema(ctx)).optional(),
@@ -3712,49 +3531,51 @@ const ModelFieldUtils = {
3712
3531
  relationByIdOrThrow,
3713
3532
  };
3714
3533
 
3715
- function getTransformer(transformer, pluginStore) {
3716
- const transformers = pluginStore.getPluginSpec(modelTransformerSpec);
3717
- return transformers.getModelTransformer(transformer.type);
3718
- }
3719
- function getTransformName(definitionContainer, transformer, pluginStore) {
3720
- const transformers = pluginStore.getPluginSpec(modelTransformerSpec);
3721
- return transformers
3722
- .getModelTransformer(transformer.type)
3723
- .getName(definitionContainer, transformer);
3534
+ function getTransformerName(definitionContainer, transformer, pluginStore) {
3535
+ const { transformers } = pluginStore.use(modelTransformerSpec);
3536
+ const transformerType = transformers.get(transformer.type);
3537
+ if (!transformerType) {
3538
+ throw new Error(`Unable to find transformer with name ${transformer.type}`);
3539
+ }
3540
+ return transformerType.getName(definitionContainer, transformer);
3724
3541
  }
3725
- const ModelTransformerUtils = { getTransformer, getTransformName };
3542
+ const ModelTransformerUtils = { getTransformerName };
3726
3543
 
3727
3544
  function byId(projectDefinition, id) {
3728
- const config = projectDefinition.packages.find((pkg) => pkg.id === id);
3545
+ const config = projectDefinition.libraries.find((lib) => lib.id === id);
3729
3546
  if (!config) {
3730
- throw new Error(`Unable to find package with ID ${id}`);
3547
+ throw new Error(`Unable to find library with ID ${id}`);
3731
3548
  }
3732
3549
  return config;
3733
3550
  }
3551
+ function byUniqueTypeOrThrow(projectDefinition, type) {
3552
+ const config = projectDefinition.libraries.filter((lib) => lib.type === type);
3553
+ if (config.length === 0) {
3554
+ throw new Error(`Unable to find library with type ${type}`);
3555
+ }
3556
+ if (config.length > 1) {
3557
+ throw new Error(`Multiple libraries with type ${type} found and only one is expected (${config.map((lib) => lib.name).join(', ')})`);
3558
+ }
3559
+ return config[0];
3560
+ }
3734
3561
  /**
3735
- * Given a package config, get the relative directory of the package
3562
+ * Given a library config, get the relative directory of the library
3736
3563
  *
3737
- * @param packageConfig The package config
3738
- * @param monorepoSettings Optional monorepo settings to determine packages folder location
3739
- * @returns The directory of the package
3564
+ * @param libraryConfig The library config
3565
+ * @param monorepoSettings Optional monorepo settings to determine libraries folder location
3566
+ * @returns The directory of the library
3740
3567
  */
3741
- function getPackageDirectory(packageConfig, monorepoSettings) {
3742
- const packagesFolder = monorepoSettings?.packagesFolder ?? 'packages';
3743
- return `${packagesFolder}/${packageConfig.name}`;
3568
+ function getLibraryDirectory(libraryConfig, monorepoSettings) {
3569
+ const librariesFolder = monorepoSettings?.librariesFolder ?? 'libs';
3570
+ return `${librariesFolder}/${libraryConfig.name}`;
3744
3571
  }
3745
- const PackageUtils = {
3572
+ const LibraryUtils = {
3746
3573
  byId,
3747
- getPackageDirectory,
3574
+ byUniqueTypeOrThrow,
3575
+ getLibraryDirectory,
3748
3576
  };
3749
3577
 
3750
3578
  const {z} = await importShared('zod');
3751
- const COMMON_SPEC_IMPLEMENTATIONS = [
3752
- pluginConfigSpec,
3753
- modelTransformerSpec,
3754
- adminCrudInputSpec,
3755
- adminCrudActionSpec,
3756
- adminCrudColumnSpec,
3757
- ];
3758
3579
  /**
3759
3580
  * Creates a plugin implementation store from the project definition and plugin store,
3760
3581
  * initializing the set of plugins enabled in the project definition.
@@ -3763,8 +3584,8 @@ const COMMON_SPEC_IMPLEMENTATIONS = [
3763
3584
  * @param projectDefinition The project definition to use
3764
3585
  * @returns The plugin implementation store
3765
3586
  */
3766
- function createPluginImplementationStore(pluginStore, projectDefinition) {
3767
- const { availablePlugins, builtinSpecImplementations = [] } = pluginStore;
3587
+ function createPluginSpecStore(pluginStore, projectDefinition) {
3588
+ const { availablePlugins, coreModules } = pluginStore;
3768
3589
  const pluginData = z
3769
3590
  .object({
3770
3591
  plugins: z.array(basePluginDefinitionSchema).optional(),
@@ -3772,35 +3593,18 @@ function createPluginImplementationStore(pluginStore, projectDefinition) {
3772
3593
  .parse(projectDefinition);
3773
3594
  const { plugins = [] } = pluginData;
3774
3595
  // initialize plugins
3775
- const initialImplementations = [
3776
- ...COMMON_SPEC_IMPLEMENTATIONS,
3777
- ...builtinSpecImplementations,
3778
- ];
3779
- const specImplementations = {};
3780
- for (const spec of initialImplementations) {
3781
- if ('type' in spec) {
3782
- if (typeof spec.defaultInitializer !== 'function') {
3783
- throw new TypeError(`Spec ${spec.type} does not have a defaultInitializer function!`);
3784
- }
3785
- specImplementations[spec.name] = spec.defaultInitializer();
3786
- }
3787
- else {
3788
- specImplementations[spec.spec.name] = spec.implementation;
3789
- }
3790
- }
3791
- const pluginsWithModules = plugins.map((p) => {
3596
+ const modulesWithKey = plugins.flatMap((p) => {
3792
3597
  const plugin = availablePlugins.find(({ metadata }) => metadata.name === p.name && metadata.packageName === p.packageName);
3793
- const pluginName = `${p.packageName}/${p.name}`;
3794
3598
  if (!plugin) {
3795
- throw new Error(`Unable to find plugin ${pluginName}!`);
3599
+ throw new Error(`Unable to find plugin ${p.packageName}/${p.name}!`);
3796
3600
  }
3797
- return {
3798
- key: plugin.metadata.key,
3799
- name: pluginName,
3800
- pluginModules: plugin.modules,
3801
- };
3601
+ return plugin.modules.map((m) => ({
3602
+ key: `${plugin.metadata.key}/${m.directory}/${m.module.name}`,
3603
+ pluginKey: plugin.metadata.key,
3604
+ module: m.module,
3605
+ }));
3802
3606
  });
3803
- return initializePlugins(pluginsWithModules, specImplementations);
3607
+ return initializePlugins([...modulesWithKey, ...coreModules]);
3804
3608
  }
3805
3609
  /**
3806
3610
  * Creates a plugin implementation store with the given plugins added to the project definition.
@@ -3826,7 +3630,7 @@ function createPluginImplementationStoreWithNewPlugins(pluginStore, plugins, pro
3826
3630
  })),
3827
3631
  ],
3828
3632
  };
3829
- return createPluginImplementationStore(pluginStore, newProjectDefinition);
3633
+ return createPluginSpecStore(pluginStore, newProjectDefinition);
3830
3634
  }
3831
3635
  /**
3832
3636
  * Creates a project definition schema with the given context.
@@ -3837,9 +3641,9 @@ function createPluginImplementationStoreWithNewPlugins(pluginStore, plugins, pro
3837
3641
  */
3838
3642
  function createProjectDefinitionSchemaWithContext(projectDefinition, context) {
3839
3643
  const { pluginStore } = context;
3840
- const pluginImplementationStore = createPluginImplementationStore(pluginStore, projectDefinition);
3644
+ const pluginSpecStore = createPluginSpecStore(pluginStore, projectDefinition);
3841
3645
  const definitionContext = createDefinitionSchemaParserContext({
3842
- plugins: pluginImplementationStore,
3646
+ plugins: pluginSpecStore,
3843
3647
  });
3844
3648
  return createProjectDefinitionSchema(definitionContext);
3845
3649
  }
@@ -3856,9 +3660,9 @@ function parseProjectDefinitionWithContext(projectDefinition, context) {
3856
3660
  */
3857
3661
  function parseProjectDefinitionWithReferences(projectDefinition, context) {
3858
3662
  const { pluginStore } = context;
3859
- const pluginImplementationStore = createPluginImplementationStore(pluginStore, projectDefinition);
3860
- const definition = parseSchemaWithTransformedReferences(createProjectDefinitionSchema, projectDefinition, { plugins: pluginImplementationStore });
3861
- return { definition, pluginStore: pluginImplementationStore };
3663
+ const pluginSpecStore = createPluginSpecStore(pluginStore, projectDefinition);
3664
+ const definition = parseSchemaWithTransformedReferences(createProjectDefinitionSchema, projectDefinition, { plugins: pluginSpecStore });
3665
+ return { definition, pluginStore: pluginSpecStore };
3862
3666
  }
3863
3667
 
3864
3668
  function byKey(projectDefinition, key) {
@@ -3888,8 +3692,8 @@ function setPluginConfig(projectDefinition, plugin, pluginConfig, definitionCont
3888
3692
  if (isNewPlugin) {
3889
3693
  // When adding a new plugin, we need to create an implementation store
3890
3694
  // that includes this plugin so its migrations are properly registered
3891
- const pluginImplementationStore = createPluginImplementationStoreWithNewPlugins(definitionContainer.parserContext.pluginStore, [plugin], definitionContainer.definition);
3892
- const pluginConfigService = pluginImplementationStore.getPluginSpec(pluginConfigSpec);
3695
+ const pluginSpecStore = createPluginImplementationStoreWithNewPlugins(definitionContainer.parserContext.pluginStore, [plugin], definitionContainer.definition);
3696
+ const pluginConfigService = pluginSpecStore.use(pluginConfigSpec);
3893
3697
  const lastMigrationVersion = pluginConfigService.getLastMigrationVersion(plugin.key);
3894
3698
  projectDefinition.plugins = [
3895
3699
  ...plugins,
@@ -4024,7 +3828,7 @@ class ProjectDefinitionContainer {
4024
3828
  * @returns A new ProjectDefinitionContainer
4025
3829
  */
4026
3830
  static fromSerializedConfig(config, context) {
4027
- const plugins = createPluginImplementationStore(context.pluginStore, config);
3831
+ const plugins = createPluginSpecStore(context.pluginStore, config);
4028
3832
  return new ProjectDefinitionContainer(deserializeSchemaWithTransformedReferences(createProjectDefinitionSchema, config, { plugins }), context, plugins);
4029
3833
  }
4030
3834
  }
@@ -9348,6 +9152,50 @@ const migration021MigrateBullmqToPlugin = createSchemaMigration({
9348
9152
  },
9349
9153
  });
9350
9154
 
9155
+ /**
9156
+ * Migration to rename packages to libraries
9157
+ *
9158
+ * This migration:
9159
+ * 1. Renames the top-level `packages` field to `libraries`
9160
+ * 2. Updates package IDs from `package:*` to `library:*`
9161
+ * 3. Renames `settings.monorepo.packagesFolder` to `settings.monorepo.librariesFolder`
9162
+ * and changes the default from 'packages' to 'libs'
9163
+ */
9164
+ const migration022RenamePackagesToLibraries = createSchemaMigration({
9165
+ version: 22,
9166
+ name: 'renamePackagesToLibraries',
9167
+ description: 'Rename packages to libraries and packagesFolder to librariesFolder',
9168
+ migrate: (config) => {
9169
+ const { packages, settings, ...rest } = config;
9170
+ // Rename packages to libraries and update IDs
9171
+ const libraries = packages?.map((pkg) => ({
9172
+ ...pkg,
9173
+ id: pkg.id.replace(/^package:/, 'library:'),
9174
+ }));
9175
+ // Update monorepo settings if present
9176
+ let newSettings = settings;
9177
+ if (settings?.monorepo) {
9178
+ const { packagesFolder, ...restMonorepo } = settings.monorepo;
9179
+ newSettings = {
9180
+ ...settings,
9181
+ monorepo: {
9182
+ ...restMonorepo,
9183
+ // If packagesFolder was explicitly set to 'packages' (old default) or not set,
9184
+ // use 'libs' (new default). Otherwise preserve the custom value.
9185
+ librariesFolder: packagesFolder === undefined || packagesFolder === 'packages'
9186
+ ? 'libs'
9187
+ : packagesFolder,
9188
+ },
9189
+ };
9190
+ }
9191
+ return {
9192
+ ...rest,
9193
+ libraries,
9194
+ settings: newSettings,
9195
+ };
9196
+ },
9197
+ });
9198
+
9351
9199
  const SCHEMA_MIGRATIONS = [
9352
9200
  migration005PrimaryUniqueRefs,
9353
9201
  migration006IndividualServiceControllers,
@@ -9366,6 +9214,7 @@ const SCHEMA_MIGRATIONS = [
9366
9214
  migration019ColumnTypeBased,
9367
9215
  migration020MoveRedisToInfrastructure,
9368
9216
  migration021MigrateBullmqToPlugin,
9217
+ migration022RenamePackagesToLibraries,
9369
9218
  ];
9370
9219
  function isMigrateableProjectDefinition(projectDefinition) {
9371
9220
  return (typeof projectDefinition === 'object' &&
@@ -9415,7 +9264,7 @@ function createTestProjectDefinition(input = {}) {
9415
9264
  features: [],
9416
9265
  cliVersion: '1.0.0',
9417
9266
  apps: [],
9418
- packages: [],
9267
+ libraries: [],
9419
9268
  models: [],
9420
9269
  isInitialized: true,
9421
9270
  schemaVersion: getLatestMigrationVersion(),
@@ -9431,9 +9280,12 @@ function createTestProjectDefinitionInput(input = {}) {
9431
9280
  function createTestProjectDefinitionContainer(input = {}) {
9432
9281
  const pluginStore = {
9433
9282
  availablePlugins: [],
9283
+ coreModules: [],
9434
9284
  };
9435
- const pluginImplementationStore = createPluginImplementationStore(pluginStore, { plugins: [] });
9436
- const resolvedRefPayload = deserializeSchemaWithTransformedReferences(createProjectDefinitionSchema, createTestProjectDefinitionInput(input), { plugins: pluginImplementationStore });
9285
+ const pluginSpecStore = createPluginSpecStore(pluginStore, {
9286
+ plugins: [],
9287
+ });
9288
+ const resolvedRefPayload = deserializeSchemaWithTransformedReferences(createProjectDefinitionSchema, createTestProjectDefinitionInput(input), { plugins: pluginSpecStore });
9437
9289
  return new ProjectDefinitionContainer(resolvedRefPayload, {
9438
9290
  pluginStore,
9439
9291
  cliVersion: '0.1.0',
@@ -9443,11 +9295,96 @@ function createTestProjectDefinitionContainer(input = {}) {
9443
9295
  directory: '/test-project',
9444
9296
  isInternalExample: false,
9445
9297
  },
9446
- }, pluginImplementationStore);
9298
+ }, pluginSpecStore);
9447
9299
  }
9448
9300
 
9449
9301
  const AVAILABLE_FLAGS = ['TEMPLATE_EXTRACTOR'];
9450
9302
 
9303
+ /**
9304
+ * Abstract base class for package type compilers
9305
+ *
9306
+ * Each package type (backend, web, library, etc.) extends this class
9307
+ * to define how it should be compiled into a PackageEntry with generator bundles.
9308
+ *
9309
+ * Each child class defines its own constructor requirements based on what
9310
+ * information it needs (e.g., app config, definition container).
9311
+ */
9312
+ class PackageCompiler {
9313
+ definitionContainer;
9314
+ constructor(definitionContainer) {
9315
+ this.definitionContainer = definitionContainer;
9316
+ }
9317
+ /**
9318
+ * Get the tasks for a package used in turbo configuration
9319
+ *
9320
+ * @returns Object with build, dev, and watch tasks
9321
+ */
9322
+ getTasks() {
9323
+ return {
9324
+ build: [],
9325
+ dev: [],
9326
+ watch: [],
9327
+ };
9328
+ }
9329
+ }
9330
+ // ============================================================================
9331
+ // Package Directory Helpers
9332
+ // ============================================================================
9333
+ const DEFAULT_APPS_FOLDER = 'apps';
9334
+ const DEFAULT_LIBRARIES_FOLDER = 'libs';
9335
+ /**
9336
+ * Build a scoped package name using the package scope or project name as scope
9337
+ *
9338
+ * @example
9339
+ * ```typescript
9340
+ * buildPackageName({ name: 'blog', packageScope: 'acme' }, 'utils')
9341
+ * // Returns: '@acme/utils'
9342
+ *
9343
+ * buildPackageName({ name: 'blog', packageScope: '' }, 'utils')
9344
+ * // Returns: '@blog/utils'
9345
+ * ```
9346
+ */
9347
+ function buildPackageName(generalSettings, packageName) {
9348
+ const scope = generalSettings.packageScope || generalSettings.name;
9349
+ return `@${scope}/${packageName}`;
9350
+ }
9351
+ /**
9352
+ * Get the package directory for an app or library package based off
9353
+ * the monorepo settings and package name
9354
+ */
9355
+ function getPackageDirectory(monorepoSettings, packageName, packageType) {
9356
+ const folder = packageType === 'app'
9357
+ ? (monorepoSettings?.appsFolder ?? DEFAULT_APPS_FOLDER)
9358
+ : (monorepoSettings?.librariesFolder ?? DEFAULT_LIBRARIES_FOLDER);
9359
+ return `${folder}/${packageName}`;
9360
+ }
9361
+ // ============================================================================
9362
+ // Library Compiler Base Class
9363
+ // ============================================================================
9364
+ /**
9365
+ * Abstract base class for library package compilers
9366
+ *
9367
+ * Library packages differ from app packages in that they:
9368
+ * - Don't use the plugin system (no AppEntryBuilder)
9369
+ * - Use the librariesFolder instead of appsFolder
9370
+ * - Have simpler compilation without app-specific features
9371
+ */
9372
+ class LibraryCompiler extends PackageCompiler {
9373
+ packageConfig;
9374
+ constructor(definitionContainer, packageConfig) {
9375
+ super(definitionContainer);
9376
+ this.packageConfig = packageConfig;
9377
+ }
9378
+ getPackageName() {
9379
+ const generalSettings = this.definitionContainer.definition.settings.general;
9380
+ return buildPackageName(generalSettings, this.packageConfig.name);
9381
+ }
9382
+ getPackageDirectory() {
9383
+ const monorepoSettings = this.definitionContainer.definition.settings.monorepo;
9384
+ return getPackageDirectory(monorepoSettings, this.packageConfig.name, 'library');
9385
+ }
9386
+ }
9387
+
9451
9388
  /**
9452
9389
  * Convert a color name to a hex color. Can be one of the following:
9453
9390
  * - A fixed color name (e.g. 'white', 'black').
@@ -10503,5 +10440,5 @@ function generateDefaultTheme() {
10503
10440
  };
10504
10441
  }
10505
10442
 
10506
- export { AVAILABLE_FLAGS, AppUtils, BUILT_IN_ADMIN_CRUD_ACTIONS, BUILT_IN_ADMIN_CRUD_COLUMNS, BUILT_IN_ADMIN_CRUD_INPUTS, BUILT_IN_TRANSFORMERS, COLOR_PALETTES, EnumUtils, FIXED_COLOR_MAPPINGS, ModelFieldUtils, ModelTransformerUtils, ModelUtils, PALETTE_SHADES, PackageUtils, PluginImplementationStore, PluginUtils, ProjectDefinitionContainer, REFERENTIAL_ACTIONS, 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, authConfigSpec, authModelConfigSpec, authRoleEntityType, backendAppEntryType, baseAdminCrudActionSchema, baseAdminCrudColumnSchema, baseAdminCrudInputSchema, baseAppSchema, baseAppValidators, basePackageSchema, basePackageValidators, basePluginDefinitionSchema, baseTransformerFields, baseTransformerSchema, convertColorNameToOklch, convertHexToOklch, convertOklchToColorName, convertOklchToHex, createAdminAppSchema, createAdminCrudActionCompilerImplementation, createAdminCrudActionImplementation, createAdminCrudActionSchema, createAdminCrudActionType, createAdminCrudColumnCompiler, createAdminCrudColumnCompilerImplementation, createAdminCrudColumnImplementation, createAdminCrudColumnSchema, createAdminCrudColumnType, createAdminCrudDeleteActionSchema, createAdminCrudEditActionSchema, createAdminCrudEmbeddedFormSchema, createAdminCrudEmbeddedInputSchema, createAdminCrudEmbeddedLocalInputSchema, createAdminCrudEnumInputSchema, createAdminCrudForeignColumnSchema, createAdminCrudForeignInputSchema, createAdminCrudInputCompilerImplementation, createAdminCrudInputImplementation, createAdminCrudInputSchema, createAdminCrudInputType, createAdminCrudPasswordInputSchema, createAdminCrudSectionSchema, createAdminCrudTextColumnSchema, createAdminCrudTextInputSchema, createAppCompiler, createAppCompilerPlugin, createAppEntryType, createAppSchema, createBackendAppSchema, createBaseAdminSectionValidators, createDefinitionEntityNameResolver, createDefinitionSchemaParserContext, createEmbeddedRelationTransformerSchema, createEntityType, createEnumBaseSchema, createEnumSchema, createEnumValueSchema, createFeaturesSchema, createModelBaseSchema, createModelGraphqlSchema, createModelRelationFieldSchema, createModelScalarFieldSchema, createModelSchema, createModelServiceSchema, createModelTransformerCompilerImplementation, createModelTransformerImplementation, createModelTransformerType, createModelUniqueConstraintSchema, createNodeLibraryPackageSchema, createPackageEntryType, createPackageSchema, createPlatformPluginExport, createPluginConfigImplementation, createPluginImplementationStore, createPluginImplementationStoreWithNewPlugins, createPluginSpec, createPluginWithConfigSchema, createPluginsSchema, createProjectDefinitionSchema, createProjectDefinitionSchemaWithContext, createSettingsSchema, createTemplateExtractorSchema, createTestProjectDefinition, createTestProjectDefinitionContainer, createTestProjectDefinitionInput, createThemeSchema, createTransformerSchema, createWebAdminSectionSchema, createWebAppSchema, createWebConfigImplementation, definitionSchema, definitionSchemaWithSlots, deserializeSchemaWithTransformedReferences, extractDefinitionRefs, featureEntityType, fixRefDeletions, generalSettingsSchema, generateCssFromThemeConfig, generateDefaultTheme, generateThemeColorsFromShade, getBackendRelativePath, getDefaultThemeColorFromShade, getLatestMigrationVersion, getManagedPluginsForPlugin, getPluginMetadataByKey, getPluginMetadataByKeyOrThrow, infrastructureSettingsSchema, initializePlugins, isMigrateableProjectDefinition, modelEntityType, modelEnumEntityType, modelEnumValueEntityType, modelForeignRelationEntityType, modelLocalRelationEntityType, modelScalarFieldEntityType, modelTransformerCompilerSpec, modelTransformerEntityType, modelTransformerSpec, modelUniqueConstraintEntityType, monorepoSettingsSchema, nodeLibraryPackageEntryType, oklchColor, packageEntityType, paletteSchema, palettesSchema, parseOklch, parseProjectDefinitionWithContext, parseProjectDefinitionWithReferences, pluginConfigSpec, pluginEntityType, pluginMetadataSchema, pluginSpecDependencySchema, pluginSpecSupportSchema, runPluginMigrations, runSchemaMigrations, serializeSchema, serializeSchemaFromRefPayload, stripEmptyGeneratorChildren, stripUndefinedValues, themeColorSchema, undefinedIfEmpty, undefinedIfFalsy, webAppEntryType, webConfigSpec };
10507
- //# sourceMappingURL=project-builder-lib-CcNtL_U6.js.map
10443
+ export { AVAILABLE_FLAGS, AppUtils, 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, EnumUtils, FIXED_COLOR_MAPPINGS, LibraryCompiler, LibraryUtils, ModelFieldUtils, ModelTransformerUtils, ModelUtils, PALETTE_SHADES, PackageCompiler, PluginSpecStore, PluginUtils, ProjectDefinitionContainer, REFERENTIAL_ACTIONS, 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, authConfigSpec, authModelsSpec, authRoleEntityType, backendAppEntryType, baseAdminCrudActionSchema, baseAdminCrudColumnSchema, baseAdminCrudInputSchema, baseAppSchema, baseAppValidators, baseLibrarySchema, baseLibraryValidators, basePluginDefinitionSchema, baseTransformerFields, baseTransformerSchema, buildPackageName, 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, createBackendAppSchema, createBaseAdminSectionValidators, createDefinitionEntityNameResolver, createDefinitionSchemaParserContext, createEmbeddedRelationTransformerSchema, createEntityType, createEnumBaseSchema, createEnumSchema, createEnumValueSchema, createFeaturesSchema, createFieldMapSpec, createLibraryWebConfig, createModelBaseSchema, createModelGraphqlSchema, createModelRelationFieldSchema, createModelScalarFieldSchema, createModelSchema, createModelServiceSchema, createModelTransformerType, createModelUniqueConstraintSchema, createPluginImplementationStoreWithNewPlugins, createPluginModule, createPluginSpecStore, createPluginWithConfigSchema, createPluginsSchema, createProjectDefinitionSchema, createProjectDefinitionSchemaWithContext, createSettingsSchema, createTemplateExtractorSchema, createTestProjectDefinition, createTestProjectDefinitionContainer, createTestProjectDefinitionInput, createThemeSchema, createTransformerSchema, createWebAdminSectionSchema, createWebAppSchema, definitionSchema, definitionSchemaWithSlots, deserializeSchemaWithTransformedReferences, extractDefinitionRefs, featureEntityType, fixRefDeletions, generalSettingsSchema, generateCssFromThemeConfig, generateDefaultTheme, generateThemeColorsFromShade, getBackendRelativePath, getDefaultThemeColorFromShade, getLatestMigrationVersion, getManagedPluginsForPlugin, getPackageDirectory, getPluginMetadataByKey, getPluginMetadataByKeyOrThrow, infrastructureSettingsSchema, initializePlugins, isMigrateableProjectDefinition, libraryEntityType, libraryTypeSpec, modelEntityType, modelEnumEntityType, modelEnumValueEntityType, modelForeignRelationEntityType, modelLocalRelationEntityType, modelScalarFieldEntityType, modelTransformerCompilerSpec, modelTransformerEntityType, modelTransformerSpec, modelUniqueConstraintEntityType, monorepoSettingsSchema, nodeLibraryDefinitionSchemaEntry, oklchColor, paletteSchema, palettesSchema, parseOklch, parseProjectDefinitionWithContext, parseProjectDefinitionWithReferences, pluginAppCompiler, pluginConfigSpec, pluginEntityType, pluginMetadataSchema, pluginSpecDependencySchema, pluginSpecSupportSchema, runInPluginContext, runPluginMigrations, runSchemaMigrations, serializeSchema, serializeSchemaFromRefPayload, stripEmptyGeneratorChildren, stripUndefinedValues, themeColorSchema, undefinedIfEmpty, undefinedIfFalsy, webAppEntryType, webConfigSpec };
10444
+ //# sourceMappingURL=project-builder-lib-CmgMfkI5.js.map