@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.
- package/dist/auth/core/common.d.ts +2 -5
- package/dist/auth/core/common.d.ts.map +1 -1
- package/dist/auth/core/common.js +14 -14
- package/dist/auth/core/common.js.map +1 -1
- package/dist/auth/core/node.d.ts +3 -3
- package/dist/auth/core/node.d.ts.map +1 -1
- package/dist/auth/core/node.js +5 -8
- package/dist/auth/core/node.js.map +1 -1
- package/dist/auth/core/web.d.ts +3 -3
- package/dist/auth/core/web.d.ts.map +1 -1
- package/dist/auth/core/web.js +4 -5
- package/dist/auth/core/web.js.map +1 -1
- package/dist/auth0/core/common.d.ts +3 -5
- package/dist/auth0/core/common.d.ts.map +1 -1
- package/dist/auth0/core/common.js +11 -14
- package/dist/auth0/core/common.js.map +1 -1
- package/dist/auth0/core/node.d.ts +3 -3
- package/dist/auth0/core/node.d.ts.map +1 -1
- package/dist/auth0/core/node.js +5 -8
- package/dist/auth0/core/node.js.map +1 -1
- package/dist/auth0/core/web.d.ts +3 -3
- package/dist/auth0/core/web.d.ts.map +1 -1
- package/dist/auth0/core/web.js +4 -5
- package/dist/auth0/core/web.js.map +1 -1
- package/dist/local-auth/admin/common.d.ts +3 -2
- package/dist/local-auth/admin/common.d.ts.map +1 -1
- package/dist/local-auth/admin/common.js +6 -7
- package/dist/local-auth/admin/common.js.map +1 -1
- package/dist/local-auth/admin/node.d.ts +3 -6
- package/dist/local-auth/admin/node.d.ts.map +1 -1
- package/dist/local-auth/admin/node.js +13 -12
- package/dist/local-auth/admin/node.js.map +1 -1
- package/dist/local-auth/admin/web.d.ts +3 -4
- package/dist/local-auth/admin/web.d.ts.map +1 -1
- package/dist/local-auth/admin/web.js +22 -21
- package/dist/local-auth/admin/web.js.map +1 -1
- package/dist/local-auth/core/common.d.ts +3 -5
- package/dist/local-auth/core/common.d.ts.map +1 -1
- package/dist/local-auth/core/common.js +10 -13
- package/dist/local-auth/core/common.js.map +1 -1
- package/dist/local-auth/core/node.d.ts +3 -3
- package/dist/local-auth/core/node.d.ts.map +1 -1
- package/dist/local-auth/core/node.js +5 -8
- package/dist/local-auth/core/node.js.map +1 -1
- package/dist/local-auth/core/web.d.ts +3 -3
- package/dist/local-auth/core/web.d.ts.map +1 -1
- package/dist/local-auth/core/web.js +4 -5
- package/dist/local-auth/core/web.js.map +1 -1
- package/dist/placeholder-auth/core/common.d.ts +2 -5
- package/dist/placeholder-auth/core/common.d.ts.map +1 -1
- package/dist/placeholder-auth/core/common.js +10 -13
- package/dist/placeholder-auth/core/common.js.map +1 -1
- package/dist/placeholder-auth/core/node.d.ts +3 -3
- package/dist/placeholder-auth/core/node.d.ts.map +1 -1
- package/dist/placeholder-auth/core/node.js +5 -8
- package/dist/placeholder-auth/core/node.js.map +1 -1
- package/dist/placeholder-auth/core/web.d.ts +3 -3
- package/dist/placeholder-auth/core/web.d.ts.map +1 -1
- package/dist/placeholder-auth/core/web.js +4 -5
- package/dist/placeholder-auth/core/web.js.map +1 -1
- package/dist/web/assets/__federation_expose_auth0CoreCommon-DLSGXjCI.js +40 -0
- package/dist/web/assets/__federation_expose_auth0CoreCommon-DLSGXjCI.js.map +1 -0
- package/dist/web/assets/{__federation_expose_auth0CoreWeb-CZueDXPK.js → __federation_expose_auth0CoreWeb-C7FfhlmF.js} +9 -10
- package/dist/web/assets/{__federation_expose_auth0CoreWeb-CZueDXPK.js.map → __federation_expose_auth0CoreWeb-C7FfhlmF.js.map} +1 -1
- package/dist/web/assets/__federation_expose_authCoreCommon-BF58isGa.js +29 -0
- package/dist/web/assets/__federation_expose_authCoreCommon-BF58isGa.js.map +1 -0
- package/dist/web/assets/{__federation_expose_authCoreWeb-C8rgnA2v.js → __federation_expose_authCoreWeb-DMq9M88g.js} +10 -11
- package/dist/web/assets/{__federation_expose_authCoreWeb-C8rgnA2v.js.map → __federation_expose_authCoreWeb-DMq9M88g.js.map} +1 -1
- package/dist/web/assets/{__federation_expose_local-authAdminCommon-C75-DAzO.js → __federation_expose_local-authAdminCommon-sQw4q5YX.js} +8 -9
- package/dist/web/assets/__federation_expose_local-authAdminCommon-sQw4q5YX.js.map +1 -0
- package/dist/web/assets/__federation_expose_local-authAdminWeb-9FbO89NR.js +41 -0
- package/dist/web/assets/__federation_expose_local-authAdminWeb-9FbO89NR.js.map +1 -0
- package/dist/web/assets/__federation_expose_local-authCoreCommon-CpUK09_4.js +21 -0
- package/dist/web/assets/__federation_expose_local-authCoreCommon-CpUK09_4.js.map +1 -0
- package/dist/web/assets/{__federation_expose_local-authCoreWeb-ChyvdsRq.js → __federation_expose_local-authCoreWeb-Czp0GaY1.js} +9 -10
- package/dist/web/assets/{__federation_expose_local-authCoreWeb-ChyvdsRq.js.map → __federation_expose_local-authCoreWeb-Czp0GaY1.js.map} +1 -1
- package/dist/web/assets/__federation_expose_placeholder-authCoreCommon-CFDDdOMo.js +23 -0
- package/dist/web/assets/__federation_expose_placeholder-authCoreCommon-CFDDdOMo.js.map +1 -0
- package/dist/web/assets/{__federation_expose_placeholder-authCoreWeb-CT8JKYLB.js → __federation_expose_placeholder-authCoreWeb-Bcn1_oDP.js} +9 -13
- package/dist/web/assets/{__federation_expose_placeholder-authCoreWeb-CT8JKYLB.js.map → __federation_expose_placeholder-authCoreWeb-Bcn1_oDP.js.map} +1 -1
- package/dist/web/assets/{__federation_fn_import-C_QCk5FX.js → __federation_fn_import-DsXcpNlB.js} +2 -2
- package/dist/web/assets/{__federation_fn_import-C_QCk5FX.js.map → __federation_fn_import-DsXcpNlB.js.map} +1 -1
- package/dist/web/assets/__federation_shared_@baseplate-dev/project-builder-lib/{web-DtztAtUw.js → web-zqe3PPcn.js} +37 -118
- package/dist/web/assets/__federation_shared_@baseplate-dev/project-builder-lib/web-zqe3PPcn.js.map +1 -0
- package/dist/web/assets/__federation_shared_@baseplate-dev/{project-builder-lib-CcNtL_U6.js → project-builder-lib-CmgMfkI5.js} +2152 -2215
- package/dist/web/assets/__federation_shared_@baseplate-dev/project-builder-lib-CmgMfkI5.js.map +1 -0
- package/dist/web/assets/__federation_shared_@baseplate-dev/{ui-components-DA_4I2Vy.js → ui-components-D1Dayhn9.js} +5 -5
- package/dist/web/assets/__federation_shared_@baseplate-dev/{ui-components-DA_4I2Vy.js.map → ui-components-D1Dayhn9.js.map} +1 -1
- package/dist/web/assets/__federation_shared_@baseplate-dev/{utils-Bxy-1ETU.js → utils-BO5VHrCf.js} +27 -6
- package/dist/web/assets/__federation_shared_@baseplate-dev/utils-BO5VHrCf.js.map +1 -0
- package/dist/web/assets/__federation_shared_@tanstack/{react-router-DooFj-IS.js → react-router-CNzDweD5.js} +2 -2
- package/dist/web/assets/__federation_shared_@tanstack/{react-router-DooFj-IS.js.map → react-router-CNzDweD5.js.map} +1 -1
- package/dist/web/assets/{get-auth-plugin-definition-D2XMaoy7.js → get-auth-plugin-definition-BV2O8wTa.js} +2 -2
- package/dist/web/assets/{get-auth-plugin-definition-D2XMaoy7.js.map → get-auth-plugin-definition-BV2O8wTa.js.map} +1 -1
- package/dist/web/assets/{index-DwJT6_Wn.js → index-BL7fotl7.js} +2 -2
- package/dist/web/assets/{index-DwJT6_Wn.js.map → index-BL7fotl7.js.map} +1 -1
- package/dist/web/assets/{index.esm-ChwWPPiL.js → index.esm-B4RpOlq_.js} +2 -2
- package/dist/web/assets/{index.esm-ChwWPPiL.js.map → index.esm-B4RpOlq_.js.map} +1 -1
- package/dist/web/assets/{isEqual-DAXqKRba.js → isEqual-BQtm2LNT.js} +5 -5
- package/dist/web/assets/{isEqual-DAXqKRba.js.map → isEqual-BQtm2LNT.js.map} +1 -1
- package/dist/web/assets/{model-merger-gGkFnyaY.js → model-merger-BwRNqcBu.js} +189 -81
- package/dist/web/assets/model-merger-BwRNqcBu.js.map +1 -0
- package/dist/web/assets/{plugin-definition-hAzbWO7b.js → plugin-definition-B9d2CoQL.js} +2 -2
- package/dist/web/assets/{plugin-definition-hAzbWO7b.js.map → plugin-definition-B9d2CoQL.js.map} +1 -1
- package/dist/web/assets/{plugin-definition-_slrOM0G.js → plugin-definition-BMTsmwyH.js} +2 -2
- package/dist/web/assets/{plugin-definition-_slrOM0G.js.map → plugin-definition-BMTsmwyH.js.map} +1 -1
- package/dist/web/assets/{plugin-definition-rpMj4pr8.js → plugin-definition-CHD5r-h7.js} +2 -2
- package/dist/web/assets/{plugin-definition-rpMj4pr8.js.map → plugin-definition-CHD5r-h7.js.map} +1 -1
- package/dist/web/assets/{plugin-definition-QRBMcFiG.js → plugin-definition-DA9rJBcS.js} +2 -2
- package/dist/web/assets/{plugin-definition-QRBMcFiG.js.map → plugin-definition-DA9rJBcS.js.map} +1 -1
- package/dist/web/assets/{react-DbX1FP85.js → react-B9vhIZMy.js} +2 -2
- package/dist/web/assets/{react-DbX1FP85.js.map → react-B9vhIZMy.js.map} +1 -1
- package/dist/web/assets/remoteEntry.js +10 -10
- package/dist/web/assets/{styles-DqLt1Blm.js → styles-CEm5K1iU.js} +3 -3
- package/dist/web/assets/{styles-DqLt1Blm.js.map → styles-CEm5K1iU.js.map} +1 -1
- package/package.json +13 -12
- package/dist/web/assets/__federation_expose_auth0CoreCommon-Ga9LD3d6.js +0 -43
- package/dist/web/assets/__federation_expose_auth0CoreCommon-Ga9LD3d6.js.map +0 -1
- package/dist/web/assets/__federation_expose_authCoreCommon-BrTLsuJC.js +0 -29
- package/dist/web/assets/__federation_expose_authCoreCommon-BrTLsuJC.js.map +0 -1
- package/dist/web/assets/__federation_expose_local-authAdminCommon-C75-DAzO.js.map +0 -1
- package/dist/web/assets/__federation_expose_local-authAdminWeb-D2xGvwyL.js +0 -40
- package/dist/web/assets/__federation_expose_local-authAdminWeb-D2xGvwyL.js.map +0 -1
- package/dist/web/assets/__federation_expose_local-authCoreCommon-BFUbyPYg.js +0 -27
- package/dist/web/assets/__federation_expose_local-authCoreCommon-BFUbyPYg.js.map +0 -1
- package/dist/web/assets/__federation_expose_placeholder-authCoreCommon-DrFV9FSW.js +0 -26
- package/dist/web/assets/__federation_expose_placeholder-authCoreCommon-DrFV9FSW.js.map +0 -1
- package/dist/web/assets/__federation_shared_@baseplate-dev/project-builder-lib/web-DtztAtUw.js.map +0 -1
- package/dist/web/assets/__federation_shared_@baseplate-dev/project-builder-lib-CcNtL_U6.js.map +0 -1
- package/dist/web/assets/__federation_shared_@baseplate-dev/utils-Bxy-1ETU.js.map +0 -1
- package/dist/web/assets/model-merger-gGkFnyaY.js.map +0 -1
|
@@ -1,1208 +1,74 @@
|
|
|
1
|
-
import { c as
|
|
2
|
-
export {
|
|
3
|
-
import { importShared } from '../__federation_fn_import-
|
|
4
|
-
import { i as isEqual } from '../isEqual-
|
|
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
|
-
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
16
|
+
* Spec for registering admin CRUD column compilers
|
|
66
17
|
*/
|
|
67
|
-
const adminCrudColumnCompilerSpec =
|
|
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
|
|
24
|
+
* Spec for registering admin CRUD input compilers
|
|
94
25
|
*/
|
|
95
|
-
const adminCrudInputCompilerSpec =
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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
|
-
*
|
|
66
|
+
* Spec for registering model transformer compilers
|
|
329
67
|
*/
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
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
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
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
|
-
*
|
|
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
|
|
1771
|
-
const
|
|
1772
|
-
const
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
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
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
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
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
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
|
-
|
|
1261
|
+
throw new Error(`Exceeded max iterations fixing deletions`);
|
|
1794
1262
|
}
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
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
|
-
|
|
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
|
|
1815
|
-
|
|
1816
|
-
return
|
|
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
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
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
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
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
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
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
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
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
|
-
|
|
1371
|
+
const obj = Object.create(proto);
|
|
1372
|
+
return Object.assign(obj, base);
|
|
1373
|
+
}
|
|
1919
1374
|
}
|
|
1920
|
-
function
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
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
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
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
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
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
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
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
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
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
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
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
|
-
|
|
2131
|
-
|
|
2132
|
-
references,
|
|
2133
|
-
data,
|
|
2134
|
-
};
|
|
1515
|
+
}
|
|
1516
|
+
return state.copy_;
|
|
2135
1517
|
}
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
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
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
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
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
//
|
|
2176
|
-
|
|
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
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
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
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
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
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
1593
|
+
if (value === peek(state.base_, prop)) {
|
|
1594
|
+
prepareCopy(state);
|
|
1595
|
+
return state.copy_[prop] = createProxy(value, state);
|
|
2201
1596
|
}
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
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
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
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
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
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
|
-
|
|
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$
|
|
1925
|
+
const {z: z$t} = await importShared('zod');
|
|
2385
1926
|
|
|
2386
1927
|
const VALIDATORS = {
|
|
2387
|
-
PASCAL_CASE_STRING: z$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
1940
|
+
.or(z$t.literal(''))
|
|
2400
1941
|
.optional(),
|
|
2401
1942
|
};
|
|
2402
1943
|
|
|
2403
|
-
const {z: z$
|
|
2404
|
-
const createRoleArray = definitionSchema((ctx) => ctx.withDefault(z$
|
|
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$
|
|
2411
|
-
objectType: ctx.withDefault(z$
|
|
2412
|
-
enabled: ctx.withDefault(z$
|
|
2413
|
-
fields: ctx.withDefault(z$
|
|
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$
|
|
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$
|
|
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$
|
|
2430
|
-
get: ctx.withDefault(z$
|
|
2431
|
-
enabled: ctx.withDefault(z$
|
|
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$
|
|
2435
|
-
enabled: ctx.withDefault(z$
|
|
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$
|
|
2440
|
-
create: ctx.withDefault(z$
|
|
2441
|
-
enabled: ctx.withDefault(z$
|
|
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$
|
|
2445
|
-
enabled: ctx.withDefault(z$
|
|
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$
|
|
2449
|
-
enabled: ctx.withDefault(z$
|
|
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$
|
|
1996
|
+
const {z: z$r} = await importShared('zod');
|
|
2456
1997
|
|
|
2457
1998
|
const baseTransformerFields = {
|
|
2458
|
-
id: z$
|
|
2459
|
-
type: z$
|
|
1999
|
+
id: z$r.string(),
|
|
2000
|
+
type: z$r.string().min(1),
|
|
2460
2001
|
};
|
|
2461
|
-
const baseTransformerSchema = z$
|
|
2002
|
+
const baseTransformerSchema = z$r.looseObject(baseTransformerFields);
|
|
2462
2003
|
function createModelTransformerType(payload) {
|
|
2463
2004
|
return payload;
|
|
2464
2005
|
}
|
|
2465
2006
|
|
|
2466
|
-
const {z: z$
|
|
2467
|
-
const createEmbeddedRelationTransformerSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => ctx.refContext({ embeddedModelSlot: modelEntityType }, ({ embeddedModelSlot }) => ctx.withEnt(z$
|
|
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$
|
|
2475
|
-
embeddedFieldNames: z$
|
|
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$
|
|
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
|
|
2050
|
+
* Spec for registering additional model transformer types
|
|
2535
2051
|
*/
|
|
2536
|
-
const modelTransformerSpec =
|
|
2537
|
-
|
|
2538
|
-
});
|
|
2052
|
+
const modelTransformerSpec = createFieldMapSpec('core/model-transformer', (t) => ({
|
|
2053
|
+
transformers: t.namedArrayToMap(BUILT_IN_TRANSFORMERS),
|
|
2054
|
+
}));
|
|
2539
2055
|
|
|
2540
|
-
const z$
|
|
2056
|
+
const z$p = await importShared('zod');
|
|
2541
2057
|
const createTransformerSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, slots) => {
|
|
2542
|
-
const transformers = ctx.plugins
|
|
2543
|
-
|
|
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$
|
|
2549
|
-
const createEnumValueSchema = definitionSchemaWithSlots({ enumSlot: modelEnumEntityType }, (ctx, { enumSlot }) => ctx.withEnt(z$
|
|
2550
|
-
id: z$
|
|
2551
|
-
name: z$
|
|
2552
|
-
friendlyName: z$
|
|
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$
|
|
2558
|
-
id: z$
|
|
2559
|
-
name: z$
|
|
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$
|
|
2565
|
-
isExposed: z$
|
|
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$
|
|
2086
|
+
const {z: z$n} = await importShared('zod');
|
|
2573
2087
|
const createModelScalarFieldSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => ctx
|
|
2574
|
-
.withEnt(z$
|
|
2575
|
-
id: z$
|
|
2088
|
+
.withEnt(z$n.object({
|
|
2089
|
+
id: z$n.string(),
|
|
2576
2090
|
name: VALIDATORS.CAMEL_CASE_STRING,
|
|
2577
|
-
type: z$
|
|
2578
|
-
isOptional: z$
|
|
2579
|
-
options: ctx.refContext({ enumSlot: modelEnumEntityType }, ({ enumSlot }) => z$
|
|
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$
|
|
2096
|
+
default: z$n.string().default(''),
|
|
2583
2097
|
// uuid options
|
|
2584
|
-
genUuid: z$
|
|
2098
|
+
genUuid: z$n.boolean().optional(),
|
|
2585
2099
|
// date options
|
|
2586
|
-
updatedAt: z$
|
|
2587
|
-
defaultToNow: z$
|
|
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$
|
|
2648
|
-
id: z$
|
|
2649
|
-
foreignId: z$
|
|
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$
|
|
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$
|
|
2672
|
-
onUpdate: z$
|
|
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$
|
|
2683
|
-
id: z$
|
|
2684
|
-
fields: z$
|
|
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$
|
|
2702
|
-
create: z$
|
|
2215
|
+
const createModelServiceSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, { modelSlot }) => z$n.object({
|
|
2216
|
+
create: z$n
|
|
2703
2217
|
.object({
|
|
2704
|
-
enabled: z$
|
|
2705
|
-
fields: z$
|
|
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$
|
|
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$
|
|
2235
|
+
update: z$n
|
|
2722
2236
|
.object({
|
|
2723
|
-
enabled: z$
|
|
2724
|
-
fields: z$
|
|
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$
|
|
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$
|
|
2254
|
+
delete: z$n
|
|
2741
2255
|
.object({
|
|
2742
|
-
enabled: z$
|
|
2256
|
+
enabled: z$n.boolean().default(false),
|
|
2743
2257
|
})
|
|
2744
2258
|
.default({
|
|
2745
2259
|
enabled: false,
|
|
2746
2260
|
}),
|
|
2747
|
-
transformers: z$
|
|
2261
|
+
transformers: z$n
|
|
2748
2262
|
.array(createTransformerSchema(ctx, { modelSlot }))
|
|
2749
2263
|
.default([]),
|
|
2750
2264
|
}));
|
|
2751
|
-
const createModelBaseSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType }, (ctx, slots) => z$
|
|
2752
|
-
id: z$
|
|
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$
|
|
2759
|
-
fields: z$
|
|
2760
|
-
relations: z$
|
|
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$
|
|
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$
|
|
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$
|
|
2795
|
-
const createBaseAdminSectionValidators = definitionSchema((ctx) => z$
|
|
2796
|
-
id: z$
|
|
2797
|
-
name: z$
|
|
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$
|
|
2803
|
-
type: z$
|
|
2316
|
+
icon: z$m.string().optional(),
|
|
2317
|
+
type: z$m.string().min(1),
|
|
2804
2318
|
}));
|
|
2805
2319
|
|
|
2806
|
-
const {z: z$
|
|
2807
|
-
const baseAdminCrudActionSchema = z$
|
|
2808
|
-
id: z$
|
|
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$
|
|
2813
|
-
position: z$
|
|
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$
|
|
2336
|
+
const {z: z$k} = await importShared('zod');
|
|
2823
2337
|
const createAdminCrudEditActionSchema = definitionSchema(() => baseAdminCrudActionSchema.extend({
|
|
2824
|
-
type: z$
|
|
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$
|
|
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
|
|
2357
|
+
* Spec for registering additional admin CRUD table actions
|
|
2865
2358
|
*/
|
|
2866
|
-
const adminCrudActionSpec =
|
|
2867
|
-
|
|
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$
|
|
2883
|
-
const baseAdminCrudColumnSchema = z$
|
|
2884
|
-
id: z$
|
|
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$
|
|
2889
|
-
label: z$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
2921
|
-
valueExpression: z$
|
|
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
|
|
2424
|
+
* Spec for registering additional admin CRUD table columns
|
|
2955
2425
|
*/
|
|
2956
|
-
const adminCrudColumnSpec =
|
|
2957
|
-
|
|
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$
|
|
2973
|
-
const baseAdminCrudInputSchema = z$
|
|
2974
|
-
id: z$
|
|
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$
|
|
2979
|
-
label: z$
|
|
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$
|
|
2459
|
+
const {z: z$g} = await importShared('zod');
|
|
2992
2460
|
const createAdminCrudTextInputSchema = definitionSchemaWithSlots({ modelSlot: modelEntityType, adminSectionSlot: adminSectionEntityType }, (ctx, { modelSlot }) => baseAdminCrudInputSchema.extend({
|
|
2993
|
-
type: z$
|
|
2994
|
-
label: z$
|
|
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$
|
|
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$
|
|
3008
|
-
label: z$
|
|
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$
|
|
3015
|
-
valueExpression: z$
|
|
3016
|
-
defaultLabel: z$
|
|
3017
|
-
nullLabel: z$
|
|
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$
|
|
3025
|
-
label: z$
|
|
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$
|
|
3038
|
-
label: z$
|
|
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$
|
|
3056
|
-
label: z$
|
|
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$
|
|
3074
|
-
label: z$
|
|
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
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
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
|
|
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
|
|
3114
|
-
|
|
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
|
-
|
|
3118
|
-
const
|
|
3119
|
-
|
|
3120
|
-
.
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
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
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
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
|
-
|
|
3204
|
-
.array(createAdminCrudEmbeddedFormSchema(ctx, { adminSectionSlot }))
|
|
3205
|
-
.optional(),
|
|
3206
|
-
}))));
|
|
3021
|
+
});
|
|
3207
3022
|
|
|
3208
|
-
const
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
const
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
})
|
|
3221
|
-
|
|
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
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
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
|
|
3246
|
-
id: z$a.string()
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
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
|
-
.
|
|
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$
|
|
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
|
|
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
|
|
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
|
-
*
|
|
3216
|
+
* Libraries will be placed in {librariesFolder}/{library-name}, e.g. "libs/shared-utils".
|
|
3391
3217
|
*
|
|
3392
|
-
* @default "
|
|
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
|
-
|
|
3222
|
+
librariesFolder: CASE_VALIDATORS.KEBAB_CASE.min(1)
|
|
3397
3223
|
.max(50)
|
|
3398
3224
|
.regex(/^[a-z0-9-]+$/, {
|
|
3399
|
-
message: '
|
|
3225
|
+
message: 'Libraries folder must contain only lowercase letters, numbers, and dashes (no slashes)',
|
|
3400
3226
|
})
|
|
3401
|
-
.default('
|
|
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
|
-
|
|
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
|
|
3716
|
-
const transformers = pluginStore.
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
return
|
|
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 = {
|
|
3542
|
+
const ModelTransformerUtils = { getTransformerName };
|
|
3726
3543
|
|
|
3727
3544
|
function byId(projectDefinition, id) {
|
|
3728
|
-
const config = projectDefinition.
|
|
3545
|
+
const config = projectDefinition.libraries.find((lib) => lib.id === id);
|
|
3729
3546
|
if (!config) {
|
|
3730
|
-
throw new Error(`Unable to find
|
|
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
|
|
3562
|
+
* Given a library config, get the relative directory of the library
|
|
3736
3563
|
*
|
|
3737
|
-
* @param
|
|
3738
|
-
* @param monorepoSettings Optional monorepo settings to determine
|
|
3739
|
-
* @returns The directory of the
|
|
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
|
|
3742
|
-
const
|
|
3743
|
-
return `${
|
|
3568
|
+
function getLibraryDirectory(libraryConfig, monorepoSettings) {
|
|
3569
|
+
const librariesFolder = monorepoSettings?.librariesFolder ?? 'libs';
|
|
3570
|
+
return `${librariesFolder}/${libraryConfig.name}`;
|
|
3744
3571
|
}
|
|
3745
|
-
const
|
|
3572
|
+
const LibraryUtils = {
|
|
3746
3573
|
byId,
|
|
3747
|
-
|
|
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
|
|
3767
|
-
const { availablePlugins,
|
|
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
|
|
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 ${
|
|
3599
|
+
throw new Error(`Unable to find plugin ${p.packageName}/${p.name}!`);
|
|
3796
3600
|
}
|
|
3797
|
-
return {
|
|
3798
|
-
key: plugin.metadata.key
|
|
3799
|
-
|
|
3800
|
-
|
|
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(
|
|
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
|
|
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
|
|
3644
|
+
const pluginSpecStore = createPluginSpecStore(pluginStore, projectDefinition);
|
|
3841
3645
|
const definitionContext = createDefinitionSchemaParserContext({
|
|
3842
|
-
plugins:
|
|
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
|
|
3860
|
-
const definition = parseSchemaWithTransformedReferences(createProjectDefinitionSchema, projectDefinition, { plugins:
|
|
3861
|
-
return { definition, pluginStore:
|
|
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
|
|
3892
|
-
const pluginConfigService =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
9436
|
-
|
|
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
|
-
},
|
|
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,
|
|
10507
|
-
//# sourceMappingURL=project-builder-lib-
|
|
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
|