@seedprotocol/sdk 0.4.3 → 0.4.5
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/README.md +38 -348
- package/dist/{ArweaveClient-CleX_4Gw.js → ArweaveClient-CgWK-JgT.js} +8 -8
- package/dist/{ArweaveClient-CleX_4Gw.js.map → ArweaveClient-CgWK-JgT.js.map} +1 -1
- package/dist/{ArweaveClient-BvJ1FhQ5.js → ArweaveClient-WcG8CZAE.js} +8 -8
- package/dist/{ArweaveClient-BvJ1FhQ5.js.map → ArweaveClient-WcG8CZAE.js.map} +1 -1
- package/dist/{Db-DX08SxS9.js → Db-DjFdIdR9.js} +9 -16
- package/dist/{Db-DX08SxS9.js.map → Db-DjFdIdR9.js.map} +1 -1
- package/dist/{Db-BPnO1-_p.js → Db-DjofXdeU.js} +9 -9
- package/dist/{Db-BPnO1-_p.js.map → Db-DjofXdeU.js.map} +1 -1
- package/dist/{EasClient-BwhUcPjY.js → EasClient-Aojewp6P.js} +8 -8
- package/dist/{EasClient-CJSs38Db.js.map → EasClient-Aojewp6P.js.map} +1 -1
- package/dist/{EasClient-CJSs38Db.js → EasClient-BVFXp2O6.js} +8 -8
- package/dist/{EasClient-BwhUcPjY.js.map → EasClient-BVFXp2O6.js.map} +1 -1
- package/dist/{FileManager-B1tdLMsX.js → FileManager-C9zr4AJe.js} +8 -8
- package/dist/{FileManager-B1tdLMsX.js.map → FileManager-C9zr4AJe.js.map} +1 -1
- package/dist/{FileManager-Ct91ZhOE.js → FileManager-CxGJLw5C.js} +8 -8
- package/dist/{FileManager-Ct91ZhOE.js.map → FileManager-CxGJLw5C.js.map} +1 -1
- package/dist/Item/Item.d.ts +28 -7
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/service/actors/runPublish.d.ts +5 -0
- package/dist/Item/service/actors/runPublish.d.ts.map +1 -0
- package/dist/Item/service/itemMachineSingle.d.ts +10 -5
- package/dist/Item/service/itemMachineSingle.d.ts.map +1 -1
- package/dist/ItemProperty/ItemProperty.d.ts +30 -5
- package/dist/ItemProperty/ItemProperty.d.ts.map +1 -1
- package/dist/ItemProperty/service/actors/loadOrCreateProperty.d.ts.map +1 -1
- package/dist/ItemProperty/service/propertyMachine.d.ts +10 -10
- package/dist/ItemProperty/service/propertyMachine.d.ts.map +1 -1
- package/dist/Model/Model.d.ts +27 -20
- package/dist/Model/Model.d.ts.map +1 -1
- package/dist/Model/index.d.ts +1 -1
- package/dist/Model/service/actors/createModelProperties.d.ts.map +1 -1
- package/dist/Model/service/actors/loadOrCreateModel.d.ts.map +1 -1
- package/dist/Model/service/actors/validateModel.d.ts.map +1 -1
- package/dist/Model/service/modelMachine.d.ts +18 -3
- package/dist/Model/service/modelMachine.d.ts.map +1 -1
- package/dist/ModelProperty/ModelProperty.d.ts +25 -2
- package/dist/ModelProperty/ModelProperty.d.ts.map +1 -1
- package/dist/ModelProperty/service/actors/compareAndMarkDraft.d.ts.map +1 -1
- package/dist/ModelProperty/service/actors/saveToSchema.d.ts.map +1 -1
- package/dist/ModelProperty/service/actors/validateProperty.d.ts.map +1 -1
- package/dist/ModelProperty/service/modelPropertyMachine.d.ts +17 -3
- package/dist/ModelProperty/service/modelPropertyMachine.d.ts.map +1 -1
- package/dist/{ModelProperty-Cr3BmgkC.js → ModelProperty-CGdkocQ8.js} +349 -817
- package/dist/ModelProperty-CGdkocQ8.js.map +1 -0
- package/dist/{PathResolver-DJdxE_OK.js → PathResolver-CX6GHoTS.js} +8 -8
- package/dist/{PathResolver-DJdxE_OK.js.map → PathResolver-CX6GHoTS.js.map} +1 -1
- package/dist/{PathResolver-BErmcZqP.js → PathResolver-z_WX47_o.js} +8 -8
- package/dist/{PathResolver-BErmcZqP.js.map → PathResolver-z_WX47_o.js.map} +1 -1
- package/dist/{QueryClient-DIu9c-w6.js → QueryClient-ByKPdRmE.js} +8 -8
- package/dist/{QueryClient-DIu9c-w6.js.map → QueryClient-ByKPdRmE.js.map} +1 -1
- package/dist/{QueryClient-D2mv63gP.js → QueryClient-Cb1iJO-x.js} +8 -8
- package/dist/{QueryClient-D2mv63gP.js.map → QueryClient-Cb1iJO-x.js.map} +1 -1
- package/dist/Schema/Schema.d.ts +24 -3
- package/dist/Schema/Schema.d.ts.map +1 -1
- package/dist/Schema/service/actors/checkExistingSchema.d.ts.map +1 -1
- package/dist/Schema/service/actors/createPropertyInstances.d.ts.map +1 -1
- package/dist/Schema/service/actors/loadOrCreateSchema.d.ts.map +1 -1
- package/dist/Schema/service/actors/verifyPropertyInstancesInCache.d.ts.map +1 -1
- package/dist/Schema/service/actors/writeModelsToDb.d.ts.map +1 -1
- package/dist/Schema/service/actors/writePropertiesToDb.d.ts.map +1 -1
- package/dist/Schema/service/actors/writeSchemaToDb.d.ts.map +1 -1
- package/dist/Schema/service/addModelsMachine.d.ts.map +1 -1
- package/dist/Schema/service/schemaMachine.d.ts +17 -3
- package/dist/Schema/service/schemaMachine.d.ts.map +1 -1
- package/dist/{Schema-DeKabJ0T.js → Schema-D1eqDHyt.js} +995 -186
- package/dist/Schema-D1eqDHyt.js.map +1 -0
- package/dist/{SchemaValidationService-cTlURuDt.js → SchemaValidationService-DyttFaV_.js} +7 -7
- package/dist/{SchemaValidationService-cTlURuDt.js.map → SchemaValidationService-DyttFaV_.js.map} +1 -1
- package/dist/browser/db/Db.d.ts.map +1 -1
- package/dist/browser/react/SeedProvider.d.ts +30 -0
- package/dist/browser/react/SeedProvider.d.ts.map +1 -0
- package/dist/browser/react/index.d.ts +4 -1
- package/dist/browser/react/index.d.ts.map +1 -1
- package/dist/browser/react/item.d.ts +10 -6
- package/dist/browser/react/item.d.ts.map +1 -1
- package/dist/browser/react/itemProperty.d.ts +37 -1
- package/dist/browser/react/itemProperty.d.ts.map +1 -1
- package/dist/browser/react/liveQuery.d.ts.map +1 -1
- package/dist/browser/react/model.d.ts +21 -7
- package/dist/browser/react/model.d.ts.map +1 -1
- package/dist/browser/react/modelProperty.d.ts +23 -0
- package/dist/browser/react/modelProperty.d.ts.map +1 -1
- package/dist/browser/react/queryClient.d.ts +28 -0
- package/dist/browser/react/queryClient.d.ts.map +1 -0
- package/dist/browser/react/schema.d.ts +8 -0
- package/dist/browser/react/schema.d.ts.map +1 -1
- package/dist/browser/react/trash.d.ts +5 -2
- package/dist/browser/react/trash.d.ts.map +1 -1
- package/dist/cjs/{ModelProperty-MkN5Rmx7.js → ModelProperty-BeJvgKMw.js} +377 -477
- package/dist/cjs/ModelProperty-BeJvgKMw.js.map +1 -0
- package/dist/cjs/{Schema-B5cr_JVK.js → Schema-CVs9J6eP.js} +709 -263
- package/dist/cjs/Schema-CVs9J6eP.js.map +1 -0
- package/dist/cjs/{SchemaValidationService-BgIzc3-r.js → SchemaValidationService-CDKcVRFQ.js} +4 -4
- package/dist/cjs/{SchemaValidationService-BgIzc3-r.js.map → SchemaValidationService-CDKcVRFQ.js.map} +1 -1
- package/dist/cjs/{getItem-CVJJPky2.js → getItem-B5RYPvrG.js} +4 -4
- package/dist/cjs/{getItem-CVJJPky2.js.map → getItem-B5RYPvrG.js.map} +1 -1
- package/dist/cjs/{getPublishPayload-DbOc3WA-.js → getPublishPayload-BD1qRob1.js} +26 -11
- package/dist/cjs/getPublishPayload-BD1qRob1.js.map +1 -0
- package/dist/cjs/{getPublishUploads-NzioLz-3.js → getPublishUploads-CnC9aYxs.js} +5 -5
- package/dist/cjs/getPublishUploads-CnC9aYxs.js.map +1 -0
- package/dist/cjs/{getSegmentedItemProperties-BsaklLwI.js → getSegmentedItemProperties-B_njnntx.js} +2 -2
- package/dist/cjs/{getSegmentedItemProperties-BsaklLwI.js.map → getSegmentedItemProperties-B_njnntx.js.map} +1 -1
- package/dist/cjs/{index-BmIVfqGN.js → index-BeKPbbk0.js} +12715 -12384
- package/dist/cjs/index-BeKPbbk0.js.map +1 -0
- package/dist/cjs/{index-C_0angRB.js → index-Dnywap_P.js} +4 -4
- package/dist/cjs/index-Dnywap_P.js.map +1 -0
- package/dist/client/actors/platformClassesInit.d.ts.map +1 -1
- package/dist/client/actors/processSchemaFiles.d.ts.map +1 -1
- package/dist/client/actors/saveAppState.d.ts.map +1 -1
- package/dist/db/read/getItemData.d.ts.map +1 -1
- package/dist/db/read/getItems.d.ts.map +1 -1
- package/dist/db/read/getModelPropertiesData.d.ts +19 -0
- package/dist/db/read/getModelPropertiesData.d.ts.map +1 -0
- package/dist/db/read/getModelsData.d.ts +15 -0
- package/dist/db/read/getModelsData.d.ts.map +1 -0
- package/dist/db/read/getPublishPayload.d.ts.map +1 -1
- package/dist/db/read/getPublishUploads.d.ts +1 -7
- package/dist/db/read/getPublishUploads.d.ts.map +1 -1
- package/dist/db/read/getSchemaUidForModel.d.ts.map +1 -1
- package/dist/db/write/updateSeedUid.d.ts +7 -0
- package/dist/db/write/updateSeedUid.d.ts.map +1 -0
- package/dist/eas.d.ts.map +1 -1
- package/dist/events/item/index.d.ts.map +1 -1
- package/dist/events/item/syncDbWithEas.d.ts.map +1 -1
- package/dist/{getItem-CcttmUY_.js → getItem-BB5HBCbK.js} +8 -8
- package/dist/{getItem-CcttmUY_.js.map → getItem-BB5HBCbK.js.map} +1 -1
- package/dist/{getPublishPayload-NFpqbd_H.js → getPublishPayload-uLm0AqN_.js} +29 -14
- package/dist/getPublishPayload-uLm0AqN_.js.map +1 -0
- package/dist/{getPublishUploads-Cpb9vgwE.js → getPublishUploads-Dc-HqhO8.js} +9 -9
- package/dist/getPublishUploads-Dc-HqhO8.js.map +1 -0
- package/dist/{getSegmentedItemProperties-DiyQPMgI.js → getSegmentedItemProperties-BrIqFNfD.js} +2 -2
- package/dist/{getSegmentedItemProperties-DiyQPMgI.js.map → getSegmentedItemProperties-BrIqFNfD.js.map} +1 -1
- package/dist/helpers/db.d.ts +12 -0
- package/dist/helpers/db.d.ts.map +1 -1
- package/dist/helpers/entity/entityDestroy.d.ts +41 -0
- package/dist/helpers/entity/entityDestroy.d.ts.map +1 -0
- package/dist/helpers/entity/index.d.ts +1 -0
- package/dist/helpers/entity/index.d.ts.map +1 -1
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/property/index.d.ts +12 -12
- package/dist/helpers/property/index.d.ts.map +1 -1
- package/dist/helpers/reactiveProxy.d.ts.map +1 -1
- package/dist/helpers/schema.d.ts.map +1 -1
- package/dist/helpers/updateSchema.d.ts +9 -0
- package/dist/helpers/updateSchema.d.ts.map +1 -1
- package/dist/helpers/waitForEntityIdle.d.ts +2 -2
- package/dist/helpers/waitForEntityIdle.d.ts.map +1 -1
- package/dist/imports/json.d.ts.map +1 -1
- package/dist/{index-r45w9hEq.js → index-2FcQHgKp.js} +2 -2
- package/dist/index-2FcQHgKp.js.map +1 -0
- package/dist/{json-I3vJhXo8.js → index-DPll6EAp.js} +12450 -12121
- package/dist/index-DPll6EAp.js.map +1 -0
- package/dist/{index-CRuq6HVi.js → index-LEY0Og1p.js} +9 -9
- package/dist/index-LEY0Og1p.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/interfaces/IItem.d.ts +2 -0
- package/dist/interfaces/IItem.d.ts.map +1 -1
- package/dist/interfaces/IItemProperty.d.ts +1 -0
- package/dist/interfaces/IItemProperty.d.ts.map +1 -1
- package/dist/main.cjs +3 -3
- package/dist/main.js +999 -1033
- package/dist/main.js.map +1 -1
- package/dist/node.js +16 -16
- package/dist/node.js.map +1 -1
- package/dist/{property-Dy09KTxg.js → property-B15X7jLX.js} +7 -5
- package/dist/property-B15X7jLX.js.map +1 -0
- package/dist/{queries-LZYSuhtz.js → queries-BPDSpiEX.js} +2 -2
- package/dist/{queries-LZYSuhtz.js.map → queries-BPDSpiEX.js.map} +1 -1
- package/dist/services/write/actors/validateEntity.d.ts.map +1 -1
- package/dist/services/write/actors/writeToDatabase.d.ts.map +1 -1
- package/dist/services/write/writeProcessMachine.d.ts +1 -1
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/item.d.ts +12 -0
- package/dist/types/item.d.ts.map +1 -1
- package/dist/types/property.d.ts +6 -0
- package/dist/types/property.d.ts.map +1 -1
- package/dist/types/publish.d.ts +9 -0
- package/dist/types/publish.d.ts.map +1 -0
- package/package.json +12 -4
- package/dist/ModelProperty-Cr3BmgkC.js.map +0 -1
- package/dist/Schema-DeKabJ0T.js.map +0 -1
- package/dist/cjs/ModelProperty-MkN5Rmx7.js.map +0 -1
- package/dist/cjs/Schema-B5cr_JVK.js.map +0 -1
- package/dist/cjs/getPublishPayload-DbOc3WA-.js.map +0 -1
- package/dist/cjs/getPublishUploads-NzioLz-3.js.map +0 -1
- package/dist/cjs/index-BmIVfqGN.js.map +0 -1
- package/dist/cjs/index-C_0angRB.js.map +0 -1
- package/dist/events/item/publish.d.ts +0 -7
- package/dist/events/item/publish.d.ts.map +0 -1
- package/dist/getPublishPayload-NFpqbd_H.js.map +0 -1
- package/dist/getPublishUploads-Cpb9vgwE.js.map +0 -1
- package/dist/index-CRuq6HVi.js.map +0 -1
- package/dist/index-r45w9hEq.js.map +0 -1
- package/dist/json-I3vJhXo8.js.map +0 -1
- package/dist/property-Dy09KTxg.js.map +0 -1
|
@@ -1,713 +1,22 @@
|
|
|
1
1
|
import { fromCallback, setup, assign, createActor } from 'xstate';
|
|
2
|
-
import {
|
|
3
|
-
import '
|
|
4
|
-
import { eq } from 'drizzle-orm';
|
|
2
|
+
import { c as convertPropertyToSchemaUpdate, u as updateModelProperties, S as Schema } from './Schema-D1eqDHyt.js';
|
|
3
|
+
import { p as BaseDb, ad as writeProcessMachine, q as models, r as properties, M as Model, o as modelPropertiesToObject, W as schemas, G as modelSchemas, ae as generateId, af as waitForEntityIdle, ag as createReactiveProxy, ah as findEntity, x as BaseFileManager, ai as forceRemoveFromCaches, aj as runDestroyLifecycle, ak as getModelIdByFileId, al as getModelId } from './index-DPll6EAp.js';
|
|
5
4
|
import debug from 'debug';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return name
|
|
22
|
-
.replace(/[^a-zA-Z0-9\s_-]/g, '_') // Replace special chars (except spaces, hyphens, underscores) with underscore
|
|
23
|
-
.replace(/\s+/g, '_') // Convert spaces to underscores
|
|
24
|
-
.replace(/^_+|_+$/g, '') // Remove leading/trailing underscores
|
|
25
|
-
.replace(/_+/g, '_'); // Collapse multiple underscores to single
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Get the full file path for a schema
|
|
29
|
-
* Format: {schemaFileId}_{schemaName}_v{version}.json
|
|
30
|
-
*
|
|
31
|
-
* The ID-first format ensures all files for a schema group together when sorted alphabetically.
|
|
32
|
-
*
|
|
33
|
-
* @param name - Schema name
|
|
34
|
-
* @param version - Schema version
|
|
35
|
-
* @param schemaFileId - Schema file ID (required)
|
|
36
|
-
*/
|
|
37
|
-
const getSchemaFilePath = (name, version, schemaFileId) => {
|
|
38
|
-
const path = BaseFileManager.getPathModule();
|
|
39
|
-
const workingDir = BaseFileManager.getWorkingDir();
|
|
40
|
-
const sanitizedName = sanitizeSchemaName(name);
|
|
41
|
-
const filename = schemaFileId
|
|
42
|
-
? `${schemaFileId}_${sanitizedName}_v${version}.json`
|
|
43
|
-
: `${sanitizedName}_v${version}.json`;
|
|
44
|
-
return path.join(workingDir, filename);
|
|
45
|
-
};
|
|
46
|
-
/**
|
|
47
|
-
* Get schemaFileId from database for a schema
|
|
48
|
-
* @param schemaName - Schema name
|
|
49
|
-
* @returns Schema file ID
|
|
50
|
-
* @throws Error if schema not found or missing schemaFileId
|
|
51
|
-
*/
|
|
52
|
-
async function getSchemaFileId(schemaName) {
|
|
53
|
-
const { BaseDb } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aI; });
|
|
54
|
-
const db = BaseDb.getAppDb();
|
|
55
|
-
const { schemas } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aN; });
|
|
56
|
-
const { eq, desc } = await import('drizzle-orm');
|
|
57
|
-
const dbSchema = await db
|
|
58
|
-
.select()
|
|
59
|
-
.from(schemas)
|
|
60
|
-
.where(eq(schemas.name, schemaName))
|
|
61
|
-
.orderBy(desc(schemas.version))
|
|
62
|
-
.limit(1);
|
|
63
|
-
if (dbSchema.length === 0 || !dbSchema[0].schemaFileId) {
|
|
64
|
-
throw new Error(`Schema ${schemaName} not found in database or missing schemaFileId`);
|
|
65
|
-
}
|
|
66
|
-
return dbSchema[0].schemaFileId;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Get model name from modelId
|
|
70
|
-
* @param modelId - The model ID to look up
|
|
71
|
-
* @returns The model name, or undefined if not found
|
|
72
|
-
*/
|
|
73
|
-
async function getModelNameFromId(modelId) {
|
|
74
|
-
if (!modelId) {
|
|
75
|
-
return undefined;
|
|
76
|
-
}
|
|
77
|
-
const db = BaseDb.getAppDb();
|
|
78
|
-
if (!db) {
|
|
79
|
-
throw new Error('Database not found');
|
|
80
|
-
}
|
|
81
|
-
const modelRecords = await db
|
|
82
|
-
.select()
|
|
83
|
-
.from(models)
|
|
84
|
-
.where(eq(models.id, modelId))
|
|
85
|
-
.limit(1);
|
|
86
|
-
if (modelRecords.length === 0) {
|
|
87
|
-
return undefined;
|
|
88
|
-
}
|
|
89
|
-
return modelRecords[0].name;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Convert a TProperty/ModelPropertyMachineContext to SchemaPropertyUpdate format
|
|
93
|
-
* This function converts the internal property representation to the schema file format
|
|
94
|
-
* @param property - The TProperty instance to convert
|
|
95
|
-
* @param modelName - The name of the model this property belongs to
|
|
96
|
-
* @param propertyName - The name of the property
|
|
97
|
-
* @returns A SchemaPropertyUpdate object ready to be passed to updateModelProperties
|
|
98
|
-
*/
|
|
99
|
-
async function convertPropertyToSchemaUpdate(property, modelName, propertyName) {
|
|
100
|
-
const updates = {};
|
|
101
|
-
// Convert dataType to type
|
|
102
|
-
if (property.dataType) {
|
|
103
|
-
updates.type = property.dataType;
|
|
104
|
-
}
|
|
105
|
-
// Handle Relation type
|
|
106
|
-
if (property.dataType === ModelPropertyDataTypes.Relation) {
|
|
107
|
-
if (property.ref) {
|
|
108
|
-
updates.model = property.ref;
|
|
109
|
-
}
|
|
110
|
-
else if (property.refModelId) {
|
|
111
|
-
// If ref is not set but refModelId is, get the model name from the database
|
|
112
|
-
const refModelName = await getModelNameFromId(property.refModelId);
|
|
113
|
-
if (refModelName) {
|
|
114
|
-
updates.model = refModelName;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
// Handle List type
|
|
119
|
-
if (property.dataType === ModelPropertyDataTypes.List) {
|
|
120
|
-
if (property.refValueType) {
|
|
121
|
-
updates.items = {
|
|
122
|
-
type: property.refValueType,
|
|
123
|
-
};
|
|
124
|
-
if (property.ref) {
|
|
125
|
-
updates.items.model = property.ref;
|
|
126
|
-
}
|
|
127
|
-
else if (property.refModelId) {
|
|
128
|
-
// If ref is not set but refModelId is, get the model name from the database
|
|
129
|
-
const refModelName = await getModelNameFromId(property.refModelId);
|
|
130
|
-
if (refModelName) {
|
|
131
|
-
updates.items.model = refModelName;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
// Handle storage configuration (for Text properties with storage)
|
|
137
|
-
if (property.storageType || property.localStorageDir || property.filenameSuffix) {
|
|
138
|
-
const storageType = property.storageType || 'ItemStorage'; // Default to ItemStorage if not specified
|
|
139
|
-
updates.storage = {
|
|
140
|
-
type: storageType,
|
|
141
|
-
};
|
|
142
|
-
if (property.localStorageDir) {
|
|
143
|
-
updates.storage.path = property.localStorageDir;
|
|
144
|
-
}
|
|
145
|
-
if (property.filenameSuffix) {
|
|
146
|
-
updates.storage.extension = property.filenameSuffix;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return {
|
|
150
|
-
modelName,
|
|
151
|
-
propertyName,
|
|
152
|
-
updates,
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Update model properties in a schema and create a new version
|
|
157
|
-
* @param schemaName - The name of the schema to update
|
|
158
|
-
* @param propertyUpdates - Array of property updates to apply
|
|
159
|
-
* @param modelUpdates - Optional array of model renames
|
|
160
|
-
* @returns The file path of the new schema version
|
|
161
|
-
* @throws Error if schema not found or updates are invalid
|
|
162
|
-
*/
|
|
163
|
-
async function updateModelProperties(schemaName, propertyUpdates, modelUpdates) {
|
|
164
|
-
// Get the latest version of the schema
|
|
165
|
-
const latestVersion = await getLatestSchemaVersion(schemaName);
|
|
166
|
-
if (latestVersion === 0) {
|
|
167
|
-
throw new Error(`Schema ${schemaName} not found`);
|
|
168
|
-
}
|
|
169
|
-
// Get schemaFileId from database
|
|
170
|
-
const schemaFileId = await getSchemaFileId(schemaName);
|
|
171
|
-
// Load the latest schema file
|
|
172
|
-
const latestFilePath = getSchemaFilePath(schemaName, latestVersion, schemaFileId);
|
|
173
|
-
const content = await BaseFileManager.readFileAsString(latestFilePath);
|
|
174
|
-
const schemaFile = JSON.parse(content);
|
|
175
|
-
if (!schemaFile.$schema) {
|
|
176
|
-
throw new Error(`Schema file ${latestFilePath} is not a complete schema file`);
|
|
177
|
-
}
|
|
178
|
-
// Create a copy of the schema for the new version
|
|
179
|
-
// Preserve schema ID and all model/property IDs
|
|
180
|
-
const newVersion = latestVersion + 1;
|
|
181
|
-
const updatedSchema = {
|
|
182
|
-
...schemaFile,
|
|
183
|
-
version: newVersion,
|
|
184
|
-
// Preserve schema ID from previous version
|
|
185
|
-
id: schemaFile.id,
|
|
186
|
-
metadata: {
|
|
187
|
-
...schemaFile.metadata,
|
|
188
|
-
updatedAt: new Date().toISOString(),
|
|
189
|
-
},
|
|
190
|
-
// Deep copy models to preserve IDs
|
|
191
|
-
models: Object.fromEntries(Object.entries(schemaFile.models).map(([modelName, model]) => [
|
|
192
|
-
modelName,
|
|
193
|
-
{
|
|
194
|
-
...model,
|
|
195
|
-
// Preserve model ID
|
|
196
|
-
id: model.id,
|
|
197
|
-
// Deep copy properties to preserve IDs
|
|
198
|
-
properties: Object.fromEntries(Object.entries(model.properties).map(([propName, prop]) => [
|
|
199
|
-
propName,
|
|
200
|
-
{
|
|
201
|
-
...prop,
|
|
202
|
-
// Preserve property ID
|
|
203
|
-
id: prop.id,
|
|
204
|
-
},
|
|
205
|
-
])),
|
|
206
|
-
},
|
|
207
|
-
])),
|
|
208
|
-
migrations: [
|
|
209
|
-
...schemaFile.migrations,
|
|
210
|
-
{
|
|
211
|
-
version: newVersion,
|
|
212
|
-
timestamp: new Date().toISOString(),
|
|
213
|
-
description: `Updated model properties: ${propertyUpdates.map(u => `${u.modelName}.${u.propertyName}`).join(', ')}`,
|
|
214
|
-
changes: propertyUpdates.map(update => ({
|
|
215
|
-
type: 'property_update',
|
|
216
|
-
modelName: update.modelName,
|
|
217
|
-
propertyName: update.propertyName,
|
|
218
|
-
updates: update.updates,
|
|
219
|
-
})),
|
|
220
|
-
},
|
|
221
|
-
],
|
|
222
|
-
};
|
|
223
|
-
// Apply model renames first (if any)
|
|
224
|
-
if (modelUpdates && modelUpdates.length > 0) {
|
|
225
|
-
for (const modelUpdate of modelUpdates) {
|
|
226
|
-
if (updatedSchema.models[modelUpdate.oldName]) {
|
|
227
|
-
// Rename the model in the models object
|
|
228
|
-
updatedSchema.models[modelUpdate.newName] = updatedSchema.models[modelUpdate.oldName];
|
|
229
|
-
delete updatedSchema.models[modelUpdate.oldName];
|
|
230
|
-
// Update any property references to this model
|
|
231
|
-
for (const modelName in updatedSchema.models) {
|
|
232
|
-
const model = updatedSchema.models[modelName];
|
|
233
|
-
for (const propertyName in model.properties) {
|
|
234
|
-
const property = model.properties[propertyName];
|
|
235
|
-
if (property.model === modelUpdate.oldName) {
|
|
236
|
-
property.model = modelUpdate.newName;
|
|
237
|
-
}
|
|
238
|
-
if (property.items?.model === modelUpdate.oldName) {
|
|
239
|
-
property.items.model = modelUpdate.newName;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
// Add to migration changes
|
|
244
|
-
updatedSchema.migrations[updatedSchema.migrations.length - 1].changes.push({
|
|
245
|
-
type: 'model_rename',
|
|
246
|
-
oldName: modelUpdate.oldName,
|
|
247
|
-
newName: modelUpdate.newName,
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
// Apply property updates
|
|
253
|
-
for (const update of propertyUpdates) {
|
|
254
|
-
const model = updatedSchema.models[update.modelName];
|
|
255
|
-
if (!model) {
|
|
256
|
-
throw new Error(`Model ${update.modelName} not found in schema ${schemaName}`);
|
|
257
|
-
}
|
|
258
|
-
if (!model.properties[update.propertyName]) {
|
|
259
|
-
throw new Error(`Property ${update.propertyName} not found in model ${update.modelName} of schema ${schemaName}`);
|
|
260
|
-
}
|
|
261
|
-
// Update the property with new values
|
|
262
|
-
const property = model.properties[update.propertyName];
|
|
263
|
-
Object.assign(property, update.updates);
|
|
264
|
-
}
|
|
265
|
-
// Write the new schema version to file using ID-based naming (preferred)
|
|
266
|
-
const newFilePath = getSchemaFilePath(schemaName, newVersion, updatedSchema.id ?? undefined);
|
|
267
|
-
const newContent = JSON.stringify(updatedSchema, null, 2);
|
|
268
|
-
await BaseFileManager.saveFile(newFilePath, newContent);
|
|
269
|
-
// Wait for the file to be available with content (important for browser/OPFS where writes may not be immediately readable)
|
|
270
|
-
await BaseFileManager.waitForFileWithContent(newFilePath);
|
|
271
|
-
logger$4(`Created new schema version ${newVersion} for ${schemaName} at ${newFilePath}`);
|
|
272
|
-
// Load the new schema file to process models and add them to the database
|
|
273
|
-
// Extract model renames from migrations to pass to database update
|
|
274
|
-
const modelRenames = new Map();
|
|
275
|
-
const latestMigration = updatedSchema.migrations[updatedSchema.migrations.length - 1];
|
|
276
|
-
for (const change of latestMigration.changes) {
|
|
277
|
-
if (change.type === 'model_rename') {
|
|
278
|
-
modelRenames.set(change.oldName, change.newName);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
// Load schema with model renames handled
|
|
282
|
-
await loadSchemaWithRenames(newFilePath, modelRenames);
|
|
283
|
-
return newFilePath;
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Load a schema file and handle model renames in the database
|
|
287
|
-
* This is a helper function that processes model renames before loading
|
|
288
|
-
*/
|
|
289
|
-
async function loadSchemaWithRenames(schemaFilePath, modelRenames) {
|
|
290
|
-
const content = await BaseFileManager.readFileAsString(schemaFilePath);
|
|
291
|
-
const schemaFile = JSON.parse(content);
|
|
292
|
-
if (!schemaFile.$schema) {
|
|
293
|
-
throw new Error(`File ${schemaFilePath} is not a complete schema file (missing $schema field).`);
|
|
294
|
-
}
|
|
295
|
-
const schemaName = schemaFile.metadata?.name;
|
|
296
|
-
const version = schemaFile.version;
|
|
297
|
-
if (!schemaName) {
|
|
298
|
-
throw new Error('Schema name is required in metadata.name');
|
|
299
|
-
}
|
|
300
|
-
// Convert to JsonImportSchema format for processing
|
|
301
|
-
// Remove id fields for JsonImportSchema format (they're not part of the import format)
|
|
302
|
-
const importData = {
|
|
303
|
-
name: schemaName,
|
|
304
|
-
models: Object.fromEntries(Object.entries(schemaFile.models).map(([modelName, model]) => [
|
|
305
|
-
modelName,
|
|
306
|
-
{
|
|
307
|
-
description: model.description,
|
|
308
|
-
properties: Object.fromEntries(Object.entries(model.properties).map(([propName, prop]) => [
|
|
309
|
-
propName,
|
|
310
|
-
{
|
|
311
|
-
type: prop.type || 'string', // Ensure type is present
|
|
312
|
-
...prop,
|
|
313
|
-
// Remove id field for import format (not part of JsonImportSchema)
|
|
314
|
-
},
|
|
315
|
-
])),
|
|
316
|
-
indexes: model.indexes,
|
|
317
|
-
},
|
|
318
|
-
])),
|
|
319
|
-
};
|
|
320
|
-
// Use dynamic import to break circular dependency
|
|
321
|
-
const { createModelsFromJson } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aW; });
|
|
322
|
-
// Generate schema ID if missing
|
|
323
|
-
if (!schemaFile.id) {
|
|
324
|
-
const { generateId } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aL; });
|
|
325
|
-
schemaFile.id = generateId();
|
|
326
|
-
logger$4('Generated schema ID for schema:', schemaFile.id);
|
|
327
|
-
}
|
|
328
|
-
// Extract schemaFileIds from JSON file and generate missing ones BEFORE creating models
|
|
329
|
-
// This ensures Model instances are created with correct IDs
|
|
330
|
-
const modelFileIds = new Map();
|
|
331
|
-
const propertyFileIds = new Map();
|
|
332
|
-
const { generateId } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aL; });
|
|
333
|
-
for (const [modelName, model] of Object.entries(schemaFile.models)) {
|
|
334
|
-
// Generate model ID if missing
|
|
335
|
-
if (!model.id) {
|
|
336
|
-
model.id = generateId();
|
|
337
|
-
logger$4(`Generated model ID for ${modelName}:`, model.id);
|
|
338
|
-
}
|
|
339
|
-
modelFileIds.set(modelName, model.id);
|
|
340
|
-
const propIds = new Map();
|
|
341
|
-
for (const [propName, prop] of Object.entries(model.properties)) {
|
|
342
|
-
// Generate property ID if missing
|
|
343
|
-
if (!prop.id) {
|
|
344
|
-
prop.id = generateId();
|
|
345
|
-
logger$4(`Generated property ID for ${modelName}.${propName}:`, prop.id);
|
|
346
|
-
}
|
|
347
|
-
propIds.set(propName, prop.id);
|
|
348
|
-
}
|
|
349
|
-
if (propIds.size > 0) {
|
|
350
|
-
propertyFileIds.set(modelName, propIds);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
// Convert JSON models to Model classes, passing modelFileIds and propertyFileIds so Model instances use correct IDs
|
|
354
|
-
const modelDefinitions = await createModelsFromJson(importData, modelFileIds, propertyFileIds);
|
|
355
|
-
// Convert schema file metadata to schema input for database
|
|
356
|
-
const schemaInput = {
|
|
357
|
-
name: schemaName,
|
|
358
|
-
version,
|
|
359
|
-
schemaFileId: schemaFile.id || null,
|
|
360
|
-
schemaData: null,
|
|
361
|
-
isDraft: false,
|
|
362
|
-
isEdited: false,
|
|
363
|
-
createdAt: new Date(schemaFile.metadata.createdAt).getTime(),
|
|
364
|
-
updatedAt: new Date(schemaFile.metadata.updatedAt).getTime(),
|
|
365
|
-
};
|
|
366
|
-
// Use dynamic import to break circular dependency
|
|
367
|
-
const { addSchemaToDb, addModelsToDb } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aR; });
|
|
368
|
-
// Add schema to database with schemaFileId
|
|
369
|
-
const schemaRecord = await addSchemaToDb(schemaInput, schemaFile.id);
|
|
370
|
-
// Add models to database with model renames handled and schemaFileIds
|
|
371
|
-
await addModelsToDb(modelDefinitions, schemaRecord, modelRenames, {
|
|
372
|
-
schemaFileId: schemaFile.id,
|
|
373
|
-
modelFileIds,
|
|
374
|
-
propertyFileIds,
|
|
375
|
-
});
|
|
376
|
-
// Models are now Model instances, no registration needed
|
|
377
|
-
// They should be created via Model.create() and are accessible via Model static methods
|
|
378
|
-
for (const [modelName] of Object.entries(modelDefinitions)) {
|
|
379
|
-
logger$4('loadSchemaWithRenames - model available:', modelName);
|
|
380
|
-
}
|
|
381
|
-
return schemaFilePath;
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* Rename a property in a model
|
|
385
|
-
* This is a convenience function that updates the property name
|
|
386
|
-
* Note: This creates a new property and you may want to handle the old property separately
|
|
387
|
-
* @param schemaName - The name of the schema
|
|
388
|
-
* @param modelName - The name of the model
|
|
389
|
-
* @param oldPropertyName - The current property name
|
|
390
|
-
* @param newPropertyName - The new property name
|
|
391
|
-
* @returns The file path of the new schema version
|
|
392
|
-
*/
|
|
393
|
-
async function renameModelProperty(schemaName, modelName, oldPropertyName, newPropertyName) {
|
|
394
|
-
// Get the latest version
|
|
395
|
-
const latestVersion = await getLatestSchemaVersion(schemaName);
|
|
396
|
-
if (latestVersion === 0) {
|
|
397
|
-
throw new Error(`Schema ${schemaName} not found`);
|
|
398
|
-
}
|
|
399
|
-
// Get schemaFileId from database
|
|
400
|
-
const schemaFileId = await getSchemaFileId(schemaName);
|
|
401
|
-
// Load the latest schema file
|
|
402
|
-
const latestFilePath = getSchemaFilePath(schemaName, latestVersion, schemaFileId);
|
|
403
|
-
const content = await BaseFileManager.readFileAsString(latestFilePath);
|
|
404
|
-
const schemaFile = JSON.parse(content);
|
|
405
|
-
if (!schemaFile.$schema) {
|
|
406
|
-
throw new Error(`Schema file ${latestFilePath} is not a complete schema file`);
|
|
407
|
-
}
|
|
408
|
-
const model = schemaFile.models[modelName];
|
|
409
|
-
if (!model) {
|
|
410
|
-
throw new Error(`Model ${modelName} not found in schema ${schemaName}`);
|
|
411
|
-
}
|
|
412
|
-
if (!model.properties[oldPropertyName]) {
|
|
413
|
-
throw new Error(`Property ${oldPropertyName} not found in model ${modelName} of schema ${schemaName}`);
|
|
414
|
-
}
|
|
415
|
-
if (model.properties[newPropertyName]) {
|
|
416
|
-
throw new Error(`Property ${newPropertyName} already exists in model ${modelName} of schema ${schemaName}`);
|
|
417
|
-
}
|
|
418
|
-
// Create new version with renamed property
|
|
419
|
-
// Preserve all IDs - when renaming, we keep the same property ID
|
|
420
|
-
const newVersion = latestVersion + 1;
|
|
421
|
-
const oldProperty = model.properties[oldPropertyName];
|
|
422
|
-
const updatedSchema = {
|
|
423
|
-
...schemaFile,
|
|
424
|
-
version: newVersion,
|
|
425
|
-
id: schemaFile.id, // Preserve schema ID
|
|
426
|
-
metadata: {
|
|
427
|
-
...schemaFile.metadata,
|
|
428
|
-
updatedAt: new Date().toISOString(),
|
|
429
|
-
},
|
|
430
|
-
models: {
|
|
431
|
-
...schemaFile.models,
|
|
432
|
-
[modelName]: {
|
|
433
|
-
...model,
|
|
434
|
-
id: model.id, // Preserve model ID
|
|
435
|
-
properties: {
|
|
436
|
-
...Object.fromEntries(Object.entries(model.properties)
|
|
437
|
-
.filter(([name]) => name !== oldPropertyName)
|
|
438
|
-
.map(([name, prop]) => [name, { ...prop, id: prop.id }])),
|
|
439
|
-
[newPropertyName]: {
|
|
440
|
-
...oldProperty,
|
|
441
|
-
id: oldProperty.id, // Preserve property ID when renaming
|
|
442
|
-
},
|
|
443
|
-
},
|
|
444
|
-
},
|
|
445
|
-
},
|
|
446
|
-
migrations: [
|
|
447
|
-
...schemaFile.migrations,
|
|
448
|
-
{
|
|
449
|
-
version: newVersion,
|
|
450
|
-
timestamp: new Date().toISOString(),
|
|
451
|
-
description: `Renamed property ${modelName}.${oldPropertyName} to ${newPropertyName}`,
|
|
452
|
-
changes: [
|
|
453
|
-
{
|
|
454
|
-
type: 'property_rename',
|
|
455
|
-
modelName,
|
|
456
|
-
oldPropertyName,
|
|
457
|
-
newPropertyName,
|
|
458
|
-
},
|
|
459
|
-
],
|
|
460
|
-
},
|
|
461
|
-
],
|
|
462
|
-
};
|
|
463
|
-
// Remove the old property name
|
|
464
|
-
delete updatedSchema.models[modelName].properties[oldPropertyName];
|
|
465
|
-
// Write the new schema version using ID-based naming (preferred)
|
|
466
|
-
const newFilePath = getSchemaFilePath(schemaName, newVersion, updatedSchema.id ?? undefined);
|
|
467
|
-
const newContent = JSON.stringify(updatedSchema, null, 2);
|
|
468
|
-
// Ensure the directory exists before saving
|
|
469
|
-
const path = BaseFileManager.getPathModule();
|
|
470
|
-
const dir = path.dirname(newFilePath);
|
|
471
|
-
await BaseFileManager.createDirIfNotExists(dir);
|
|
472
|
-
await BaseFileManager.saveFile(newFilePath, newContent);
|
|
473
|
-
// Wait for the file to be available with content (important for browser/OPFS where writes may not be immediately readable)
|
|
474
|
-
await BaseFileManager.waitForFileWithContent(newFilePath);
|
|
475
|
-
logger$4(`Renamed property ${oldPropertyName} to ${newPropertyName} in schema ${schemaName} v${newVersion}`);
|
|
476
|
-
// Use dynamic import to break circular dependency
|
|
477
|
-
const { loadSchemaFromFile } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aW; });
|
|
478
|
-
// Load the new schema file
|
|
479
|
-
await loadSchemaFromFile(newFilePath);
|
|
480
|
-
return newFilePath;
|
|
481
|
-
}
|
|
482
|
-
/**
|
|
483
|
-
* Delete a model from a schema
|
|
484
|
-
* @param schemaName - The name of the schema
|
|
485
|
-
* @param modelName - The name of the model to delete
|
|
486
|
-
* @param options - Optional deletion options
|
|
487
|
-
* @returns The file path of the new schema version
|
|
488
|
-
* @throws Error if schema or model not found
|
|
489
|
-
*/
|
|
490
|
-
async function deleteModelFromSchema(schemaName, modelName, options = {}) {
|
|
491
|
-
const { removeReferencingProperties = false } = options;
|
|
492
|
-
// Get the latest version
|
|
493
|
-
const latestVersion = await getLatestSchemaVersion(schemaName);
|
|
494
|
-
if (latestVersion === 0) {
|
|
495
|
-
throw new Error(`Schema ${schemaName} not found`);
|
|
496
|
-
}
|
|
497
|
-
// Get schemaFileId from database
|
|
498
|
-
const schemaFileId = await getSchemaFileId(schemaName);
|
|
499
|
-
// Load the latest schema file
|
|
500
|
-
const latestFilePath = getSchemaFilePath(schemaName, latestVersion, schemaFileId);
|
|
501
|
-
const content = await BaseFileManager.readFileAsString(latestFilePath);
|
|
502
|
-
const schemaFile = JSON.parse(content);
|
|
503
|
-
if (!schemaFile.$schema) {
|
|
504
|
-
throw new Error(`Schema file ${latestFilePath} is not a complete schema file`);
|
|
505
|
-
}
|
|
506
|
-
if (!schemaFile.models[modelName]) {
|
|
507
|
-
throw new Error(`Model ${modelName} not found in schema ${schemaName}`);
|
|
508
|
-
}
|
|
509
|
-
// Create new version without the model
|
|
510
|
-
// Preserve IDs for remaining models and properties
|
|
511
|
-
const newVersion = latestVersion + 1;
|
|
512
|
-
const updatedSchema = {
|
|
513
|
-
...schemaFile,
|
|
514
|
-
version: newVersion,
|
|
515
|
-
id: schemaFile.id, // Preserve schema ID
|
|
516
|
-
metadata: {
|
|
517
|
-
...schemaFile.metadata,
|
|
518
|
-
updatedAt: new Date().toISOString(),
|
|
519
|
-
},
|
|
520
|
-
// Preserve IDs for remaining models and their properties
|
|
521
|
-
models: Object.fromEntries(Object.entries(schemaFile.models)
|
|
522
|
-
.filter(([name]) => name !== modelName)
|
|
523
|
-
.map(([name, model]) => [
|
|
524
|
-
name,
|
|
525
|
-
{
|
|
526
|
-
...model,
|
|
527
|
-
id: model.id, // Preserve model ID
|
|
528
|
-
properties: Object.fromEntries(Object.entries(model.properties).map(([propName, prop]) => [
|
|
529
|
-
propName,
|
|
530
|
-
{ ...prop, id: prop.id }, // Preserve property ID
|
|
531
|
-
])),
|
|
532
|
-
},
|
|
533
|
-
])),
|
|
534
|
-
migrations: [
|
|
535
|
-
...schemaFile.migrations,
|
|
536
|
-
{
|
|
537
|
-
version: newVersion,
|
|
538
|
-
timestamp: new Date().toISOString(),
|
|
539
|
-
description: `Deleted model ${modelName} from schema`,
|
|
540
|
-
changes: [
|
|
541
|
-
{
|
|
542
|
-
type: 'model_delete',
|
|
543
|
-
modelName,
|
|
544
|
-
removeReferencingProperties,
|
|
545
|
-
},
|
|
546
|
-
],
|
|
547
|
-
},
|
|
548
|
-
],
|
|
549
|
-
};
|
|
550
|
-
// Remove the model
|
|
551
|
-
delete updatedSchema.models[modelName];
|
|
552
|
-
// Handle properties that reference this model
|
|
553
|
-
const propertiesToRemove = [];
|
|
554
|
-
for (const [otherModelName, model] of Object.entries(updatedSchema.models)) {
|
|
555
|
-
for (const [propertyName, property] of Object.entries(model.properties)) {
|
|
556
|
-
// Check if property references the deleted model
|
|
557
|
-
if (property.model === modelName || property.items?.model === modelName) {
|
|
558
|
-
if (removeReferencingProperties) {
|
|
559
|
-
// Mark for removal
|
|
560
|
-
propertiesToRemove.push({ modelName: otherModelName, propertyName });
|
|
561
|
-
}
|
|
562
|
-
else {
|
|
563
|
-
// Remove the reference (set to null or remove model field)
|
|
564
|
-
if (property.model === modelName) {
|
|
565
|
-
delete property.model;
|
|
566
|
-
}
|
|
567
|
-
if (property.items?.model === modelName) {
|
|
568
|
-
delete property.items.model;
|
|
569
|
-
// If items only had model, we might want to remove items entirely
|
|
570
|
-
// But for now, just remove the model reference
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
// Remove properties if requested
|
|
577
|
-
if (removeReferencingProperties) {
|
|
578
|
-
for (const { modelName: mName, propertyName } of propertiesToRemove) {
|
|
579
|
-
delete updatedSchema.models[mName].properties[propertyName];
|
|
580
|
-
updatedSchema.migrations[updatedSchema.migrations.length - 1].changes.push({
|
|
581
|
-
type: 'property_delete',
|
|
582
|
-
modelName: mName,
|
|
583
|
-
propertyName,
|
|
584
|
-
reason: `Referenced deleted model ${modelName}`,
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
else {
|
|
589
|
-
// Update migration to note which properties were updated
|
|
590
|
-
const updatedProperties = [];
|
|
591
|
-
for (const [otherModelName, model] of Object.entries(updatedSchema.models)) {
|
|
592
|
-
for (const [propertyName, property] of Object.entries(model.properties)) {
|
|
593
|
-
if (property.model === modelName || property.items?.model === modelName) {
|
|
594
|
-
updatedProperties.push({ modelName: otherModelName, propertyName });
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
if (updatedProperties.length > 0) {
|
|
599
|
-
updatedSchema.migrations[updatedSchema.migrations.length - 1].changes.push({
|
|
600
|
-
type: 'properties_updated',
|
|
601
|
-
properties: updatedProperties,
|
|
602
|
-
reason: `Removed references to deleted model ${modelName}`,
|
|
603
|
-
});
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
// Write the new schema version using ID-based naming (preferred)
|
|
607
|
-
const newFilePath = getSchemaFilePath(schemaName, newVersion, updatedSchema.id ?? undefined);
|
|
608
|
-
const newContent = JSON.stringify(updatedSchema, null, 2);
|
|
609
|
-
// Ensure the directory exists before saving
|
|
610
|
-
const path = BaseFileManager.getPathModule();
|
|
611
|
-
const dir = path.dirname(newFilePath);
|
|
612
|
-
await BaseFileManager.createDirIfNotExists(dir);
|
|
613
|
-
await BaseFileManager.saveFile(newFilePath, newContent);
|
|
614
|
-
// Wait for the file to be available with content (important for browser/OPFS where writes may not be immediately readable)
|
|
615
|
-
await BaseFileManager.waitForFileWithContent(newFilePath);
|
|
616
|
-
logger$4(`Deleted model ${modelName} from schema ${schemaName} v${newVersion}`);
|
|
617
|
-
// Use dynamic import to break circular dependency
|
|
618
|
-
const { loadSchemaFromFile } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aW; });
|
|
619
|
-
// Load the new schema file
|
|
620
|
-
await loadSchemaFromFile(newFilePath);
|
|
621
|
-
return newFilePath;
|
|
622
|
-
}
|
|
623
|
-
/**
|
|
624
|
-
* Delete a property from a model in a schema
|
|
625
|
-
* @param schemaName - The name of the schema
|
|
626
|
-
* @param modelName - The name of the model
|
|
627
|
-
* @param propertyName - The name of the property to delete
|
|
628
|
-
* @param options - Optional deletion options
|
|
629
|
-
* @returns The file path of the new schema version
|
|
630
|
-
* @throws Error if schema, model, or property not found
|
|
631
|
-
*/
|
|
632
|
-
async function deletePropertyFromModel(schemaName, modelName, propertyName, options = {}) {
|
|
633
|
-
// Get the latest version
|
|
634
|
-
const latestVersion = await getLatestSchemaVersion(schemaName);
|
|
635
|
-
if (latestVersion === 0) {
|
|
636
|
-
throw new Error(`Schema ${schemaName} not found`);
|
|
637
|
-
}
|
|
638
|
-
// Get schemaFileId from database
|
|
639
|
-
const schemaFileId = await getSchemaFileId(schemaName);
|
|
640
|
-
// Load the latest schema file
|
|
641
|
-
const latestFilePath = getSchemaFilePath(schemaName, latestVersion, schemaFileId);
|
|
642
|
-
const content = await BaseFileManager.readFileAsString(latestFilePath);
|
|
643
|
-
const schemaFile = JSON.parse(content);
|
|
644
|
-
if (!schemaFile.$schema) {
|
|
645
|
-
throw new Error(`Schema file ${latestFilePath} is not a complete schema file`);
|
|
646
|
-
}
|
|
647
|
-
const model = schemaFile.models[modelName];
|
|
648
|
-
if (!model) {
|
|
649
|
-
throw new Error(`Model ${modelName} not found in schema ${schemaName}`);
|
|
650
|
-
}
|
|
651
|
-
if (!model.properties[propertyName]) {
|
|
652
|
-
throw new Error(`Property ${propertyName} not found in model ${modelName} of schema ${schemaName}`);
|
|
653
|
-
}
|
|
654
|
-
// Create new version without the property
|
|
655
|
-
// Preserve IDs for schema, models, and remaining properties
|
|
656
|
-
const newVersion = latestVersion + 1;
|
|
657
|
-
const updatedSchema = {
|
|
658
|
-
...schemaFile,
|
|
659
|
-
version: newVersion,
|
|
660
|
-
id: schemaFile.id, // Preserve schema ID
|
|
661
|
-
metadata: {
|
|
662
|
-
...schemaFile.metadata,
|
|
663
|
-
updatedAt: new Date().toISOString(),
|
|
664
|
-
},
|
|
665
|
-
models: Object.fromEntries(Object.entries(schemaFile.models).map(([mName, m]) => [
|
|
666
|
-
mName,
|
|
667
|
-
{
|
|
668
|
-
...m,
|
|
669
|
-
id: m.id, // Preserve model ID
|
|
670
|
-
properties: Object.fromEntries(Object.entries(m.properties)
|
|
671
|
-
.filter(([propName]) => !(mName === modelName && propName === propertyName))
|
|
672
|
-
.map(([propName, prop]) => [
|
|
673
|
-
propName,
|
|
674
|
-
{ ...prop, id: prop.id }, // Preserve property ID
|
|
675
|
-
])),
|
|
676
|
-
},
|
|
677
|
-
])),
|
|
678
|
-
migrations: [
|
|
679
|
-
...schemaFile.migrations,
|
|
680
|
-
{
|
|
681
|
-
version: newVersion,
|
|
682
|
-
timestamp: new Date().toISOString(),
|
|
683
|
-
description: `Deleted property ${modelName}.${propertyName} from schema`,
|
|
684
|
-
changes: [
|
|
685
|
-
{
|
|
686
|
-
type: 'property_delete',
|
|
687
|
-
modelName,
|
|
688
|
-
propertyName,
|
|
689
|
-
},
|
|
690
|
-
],
|
|
691
|
-
},
|
|
692
|
-
],
|
|
693
|
-
};
|
|
694
|
-
// Write the new schema version using ID-based naming (preferred)
|
|
695
|
-
const newFilePath = getSchemaFilePath(schemaName, newVersion, updatedSchema.id ?? undefined);
|
|
696
|
-
const newContent = JSON.stringify(updatedSchema, null, 2);
|
|
697
|
-
// Ensure the directory exists before saving
|
|
698
|
-
const path = BaseFileManager.getPathModule();
|
|
699
|
-
const dir = path.dirname(newFilePath);
|
|
700
|
-
await BaseFileManager.createDirIfNotExists(dir);
|
|
701
|
-
await BaseFileManager.saveFile(newFilePath, newContent);
|
|
702
|
-
// Wait for the file to be available with content (important for browser/OPFS where writes may not be immediately readable)
|
|
703
|
-
await BaseFileManager.waitForFileWithContent(newFilePath);
|
|
704
|
-
logger$4(`Deleted property ${propertyName} from model ${modelName} in schema ${schemaName} v${newVersion}`);
|
|
705
|
-
// Use dynamic import to break circular dependency
|
|
706
|
-
const { loadSchemaFromFile } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aW; });
|
|
707
|
-
// Load the new schema file
|
|
708
|
-
await loadSchemaFromFile(newFilePath);
|
|
709
|
-
return newFilePath;
|
|
710
|
-
}
|
|
5
|
+
import { eq, and } from 'drizzle-orm';
|
|
6
|
+
import './SchemaValidationService-DyttFaV_.js';
|
|
7
|
+
import '@sinclair/typebox/value';
|
|
8
|
+
import 'reflect-metadata';
|
|
9
|
+
import 'pluralize';
|
|
10
|
+
import '@sinclair/typebox';
|
|
11
|
+
import 'drizzle-orm/sqlite-core';
|
|
12
|
+
import 'nanoid';
|
|
13
|
+
import 'nanoid-dictionary';
|
|
14
|
+
import 'ethers';
|
|
15
|
+
import 'rxjs';
|
|
16
|
+
import 'lodash-es';
|
|
17
|
+
import 'drizzle-orm/casing';
|
|
18
|
+
import 'eventemitter3';
|
|
19
|
+
import 'arweave';
|
|
711
20
|
|
|
712
21
|
const logger$3 = debug('seedSdk:modelProperty:actors:saveToSchema');
|
|
713
22
|
/**
|
|
@@ -717,11 +26,11 @@ const logger$3 = debug('seedSdk:modelProperty:actors:saveToSchema');
|
|
|
717
26
|
*/
|
|
718
27
|
async function getSchemaNameFromModel(modelName) {
|
|
719
28
|
// Get the latest schema files and find which one contains this model
|
|
720
|
-
const { listLatestSchemaFiles } = await import('./
|
|
29
|
+
const { listLatestSchemaFiles } = await import('./index-DPll6EAp.js').then(function (n) { return n.aU; });
|
|
721
30
|
const latestSchemas = await listLatestSchemaFiles();
|
|
722
31
|
for (const schema of latestSchemas) {
|
|
723
32
|
try {
|
|
724
|
-
const { BaseFileManager } = await import('./
|
|
33
|
+
const { BaseFileManager } = await import('./index-DPll6EAp.js').then(function (n) { return n.aS; });
|
|
725
34
|
const content = await BaseFileManager.readFileAsString(schema.filePath);
|
|
726
35
|
const schemaFile = JSON.parse(content);
|
|
727
36
|
if (schemaFile.models && schemaFile.models[modelName]) {
|
|
@@ -738,7 +47,7 @@ async function getSchemaNameFromModel(modelName) {
|
|
|
738
47
|
const saveToSchema = fromCallback(({ sendBack, input: { context } }) => {
|
|
739
48
|
const _saveToSchema = async () => {
|
|
740
49
|
// Use dynamic import to break circular dependency
|
|
741
|
-
const { SchemaValidationService } = await import('./SchemaValidationService-
|
|
50
|
+
const { SchemaValidationService } = await import('./SchemaValidationService-DyttFaV_.js');
|
|
742
51
|
const validationService = new SchemaValidationService();
|
|
743
52
|
// Validate property structure before saving
|
|
744
53
|
const validationResult = validationService.validatePropertyStructure(context);
|
|
@@ -766,8 +75,7 @@ const saveToSchema = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
766
75
|
await updateModelProperties(schemaName, [propertyUpdate]);
|
|
767
76
|
// Clear isEdited flag in database after saving to schema file
|
|
768
77
|
try {
|
|
769
|
-
const {
|
|
770
|
-
const { properties: propertiesTable, models: modelsTable } = await import('./index-r45w9hEq.js').then(function (n) { return n.s; });
|
|
78
|
+
const { properties: propertiesTable, models: modelsTable } = await import('./index-2FcQHgKp.js').then(function (n) { return n.s; });
|
|
771
79
|
const { eq, and } = await import('drizzle-orm');
|
|
772
80
|
const db = BaseDb.getAppDb();
|
|
773
81
|
if (db && context.modelName && context.name) {
|
|
@@ -811,54 +119,89 @@ const saveToSchema = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
811
119
|
};
|
|
812
120
|
});
|
|
813
121
|
|
|
814
|
-
var saveToSchema$1 = /*#__PURE__*/Object.freeze({
|
|
815
|
-
__proto__: null,
|
|
816
|
-
getSchemaNameFromModel: getSchemaNameFromModel,
|
|
817
|
-
saveToSchema: saveToSchema
|
|
818
|
-
});
|
|
819
|
-
|
|
820
122
|
const logger$2 = debug('seedSdk:modelProperty:actors:compareAndMarkDraft');
|
|
821
123
|
const compareAndMarkDraft = fromCallback(({ sendBack, input: { context } }) => {
|
|
822
124
|
const _compareAndMarkDraft = async () => {
|
|
125
|
+
// Fill modelName/dataType from _originalValues when missing, then from DB by schemaFileId
|
|
126
|
+
let fullContext = {
|
|
127
|
+
...context,
|
|
128
|
+
modelName: context.modelName ?? context._originalValues?.modelName,
|
|
129
|
+
dataType: context.dataType ?? context._originalValues?.dataType,
|
|
130
|
+
};
|
|
131
|
+
const schemaFileIdForResolve = fullContext._propertyFileId || (typeof fullContext.id === 'string' ? fullContext.id : undefined);
|
|
132
|
+
if (schemaFileIdForResolve && (fullContext.modelName === undefined || fullContext.dataType === undefined)) {
|
|
133
|
+
try {
|
|
134
|
+
const { getPropertyModelNameAndDataType, getModelNameByModelId } = await import('./index-DPll6EAp.js').then(function (n) { return n.aT; });
|
|
135
|
+
let fromDb;
|
|
136
|
+
for (let attempt = 0; attempt < 6; attempt++) {
|
|
137
|
+
fromDb = await getPropertyModelNameAndDataType(schemaFileIdForResolve);
|
|
138
|
+
if (fromDb)
|
|
139
|
+
break;
|
|
140
|
+
if (attempt < 5)
|
|
141
|
+
await new Promise((r) => setTimeout(r, 40));
|
|
142
|
+
}
|
|
143
|
+
if (fromDb) {
|
|
144
|
+
fullContext = {
|
|
145
|
+
...fullContext,
|
|
146
|
+
modelName: fullContext.modelName ?? fromDb.modelName,
|
|
147
|
+
dataType: fullContext.dataType ?? fromDb.dataType,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
if (fullContext.modelName === undefined && schemaFileIdForResolve) {
|
|
151
|
+
const mod = await Promise.resolve().then(function () { return ModelProperty$1; });
|
|
152
|
+
const ModelProperty = mod?.ModelProperty ?? mod?.default;
|
|
153
|
+
const pendingModelId = ModelProperty?.getPendingModelId?.(schemaFileIdForResolve);
|
|
154
|
+
if (pendingModelId != null) {
|
|
155
|
+
const modelName = await getModelNameByModelId(pendingModelId);
|
|
156
|
+
if (modelName) {
|
|
157
|
+
fullContext = { ...fullContext, modelName };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// ignore
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const schemaFileId = fullContext._propertyFileId || (typeof fullContext.id === 'string' ? fullContext.id : undefined);
|
|
823
167
|
// If _originalValues is not set, we still need to save to database if the property exists
|
|
824
168
|
// This handles the case where the name is changed before _originalValues is initialized
|
|
825
|
-
if (!
|
|
169
|
+
if (!fullContext._originalValues) {
|
|
826
170
|
logger$2('No original values to compare against');
|
|
827
|
-
logger$2(`[compareAndMarkDraft] Context: modelName=${
|
|
171
|
+
logger$2(`[compareAndMarkDraft] Context: modelName=${fullContext.modelName}, name=${fullContext.name}, id=${fullContext.id}, _propertyFileId=${fullContext._propertyFileId}`);
|
|
828
172
|
// If we have a name and modelName, try to save to database anyway
|
|
829
173
|
// This ensures name changes are persisted even if _originalValues isn't initialized yet
|
|
830
174
|
// We need either schemaFileId (id or _propertyFileId) to find the property in the database
|
|
831
|
-
|
|
832
|
-
if (context.modelName && context.name && schemaFileId) {
|
|
175
|
+
if (fullContext.modelName && fullContext.name && schemaFileId) {
|
|
833
176
|
logger$2(`[compareAndMarkDraft] _originalValues not set, but saving to database anyway for property ${context.modelName}:${context.name} (schemaFileId: ${schemaFileId})`);
|
|
834
177
|
try {
|
|
835
|
-
const { savePropertyToDb } = await import('./
|
|
178
|
+
const { savePropertyToDb } = await import('./index-DPll6EAp.js').then(function (n) { return n.aT; });
|
|
836
179
|
// Ensure _propertyFileId is set for savePropertyToDb to find the property
|
|
837
180
|
const contextWithFileId = {
|
|
838
|
-
...
|
|
181
|
+
...fullContext,
|
|
839
182
|
_propertyFileId: schemaFileId,
|
|
840
183
|
};
|
|
841
184
|
await savePropertyToDb(contextWithFileId);
|
|
842
|
-
logger$2(`[compareAndMarkDraft] Successfully saved property ${
|
|
185
|
+
logger$2(`[compareAndMarkDraft] Successfully saved property ${fullContext.modelName}:${fullContext.name} to database (no _originalValues)`);
|
|
843
186
|
}
|
|
844
187
|
catch (error) {
|
|
845
188
|
logger$2(`[compareAndMarkDraft] Error saving property to database (no _originalValues): ${error}`);
|
|
846
189
|
// Don't throw - this is a best-effort save, but log the error for debugging
|
|
847
|
-
console.error(`[compareAndMarkDraft] Failed to save property ${
|
|
190
|
+
console.error(`[compareAndMarkDraft] Failed to save property ${fullContext.modelName}:${fullContext.name}:`, error);
|
|
848
191
|
}
|
|
849
192
|
}
|
|
850
193
|
else {
|
|
851
|
-
logger$2(`[compareAndMarkDraft] Cannot save property ${
|
|
194
|
+
logger$2(`[compareAndMarkDraft] Cannot save property ${fullContext.modelName}:${fullContext.name} - missing required fields (schemaFileId: ${schemaFileId})`);
|
|
852
195
|
}
|
|
853
196
|
return;
|
|
854
197
|
}
|
|
855
|
-
logger$2(`[compareAndMarkDraft] Comparing: context.name=${
|
|
198
|
+
logger$2(`[compareAndMarkDraft] Comparing: context.name=${fullContext.name}, _originalValues.name=${fullContext._originalValues?.name}`);
|
|
856
199
|
// Compare current values with original
|
|
857
200
|
// Only compare property fields, not internal fields
|
|
858
201
|
const propertyFields = ['name', 'dataType', 'ref', 'refModelName', 'refModelId', 'refValueType', 'storageType', 'localStorageDir', 'filenameSuffix', 'modelName', 'modelId'];
|
|
859
202
|
const hasChanges = propertyFields.some(key => {
|
|
860
|
-
const currentValue =
|
|
861
|
-
const originalValue =
|
|
203
|
+
const currentValue = fullContext[key];
|
|
204
|
+
const originalValue = fullContext._originalValues?.[key];
|
|
862
205
|
// Handle name changes specifically
|
|
863
206
|
if (key === 'name') {
|
|
864
207
|
const nameChanged = currentValue !== originalValue;
|
|
@@ -869,8 +212,8 @@ const compareAndMarkDraft = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
869
212
|
}
|
|
870
213
|
// Handle ref fields - compare by name
|
|
871
214
|
if (key === 'ref' || key === 'refModelName') {
|
|
872
|
-
const currentRef =
|
|
873
|
-
const originalRef =
|
|
215
|
+
const currentRef = fullContext.refModelName || fullContext.ref;
|
|
216
|
+
const originalRef = fullContext._originalValues?.refModelName || fullContext._originalValues?.ref;
|
|
874
217
|
// Both undefined/null means no ref, so they're the same
|
|
875
218
|
if (!currentRef && !originalRef)
|
|
876
219
|
return false;
|
|
@@ -888,53 +231,54 @@ const compareAndMarkDraft = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
888
231
|
return currentValue !== originalValue;
|
|
889
232
|
});
|
|
890
233
|
if (hasChanges) {
|
|
891
|
-
logger$2(`Property ${
|
|
892
|
-
logger$2(`[compareAndMarkDraft] Context when saving: id=${
|
|
234
|
+
logger$2(`Property ${fullContext.modelName}:${fullContext.name} has changes, marking as edited`);
|
|
235
|
+
logger$2(`[compareAndMarkDraft] Context when saving: id=${fullContext.id}, _propertyFileId=${fullContext._propertyFileId}, name=${fullContext.name}, _originalValues.name=${fullContext._originalValues?.name}`);
|
|
893
236
|
// Use dynamic import to break circular dependency
|
|
894
|
-
const { savePropertyToDb } = await import('./
|
|
237
|
+
const { savePropertyToDb } = await import('./index-DPll6EAp.js').then(function (n) { return n.aT; });
|
|
895
238
|
// Save to database (but not JSON file) - always save to DB when there are changes
|
|
896
239
|
try {
|
|
897
|
-
await savePropertyToDb(
|
|
898
|
-
logger$2(`[compareAndMarkDraft] Successfully saved property ${
|
|
240
|
+
await savePropertyToDb(fullContext);
|
|
241
|
+
logger$2(`[compareAndMarkDraft] Successfully saved property ${fullContext.modelName}:${fullContext.name} to database`);
|
|
899
242
|
}
|
|
900
243
|
catch (error) {
|
|
901
244
|
logger$2(`[compareAndMarkDraft] Error saving property to database: ${error}`);
|
|
902
245
|
throw error;
|
|
903
246
|
}
|
|
904
247
|
// Mark schema as draft if schema name is available
|
|
905
|
-
if (
|
|
248
|
+
if (fullContext._schemaName) {
|
|
906
249
|
// Get the Schema instance and mark it as draft
|
|
907
|
-
const { Schema } = await import('./Schema-
|
|
908
|
-
const schema = Schema.create(
|
|
250
|
+
const { Schema } = await import('./Schema-D1eqDHyt.js').then(function (n) { return n.b; });
|
|
251
|
+
const schema = Schema.create(fullContext._schemaName, {
|
|
252
|
+
waitForReady: false,
|
|
253
|
+
});
|
|
909
254
|
// Send event to Schema machine to mark as draft
|
|
910
255
|
schema.getService().send({
|
|
911
256
|
type: 'markAsDraft',
|
|
912
|
-
propertyKey: `${
|
|
257
|
+
propertyKey: `${fullContext.modelName}:${fullContext.name}`,
|
|
913
258
|
});
|
|
914
259
|
}
|
|
915
260
|
}
|
|
916
261
|
else {
|
|
917
262
|
// No changes - clear edited flag in database and context
|
|
918
|
-
logger$2(`Property ${
|
|
263
|
+
logger$2(`Property ${fullContext.modelName}:${fullContext.name} has no changes`);
|
|
919
264
|
// Clear isEdited flag in database
|
|
920
265
|
try {
|
|
921
|
-
const {
|
|
922
|
-
const { properties: propertiesTable, models: modelsTable } = await import('./index-r45w9hEq.js').then(function (n) { return n.s; });
|
|
266
|
+
const { properties: propertiesTable, models: modelsTable } = await import('./index-2FcQHgKp.js').then(function (n) { return n.s; });
|
|
923
267
|
const { eq, and } = await import('drizzle-orm');
|
|
924
268
|
const db = BaseDb.getAppDb();
|
|
925
|
-
if (db &&
|
|
269
|
+
if (db && fullContext.modelName && fullContext.name) {
|
|
926
270
|
// Find model by name
|
|
927
271
|
const modelRecords = await db
|
|
928
272
|
.select({ id: modelsTable.id })
|
|
929
273
|
.from(modelsTable)
|
|
930
|
-
.where(eq(modelsTable.name,
|
|
274
|
+
.where(eq(modelsTable.name, fullContext.modelName))
|
|
931
275
|
.limit(1);
|
|
932
276
|
if (modelRecords.length > 0) {
|
|
933
277
|
// Find property by name and modelId
|
|
934
278
|
const propertyRecords = await db
|
|
935
279
|
.select({ id: propertiesTable.id })
|
|
936
280
|
.from(propertiesTable)
|
|
937
|
-
.where(and(eq(propertiesTable.name,
|
|
281
|
+
.where(and(eq(propertiesTable.name, fullContext.name), eq(propertiesTable.modelId, modelRecords[0].id)))
|
|
938
282
|
.limit(1);
|
|
939
283
|
if (propertyRecords.length > 0) {
|
|
940
284
|
// Clear isEdited flag in database
|
|
@@ -942,7 +286,7 @@ const compareAndMarkDraft = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
942
286
|
.update(propertiesTable)
|
|
943
287
|
.set({ isEdited: false })
|
|
944
288
|
.where(eq(propertiesTable.id, propertyRecords[0].id));
|
|
945
|
-
logger$2(`Cleared isEdited flag in database for property ${
|
|
289
|
+
logger$2(`Cleared isEdited flag in database for property ${fullContext.modelName}:${fullContext.name}`);
|
|
946
290
|
}
|
|
947
291
|
}
|
|
948
292
|
}
|
|
@@ -969,20 +313,82 @@ const compareAndMarkDraft = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
969
313
|
const logger$1 = debug('seedSdk:modelProperty:actors:validateProperty');
|
|
970
314
|
const validateProperty = fromCallback(({ sendBack, input: { context } }) => {
|
|
971
315
|
const _validateProperty = async () => {
|
|
972
|
-
|
|
316
|
+
// Use full context for validation: fill modelName/dataType from _originalValues when missing, then
|
|
317
|
+
// from DB by schemaFileId (context.id) so just-created renames don't fail structure validation.
|
|
318
|
+
let fullContext = {
|
|
319
|
+
...context,
|
|
320
|
+
modelName: context.modelName ?? context._originalValues?.modelName,
|
|
321
|
+
dataType: context.dataType ?? context._originalValues?.dataType,
|
|
322
|
+
};
|
|
323
|
+
const schemaFileId = typeof context.id === 'string' ? context.id : undefined;
|
|
324
|
+
if (schemaFileId && (fullContext.modelName === undefined || fullContext.dataType === undefined)) {
|
|
325
|
+
// Brief wait so trackPendingWrite from ModelProperty.create() has time to run (it's in setTimeout(0))
|
|
326
|
+
await new Promise((r) => setTimeout(r, 60));
|
|
327
|
+
try {
|
|
328
|
+
const { getPropertyModelNameAndDataType, getModelNameByModelId } = await import('./index-DPll6EAp.js').then(function (n) { return n.aT; });
|
|
329
|
+
// Try pending write first (property row may not exist yet)
|
|
330
|
+
if (fullContext.modelName === undefined && schemaFileId) {
|
|
331
|
+
const mod = await Promise.resolve().then(function () { return ModelProperty$1; });
|
|
332
|
+
const ModelProperty = mod?.ModelProperty ?? mod?.default;
|
|
333
|
+
const pendingModelId = ModelProperty?.getPendingModelId?.(schemaFileId);
|
|
334
|
+
if (pendingModelId != null) {
|
|
335
|
+
const modelName = await getModelNameByModelId(pendingModelId);
|
|
336
|
+
if (modelName) {
|
|
337
|
+
fullContext = { ...fullContext, modelName };
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
// Then DB property lookup with retry (catches row after initial write)
|
|
342
|
+
let fromDb;
|
|
343
|
+
for (let attempt = 0; attempt < 6; attempt++) {
|
|
344
|
+
fromDb = await getPropertyModelNameAndDataType(schemaFileId);
|
|
345
|
+
if (fromDb)
|
|
346
|
+
break;
|
|
347
|
+
if (attempt < 5)
|
|
348
|
+
await new Promise((r) => setTimeout(r, 40));
|
|
349
|
+
}
|
|
350
|
+
if (fromDb) {
|
|
351
|
+
fullContext = {
|
|
352
|
+
...fullContext,
|
|
353
|
+
modelName: fullContext.modelName ?? fromDb.modelName,
|
|
354
|
+
dataType: fullContext.dataType ?? fromDb.dataType,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
// If still no modelName, try pending write again (may have been set during retries)
|
|
358
|
+
if (fullContext.modelName === undefined && schemaFileId) {
|
|
359
|
+
const mod = await Promise.resolve().then(function () { return ModelProperty$1; });
|
|
360
|
+
const ModelProperty = mod?.ModelProperty ?? mod?.default;
|
|
361
|
+
const pendingModelId = ModelProperty?.getPendingModelId?.(schemaFileId);
|
|
362
|
+
if (pendingModelId != null) {
|
|
363
|
+
const modelName = await getModelNameByModelId(pendingModelId);
|
|
364
|
+
if (modelName) {
|
|
365
|
+
fullContext = { ...fullContext, modelName };
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
catch {
|
|
371
|
+
// ignore
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// Last resort for structure validation: TProperty requires dataType; allow name+id to pass if we have schemaFileId
|
|
375
|
+
if (fullContext.dataType === undefined && (fullContext.modelName !== undefined || schemaFileId)) {
|
|
376
|
+
fullContext = { ...fullContext, dataType: (fullContext.dataType ?? context._originalValues?.dataType) || 'Text' };
|
|
377
|
+
}
|
|
378
|
+
console.log('[validateProperty] Starting validation for property:', fullContext.name);
|
|
973
379
|
console.log('[validateProperty] Context:', {
|
|
974
|
-
name:
|
|
975
|
-
modelName:
|
|
976
|
-
_schemaName:
|
|
977
|
-
_originalValues:
|
|
380
|
+
name: fullContext.name,
|
|
381
|
+
modelName: fullContext.modelName,
|
|
382
|
+
_schemaName: fullContext._schemaName,
|
|
383
|
+
_originalValues: fullContext._originalValues
|
|
978
384
|
});
|
|
979
385
|
// Use dynamic imports to break circular dependencies
|
|
980
|
-
const { SchemaValidationService } = await import('./SchemaValidationService-
|
|
386
|
+
const { SchemaValidationService } = await import('./SchemaValidationService-DyttFaV_.js');
|
|
981
387
|
const validationService = new SchemaValidationService();
|
|
982
|
-
const { Schema } = await import('./Schema-
|
|
388
|
+
const { Schema } = await import('./Schema-D1eqDHyt.js').then(function (n) { return n.b; });
|
|
983
389
|
// Validate property structure
|
|
984
390
|
console.log('[validateProperty] Validating property structure...');
|
|
985
|
-
const structureResult = validationService.validatePropertyStructure(
|
|
391
|
+
const structureResult = validationService.validatePropertyStructure(fullContext);
|
|
986
392
|
console.log('[validateProperty] Structure validation result:', structureResult.isValid);
|
|
987
393
|
if (!structureResult.isValid) {
|
|
988
394
|
console.log('[validateProperty] Structure validation failed:', structureResult.errors);
|
|
@@ -991,11 +397,13 @@ const validateProperty = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
991
397
|
}
|
|
992
398
|
console.log('[validateProperty] Structure validation passed');
|
|
993
399
|
// If we have schema name and model name, validate against schema
|
|
994
|
-
console.log('[validateProperty] Checking schema validation:', { hasSchemaName: !!
|
|
995
|
-
if (
|
|
400
|
+
console.log('[validateProperty] Checking schema validation:', { hasSchemaName: !!fullContext._schemaName, hasModelName: !!fullContext.modelName });
|
|
401
|
+
if (fullContext._schemaName && fullContext.modelName) {
|
|
996
402
|
try {
|
|
997
|
-
console.log('[validateProperty] Creating schema instance:',
|
|
998
|
-
const schema = Schema.create(
|
|
403
|
+
console.log('[validateProperty] Creating schema instance:', fullContext._schemaName);
|
|
404
|
+
const schema = Schema.create(fullContext._schemaName, {
|
|
405
|
+
waitForReady: false,
|
|
406
|
+
});
|
|
999
407
|
const schemaSnapshot = schema.getService().getSnapshot();
|
|
1000
408
|
const schemaStatus = schemaSnapshot.value;
|
|
1001
409
|
console.log('[validateProperty] Schema status:', schemaStatus);
|
|
@@ -1008,28 +416,28 @@ const validateProperty = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
1008
416
|
if (schemaContext.models && Object.keys(schemaContext.models).length > 0) {
|
|
1009
417
|
// If property name has changed, validate against the original name (from schema file)
|
|
1010
418
|
// This handles the case where a property is renamed - the schema file still has the old name
|
|
1011
|
-
const propertyNameToValidate =
|
|
1012
|
-
?
|
|
1013
|
-
:
|
|
419
|
+
const propertyNameToValidate = fullContext._originalValues?.name && fullContext._originalValues.name !== fullContext.name
|
|
420
|
+
? fullContext._originalValues.name
|
|
421
|
+
: fullContext.name || '';
|
|
1014
422
|
console.log('[validateProperty] Validating against schema:', {
|
|
1015
|
-
modelName:
|
|
423
|
+
modelName: fullContext.modelName,
|
|
1016
424
|
propertyNameToValidate,
|
|
1017
|
-
originalName:
|
|
1018
|
-
currentName:
|
|
425
|
+
originalName: fullContext._originalValues?.name,
|
|
426
|
+
currentName: fullContext.name
|
|
1019
427
|
});
|
|
1020
|
-
const schemaResult = validationService.validateProperty(schemaContext,
|
|
428
|
+
const schemaResult = validationService.validateProperty(schemaContext, fullContext.modelName, propertyNameToValidate, fullContext);
|
|
1021
429
|
console.log('[validateProperty] Schema validation result:', { isValid: schemaResult.isValid, errors: schemaResult.errors.length, errorCodes: schemaResult.errors.map(e => e.code) });
|
|
1022
430
|
if (!schemaResult.isValid) {
|
|
1023
431
|
// If property was renamed, some validation errors are expected (like property_not_found, missing_type)
|
|
1024
432
|
// Only fail if it's a critical error that's not related to the rename
|
|
1025
|
-
const isRenamed =
|
|
433
|
+
const isRenamed = fullContext._originalValues?.name && fullContext._originalValues.name !== fullContext.name;
|
|
1026
434
|
const criticalErrors = schemaResult.errors.filter(err => {
|
|
1027
435
|
// Allow property_not_found and missing_type errors when property is renamed
|
|
1028
436
|
if (isRenamed && (err.code === 'property_not_found' || err.code === 'missing_type')) {
|
|
1029
437
|
return false; // Not critical
|
|
1030
438
|
}
|
|
1031
439
|
// For non-renamed properties, only allow property_not_found if we're validating with the same name
|
|
1032
|
-
if (err.code === 'property_not_found' && propertyNameToValidate ===
|
|
440
|
+
if (err.code === 'property_not_found' && propertyNameToValidate === fullContext.name) {
|
|
1033
441
|
return false; // Not critical
|
|
1034
442
|
}
|
|
1035
443
|
return true; // Critical error
|
|
@@ -1163,6 +571,15 @@ const modelPropertyMachine = setup({
|
|
|
1163
571
|
}
|
|
1164
572
|
newContext[key] = value;
|
|
1165
573
|
}
|
|
574
|
+
// Preserve modelName and dataType from context or _originalValues so validation and savePropertyToDb
|
|
575
|
+
// never run with missing required/needed fields (e.g. when a just-created property is renamed before
|
|
576
|
+
// the full context is available from the creator).
|
|
577
|
+
if (newContext.modelName === undefined && context._originalValues?.modelName !== undefined) {
|
|
578
|
+
newContext.modelName = context._originalValues.modelName;
|
|
579
|
+
}
|
|
580
|
+
if (newContext.dataType === undefined && context._originalValues?.dataType !== undefined) {
|
|
581
|
+
newContext.dataType = context._originalValues.dataType;
|
|
582
|
+
}
|
|
1166
583
|
// Compare with original values and set _isEdited flag (only for non-internal updates)
|
|
1167
584
|
if (!onlyInternalFields && context._originalValues) {
|
|
1168
585
|
const hasChanges = Object.keys(event).some((key) => {
|
|
@@ -1232,6 +649,23 @@ const modelPropertyMachine = setup({
|
|
|
1232
649
|
_schemaName: event.schemaName,
|
|
1233
650
|
})),
|
|
1234
651
|
},
|
|
652
|
+
destroyStarted: {
|
|
653
|
+
actions: assign({ _destroyInProgress: true, _destroyError: null }),
|
|
654
|
+
},
|
|
655
|
+
destroyDone: {
|
|
656
|
+
actions: assign({ _destroyInProgress: false }),
|
|
657
|
+
},
|
|
658
|
+
destroyError: {
|
|
659
|
+
actions: assign(({ event }) => ({
|
|
660
|
+
_destroyInProgress: false,
|
|
661
|
+
_destroyError: event.error instanceof Error
|
|
662
|
+
? { message: event.error.message, name: event.error.name }
|
|
663
|
+
: { message: String(event.error) },
|
|
664
|
+
})),
|
|
665
|
+
},
|
|
666
|
+
clearDestroyError: {
|
|
667
|
+
actions: assign({ _destroyError: null }),
|
|
668
|
+
},
|
|
1235
669
|
},
|
|
1236
670
|
states: {
|
|
1237
671
|
idle: {
|
|
@@ -1357,6 +791,32 @@ const modelPropertyMachine = setup({
|
|
|
1357
791
|
},
|
|
1358
792
|
});
|
|
1359
793
|
|
|
794
|
+
/**
|
|
795
|
+
* Returns property rows for a model identified by modelFileId (model's schemaFileId).
|
|
796
|
+
* Resolves modelFileId -> modelId via models table, then selects all properties where modelId = ?.
|
|
797
|
+
* Each row includes schemaFileId for use with ModelProperty.createById(schemaFileId).
|
|
798
|
+
*/
|
|
799
|
+
const getModelPropertiesData = async (modelFileId) => {
|
|
800
|
+
const appDb = BaseDb.getAppDb();
|
|
801
|
+
if (!appDb || !modelFileId) {
|
|
802
|
+
return [];
|
|
803
|
+
}
|
|
804
|
+
const modelRows = await appDb
|
|
805
|
+
.select({ id: models.id })
|
|
806
|
+
.from(models)
|
|
807
|
+
.where(eq(models.schemaFileId, modelFileId))
|
|
808
|
+
.limit(1);
|
|
809
|
+
if (modelRows.length === 0) {
|
|
810
|
+
return [];
|
|
811
|
+
}
|
|
812
|
+
const modelId = modelRows[0].id;
|
|
813
|
+
const rows = await appDb
|
|
814
|
+
.select()
|
|
815
|
+
.from(properties)
|
|
816
|
+
.where(eq(properties.modelId, modelId));
|
|
817
|
+
return rows;
|
|
818
|
+
};
|
|
819
|
+
|
|
1360
820
|
const logger = debug('seedSdk:modelProperty:ModelProperty');
|
|
1361
821
|
// Define the property keys from TProperty
|
|
1362
822
|
const TPropertyKeys = [
|
|
@@ -1523,27 +983,24 @@ class ModelProperty {
|
|
|
1523
983
|
return fallbackIsEdited;
|
|
1524
984
|
}
|
|
1525
985
|
try {
|
|
1526
|
-
const { BaseDb } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aI; });
|
|
1527
|
-
const { properties: propertiesTable, models: modelsTable } = await import('./index-r45w9hEq.js').then(function (n) { return n.s; });
|
|
1528
|
-
const { eq, and } = await import('drizzle-orm');
|
|
1529
986
|
const db = BaseDb.getAppDb();
|
|
1530
987
|
if (!db) {
|
|
1531
988
|
return fallbackIsEdited;
|
|
1532
989
|
}
|
|
1533
990
|
// Find model by name
|
|
1534
991
|
const modelRecords = await db
|
|
1535
|
-
.select({ id:
|
|
1536
|
-
.from(
|
|
1537
|
-
.where(eq(
|
|
992
|
+
.select({ id: models.id })
|
|
993
|
+
.from(models)
|
|
994
|
+
.where(eq(models.name, property.modelName))
|
|
1538
995
|
.limit(1);
|
|
1539
996
|
if (modelRecords.length === 0) {
|
|
1540
997
|
return fallbackIsEdited;
|
|
1541
998
|
}
|
|
1542
999
|
// Find property by name and modelId
|
|
1543
1000
|
const propertyRecords = await db
|
|
1544
|
-
.select({ isEdited:
|
|
1545
|
-
.from(
|
|
1546
|
-
.where(and(eq(
|
|
1001
|
+
.select({ isEdited: properties.isEdited })
|
|
1002
|
+
.from(properties)
|
|
1003
|
+
.where(and(eq(properties.name, property.name), eq(properties.modelId, modelRecords[0].id)))
|
|
1547
1004
|
.limit(1);
|
|
1548
1005
|
if (propertyRecords.length > 0) {
|
|
1549
1006
|
return propertyRecords[0].isEdited ?? false;
|
|
@@ -1564,18 +1021,14 @@ class ModelProperty {
|
|
|
1564
1021
|
return undefined;
|
|
1565
1022
|
}
|
|
1566
1023
|
try {
|
|
1567
|
-
const { BaseDb } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aI; });
|
|
1568
|
-
const seedSchema = await import('./index-r45w9hEq.js').then(function (n) { return n.s; });
|
|
1569
|
-
const modelsTable = seedSchema.models;
|
|
1570
|
-
const { eq } = await import('drizzle-orm');
|
|
1571
1024
|
const db = BaseDb.getAppDb();
|
|
1572
1025
|
if (!db) {
|
|
1573
1026
|
return undefined;
|
|
1574
1027
|
}
|
|
1575
1028
|
const refModelRecords = await db
|
|
1576
1029
|
.select()
|
|
1577
|
-
.from(
|
|
1578
|
-
.where(eq(
|
|
1030
|
+
.from(models)
|
|
1031
|
+
.where(eq(models.name, refModelName))
|
|
1579
1032
|
.limit(1);
|
|
1580
1033
|
if (refModelRecords.length > 0 && refModelRecords[0].id) {
|
|
1581
1034
|
return refModelRecords[0].id;
|
|
@@ -1596,8 +1049,6 @@ class ModelProperty {
|
|
|
1596
1049
|
return undefined;
|
|
1597
1050
|
}
|
|
1598
1051
|
try {
|
|
1599
|
-
const { Model } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aS; });
|
|
1600
|
-
const { modelPropertiesToObject } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aP; });
|
|
1601
1052
|
const model = await Model.getByNameAsync(property.modelName);
|
|
1602
1053
|
if (!model || !model.properties || model.properties.length === 0) {
|
|
1603
1054
|
return undefined;
|
|
@@ -1646,12 +1097,6 @@ class ModelProperty {
|
|
|
1646
1097
|
// Try to get schema name from database first (more reliable)
|
|
1647
1098
|
if (this.modelId) {
|
|
1648
1099
|
try {
|
|
1649
|
-
const { BaseDb } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aI; });
|
|
1650
|
-
const seedSchema = await import('./index-r45w9hEq.js').then(function (n) { return n.s; });
|
|
1651
|
-
const modelsTable = seedSchema.models;
|
|
1652
|
-
const modelSchemas = seedSchema.modelSchemas;
|
|
1653
|
-
const schemas = seedSchema.schemas;
|
|
1654
|
-
const { eq } = await import('drizzle-orm');
|
|
1655
1100
|
const db = BaseDb.getAppDb();
|
|
1656
1101
|
if (db) {
|
|
1657
1102
|
const modelSchemaRecords = await db
|
|
@@ -1660,8 +1105,8 @@ class ModelProperty {
|
|
|
1660
1105
|
})
|
|
1661
1106
|
.from(modelSchemas)
|
|
1662
1107
|
.innerJoin(schemas, eq(modelSchemas.schemaId, schemas.id))
|
|
1663
|
-
.innerJoin(
|
|
1664
|
-
.where(eq(
|
|
1108
|
+
.innerJoin(models, eq(modelSchemas.modelId, models.id))
|
|
1109
|
+
.where(eq(models.id, this.modelId))
|
|
1665
1110
|
.limit(1);
|
|
1666
1111
|
if (modelSchemaRecords.length > 0) {
|
|
1667
1112
|
schemaName = modelSchemaRecords[0].schemaName;
|
|
@@ -1674,7 +1119,6 @@ class ModelProperty {
|
|
|
1674
1119
|
}
|
|
1675
1120
|
// Fall back to schema file lookup if database didn't work
|
|
1676
1121
|
if (!schemaName) {
|
|
1677
|
-
const { getSchemaNameFromModel } = await Promise.resolve().then(function () { return saveToSchema$1; });
|
|
1678
1122
|
schemaName = await getSchemaNameFromModel(modelName);
|
|
1679
1123
|
}
|
|
1680
1124
|
if (schemaName) {
|
|
@@ -1699,10 +1143,12 @@ class ModelProperty {
|
|
|
1699
1143
|
schemaName,
|
|
1700
1144
|
});
|
|
1701
1145
|
}
|
|
1702
|
-
static create(property) {
|
|
1146
|
+
static create(property, options) {
|
|
1703
1147
|
if (!property) {
|
|
1704
1148
|
throw new Error('Property is required');
|
|
1705
1149
|
}
|
|
1150
|
+
const waitForReady = options?.waitForReady !== false;
|
|
1151
|
+
const readyTimeout = options?.readyTimeout ?? 5000;
|
|
1706
1152
|
// Debug: Log what's being passed to create()
|
|
1707
1153
|
console.log(`[ModelProperty.create] Input property data:`, JSON.stringify({
|
|
1708
1154
|
name: property.name,
|
|
@@ -1776,7 +1222,9 @@ class ModelProperty {
|
|
|
1776
1222
|
instance,
|
|
1777
1223
|
refCount: refCount + 1,
|
|
1778
1224
|
});
|
|
1779
|
-
|
|
1225
|
+
if (!waitForReady)
|
|
1226
|
+
return instance;
|
|
1227
|
+
return waitForEntityIdle(instance, { timeout: readyTimeout }).then(() => instance);
|
|
1780
1228
|
}
|
|
1781
1229
|
// Debug: Log what's being passed to the constructor
|
|
1782
1230
|
console.log(`[ModelProperty.create] propertyWithId before constructor:`, JSON.stringify({
|
|
@@ -1851,7 +1299,6 @@ class ModelProperty {
|
|
|
1851
1299
|
else if (typeof propertyWithId.modelId === 'string') {
|
|
1852
1300
|
// modelId is a string (modelFileId), need to convert to database ID
|
|
1853
1301
|
try {
|
|
1854
|
-
const { getModelIdByFileId } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aR; });
|
|
1855
1302
|
resolvedModelId = await getModelIdByFileId(propertyWithId.modelId);
|
|
1856
1303
|
logger(`Converted modelFileId "${propertyWithId.modelId}" to database modelId: ${resolvedModelId}`);
|
|
1857
1304
|
}
|
|
@@ -1864,7 +1311,6 @@ class ModelProperty {
|
|
|
1864
1311
|
// If we still don't have a modelId, try to resolve it from modelName
|
|
1865
1312
|
if (!resolvedModelId && propertyWithId.modelName) {
|
|
1866
1313
|
try {
|
|
1867
|
-
const { getModelId } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aR; });
|
|
1868
1314
|
// Get schemaName from context if available
|
|
1869
1315
|
const schemaName = snapshot.context._schemaName;
|
|
1870
1316
|
resolvedModelId = await getModelId(propertyWithId.modelName, schemaName);
|
|
@@ -1938,7 +1384,9 @@ class ModelProperty {
|
|
|
1938
1384
|
// Start checking after a short delay to allow state machine to initialize
|
|
1939
1385
|
setTimeout(checkAndSend, 0);
|
|
1940
1386
|
}
|
|
1941
|
-
|
|
1387
|
+
if (!waitForReady)
|
|
1388
|
+
return proxiedInstance;
|
|
1389
|
+
return waitForEntityIdle(proxiedInstance, { timeout: readyTimeout }).then(() => proxiedInstance);
|
|
1942
1390
|
}
|
|
1943
1391
|
/**
|
|
1944
1392
|
* Get ModelProperty instance by propertyFileId from static cache
|
|
@@ -1971,9 +1419,6 @@ class ModelProperty {
|
|
|
1971
1419
|
return cachedInstance;
|
|
1972
1420
|
}
|
|
1973
1421
|
// Query database to get property data from ID
|
|
1974
|
-
const { BaseDb } = await import('./json-I3vJhXo8.js').then(function (n) { return n.aI; });
|
|
1975
|
-
const { properties: propertiesTable, models: modelsTable } = await import('./index-r45w9hEq.js').then(function (n) { return n.s; });
|
|
1976
|
-
const { eq } = await import('drizzle-orm');
|
|
1977
1422
|
const db = BaseDb.getAppDb();
|
|
1978
1423
|
console.log('db', !!db);
|
|
1979
1424
|
if (!db) {
|
|
@@ -1982,13 +1427,13 @@ class ModelProperty {
|
|
|
1982
1427
|
}
|
|
1983
1428
|
const testRecords = await db
|
|
1984
1429
|
.select()
|
|
1985
|
-
.from(
|
|
1430
|
+
.from(properties)
|
|
1986
1431
|
.limit(100);
|
|
1987
1432
|
console.log('testRecords', testRecords);
|
|
1988
1433
|
const propertyRecords = await db
|
|
1989
1434
|
.select()
|
|
1990
|
-
.from(
|
|
1991
|
-
.where(eq(
|
|
1435
|
+
.from(properties)
|
|
1436
|
+
.where(eq(properties.schemaFileId, propertyFileId))
|
|
1992
1437
|
.limit(1);
|
|
1993
1438
|
console.log('propertyRecords', propertyRecords);
|
|
1994
1439
|
if (propertyRecords.length === 0) {
|
|
@@ -1997,9 +1442,9 @@ class ModelProperty {
|
|
|
1997
1442
|
const propertyRecord = propertyRecords[0];
|
|
1998
1443
|
// Get model name
|
|
1999
1444
|
const modelRecords = await db
|
|
2000
|
-
.select({ name:
|
|
2001
|
-
.from(
|
|
2002
|
-
.where(eq(
|
|
1445
|
+
.select({ name: models.name })
|
|
1446
|
+
.from(models)
|
|
1447
|
+
.where(eq(models.id, propertyRecord.modelId))
|
|
2003
1448
|
.limit(1);
|
|
2004
1449
|
if (modelRecords.length === 0) {
|
|
2005
1450
|
return undefined;
|
|
@@ -2022,17 +1467,17 @@ class ModelProperty {
|
|
|
2022
1467
|
// Get ref model name if applicable
|
|
2023
1468
|
if (propertyRecord.refModelId) {
|
|
2024
1469
|
const refModelRecords = await db
|
|
2025
|
-
.select({ name:
|
|
2026
|
-
.from(
|
|
2027
|
-
.where(eq(
|
|
1470
|
+
.select({ name: models.name })
|
|
1471
|
+
.from(models)
|
|
1472
|
+
.where(eq(models.id, propertyRecord.refModelId))
|
|
2028
1473
|
.limit(1);
|
|
2029
1474
|
if (refModelRecords.length > 0) {
|
|
2030
1475
|
propertyData.refModelName = refModelRecords[0].name;
|
|
2031
1476
|
propertyData.ref = refModelRecords[0].name;
|
|
2032
1477
|
}
|
|
2033
1478
|
}
|
|
2034
|
-
// Create ModelProperty instance
|
|
2035
|
-
const instance = this.create(propertyData);
|
|
1479
|
+
// Create ModelProperty instance (sync for createById so we can send updateContext)
|
|
1480
|
+
const instance = this.create(propertyData, { waitForReady: false });
|
|
2036
1481
|
// Set isEdited from database after creation
|
|
2037
1482
|
if (isEditedFromDb) {
|
|
2038
1483
|
instance._service.send({
|
|
@@ -2060,6 +1505,32 @@ class ModelProperty {
|
|
|
2060
1505
|
readyTimeout,
|
|
2061
1506
|
});
|
|
2062
1507
|
}
|
|
1508
|
+
/**
|
|
1509
|
+
* Get all ModelProperty instances for a model.
|
|
1510
|
+
* Loads property rows from DB for the given modelFileId, creates instances via createById, optionally waits for idle.
|
|
1511
|
+
*/
|
|
1512
|
+
static async all(modelFileId, options) {
|
|
1513
|
+
const { waitForReady = false, readyTimeout = 5000 } = options ?? {};
|
|
1514
|
+
if (!modelFileId) {
|
|
1515
|
+
return [];
|
|
1516
|
+
}
|
|
1517
|
+
const rows = await getModelPropertiesData(modelFileId);
|
|
1518
|
+
const instances = [];
|
|
1519
|
+
for (const row of rows) {
|
|
1520
|
+
if (row.schemaFileId) {
|
|
1521
|
+
const instance = await this.createById(row.schemaFileId);
|
|
1522
|
+
if (instance) {
|
|
1523
|
+
instances.push(instance);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
if (waitForReady && instances.length > 0) {
|
|
1528
|
+
await Promise.all(instances.map((p) => waitForEntityIdle(p, {
|
|
1529
|
+
timeout: readyTimeout,
|
|
1530
|
+
})));
|
|
1531
|
+
}
|
|
1532
|
+
return instances;
|
|
1533
|
+
}
|
|
2063
1534
|
/**
|
|
2064
1535
|
* Track a pending write for a property
|
|
2065
1536
|
*/
|
|
@@ -2098,6 +1569,13 @@ class ModelProperty {
|
|
|
2098
1569
|
.filter(([_, write]) => write.modelId === modelId && write.status !== 'error')
|
|
2099
1570
|
.map(([propertyFileId]) => propertyFileId);
|
|
2100
1571
|
}
|
|
1572
|
+
/**
|
|
1573
|
+
* Get modelId for a property that has a pending write (row may not be in DB yet).
|
|
1574
|
+
* Used to resolve modelName when validating a just-created property rename.
|
|
1575
|
+
*/
|
|
1576
|
+
static getPendingModelId(propertyFileId) {
|
|
1577
|
+
return this.pendingWrites.get(propertyFileId)?.modelId;
|
|
1578
|
+
}
|
|
2101
1579
|
getService() {
|
|
2102
1580
|
return this._service;
|
|
2103
1581
|
}
|
|
@@ -2204,6 +1682,60 @@ class ModelProperty {
|
|
|
2204
1682
|
// Service might already be stopped
|
|
2205
1683
|
}
|
|
2206
1684
|
}
|
|
1685
|
+
/**
|
|
1686
|
+
* Destroy the model property: remove from caches, delete from database, update Schema context, stop service.
|
|
1687
|
+
*/
|
|
1688
|
+
async destroy() {
|
|
1689
|
+
const context = this._getSnapshotContext();
|
|
1690
|
+
const cacheKey = context.modelName && context.name
|
|
1691
|
+
? `${context.modelName}:${context.name}`
|
|
1692
|
+
: (context.id ?? '');
|
|
1693
|
+
if (!cacheKey)
|
|
1694
|
+
return;
|
|
1695
|
+
forceRemoveFromCaches(this, {
|
|
1696
|
+
getCacheKeys: () => [cacheKey],
|
|
1697
|
+
caches: [ModelProperty.instanceCache],
|
|
1698
|
+
});
|
|
1699
|
+
await runDestroyLifecycle(this, {
|
|
1700
|
+
getService: (instance) => instance._service,
|
|
1701
|
+
doDestroy: async () => {
|
|
1702
|
+
const db = BaseDb.getAppDb();
|
|
1703
|
+
const schemaName = context._schemaName;
|
|
1704
|
+
const modelName = context.modelName;
|
|
1705
|
+
const propertyName = context.name;
|
|
1706
|
+
if (!modelName || !propertyName)
|
|
1707
|
+
return;
|
|
1708
|
+
if (db && schemaName) {
|
|
1709
|
+
const propertyRecords = await db
|
|
1710
|
+
.select({ propertyId: properties.id })
|
|
1711
|
+
.from(properties)
|
|
1712
|
+
.innerJoin(models, eq(properties.modelId, models.id))
|
|
1713
|
+
.innerJoin(modelSchemas, eq(models.id, modelSchemas.modelId))
|
|
1714
|
+
.innerJoin(schemas, eq(modelSchemas.schemaId, schemas.id))
|
|
1715
|
+
.where(and(eq(schemas.name, schemaName), eq(models.name, modelName), eq(properties.name, propertyName)))
|
|
1716
|
+
.limit(1);
|
|
1717
|
+
if (propertyRecords.length > 0 && propertyRecords[0].propertyId != null) {
|
|
1718
|
+
await db
|
|
1719
|
+
.delete(properties)
|
|
1720
|
+
.where(eq(properties.id, propertyRecords[0].propertyId));
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
if (schemaName) {
|
|
1724
|
+
const schema = Schema.create(schemaName, { waitForReady: false });
|
|
1725
|
+
const snapshot = schema.getService().getSnapshot();
|
|
1726
|
+
const schemaContext = snapshot.context;
|
|
1727
|
+
if (schemaContext.models?.[modelName]?.properties?.[propertyName]) {
|
|
1728
|
+
const updatedModels = { ...schemaContext.models };
|
|
1729
|
+
const updatedProperties = { ...updatedModels[modelName].properties };
|
|
1730
|
+
delete updatedProperties[propertyName];
|
|
1731
|
+
updatedModels[modelName] = { ...updatedModels[modelName], properties: updatedProperties };
|
|
1732
|
+
schema.getService().send({ type: 'updateContext', models: updatedModels });
|
|
1733
|
+
schema.getService().send({ type: 'markAsDraft', propertyKey: `property:${modelName}:${propertyName}` });
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
},
|
|
1737
|
+
});
|
|
1738
|
+
}
|
|
2207
1739
|
}
|
|
2208
1740
|
ModelProperty.instanceCache = new Map();
|
|
2209
1741
|
// Pending writes tracking
|
|
@@ -2214,5 +1746,5 @@ var ModelProperty$1 = /*#__PURE__*/Object.freeze({
|
|
|
2214
1746
|
ModelProperty: ModelProperty
|
|
2215
1747
|
});
|
|
2216
1748
|
|
|
2217
|
-
export { ModelProperty
|
|
2218
|
-
//# sourceMappingURL=ModelProperty-
|
|
1749
|
+
export { ModelProperty };
|
|
1750
|
+
//# sourceMappingURL=ModelProperty-CGdkocQ8.js.map
|