@seedprotocol/sdk 0.7.3 → 0.7.4-next.784.g879c6a3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/dist/{BasePathResolver-Cm4apKRb.js → BasePathResolver-DxdS0wJ0.js} +43 -8
  2. package/dist/BasePathResolver-DxdS0wJ0.js.map +1 -0
  3. package/dist/{ClientManager-i3nJASkg.js → ClientManager-De-vKHGe.js} +37 -38
  4. package/dist/ClientManager-De-vKHGe.js.map +1 -0
  5. package/dist/{Item-DBFchXpC.js → Item-cq9VcsAY.js} +365 -191
  6. package/dist/Item-cq9VcsAY.js.map +1 -0
  7. package/dist/{ModelProperty-BS49g01Y.js → ModelProperty-DuuoFXaC.js} +45 -37
  8. package/dist/ModelProperty-DuuoFXaC.js.map +1 -0
  9. package/dist/{Schema-CpMNEnUO.js → Schema-Dc5EA8Yb.js} +246 -68
  10. package/dist/Schema-Dc5EA8Yb.js.map +1 -0
  11. package/dist/{SchemaValidationService-DieV4KL-.js → SchemaValidationService-DViJ056F.js} +49 -36
  12. package/dist/SchemaValidationService-DViJ056F.js.map +1 -0
  13. package/dist/{backfillMetadataPropertyIds-DSoOoTnX.js → backfillMetadataPropertyIds-DacVthS5.js} +3 -3
  14. package/dist/{backfillMetadataPropertyIds-DSoOoTnX.js.map → backfillMetadataPropertyIds-DacVthS5.js.map} +1 -1
  15. package/dist/{configurePlatform-D0lQGAMQ.js → configurePlatform-DlZ23w7e.js} +2 -2
  16. package/dist/{configurePlatform-D0lQGAMQ.js.map → configurePlatform-DlZ23w7e.js.map} +1 -1
  17. package/dist/{detachRowsBeforeDelete-S0q-DJPT.js → detachRowsBeforeDelete-YRSZY6dO.js} +2 -2
  18. package/dist/{detachRowsBeforeDelete-S0q-DJPT.js.map → detachRowsBeforeDelete-YRSZY6dO.js.map} +1 -1
  19. package/dist/{eas-6pjU-OuX.js → eas-D_6ptL_F.js} +4 -4
  20. package/dist/{eas-6pjU-OuX.js.map → eas-D_6ptL_F.js.map} +1 -1
  21. package/dist/{index-8O3Uow-Y.js → errors-Cl8rbtKR.js} +192 -48
  22. package/dist/errors-Cl8rbtKR.js.map +1 -0
  23. package/dist/{getItem-CxBNZ-WL.js → getItem-BcmJcUZB.js} +5 -5
  24. package/dist/{getItem-CxBNZ-WL.js.map → getItem-BcmJcUZB.js.map} +1 -1
  25. package/dist/{getPublishPayload-CTCvRUoU.js → getPublishPayload-C278kK9P.js} +15 -15
  26. package/dist/{getPublishPayload-CTCvRUoU.js.map → getPublishPayload-C278kK9P.js.map} +1 -1
  27. package/dist/{getPublishUploads-SFHCbf_y.js → getPublishUploads-DJ1UPh7i.js} +9 -9
  28. package/dist/{getPublishUploads-SFHCbf_y.js.map → getPublishUploads-DJ1UPh7i.js.map} +1 -1
  29. package/dist/{index-Cvt5UBz4.js → index-CqnU-5i0.js} +9 -9
  30. package/dist/index-CqnU-5i0.js.map +1 -0
  31. package/dist/{index-AVFTVp1m.js → index-DAl9U4rn.js} +2 -2
  32. package/dist/index-DAl9U4rn.js.map +1 -0
  33. package/dist/{index.browser-DBhxRoe8.js → index.browser-J6QZ9smP.js} +10 -10
  34. package/dist/{index.browser-DBhxRoe8.js.map → index.browser-J6QZ9smP.js.map} +1 -1
  35. package/dist/{index.node-CJhlcNHM.js → index.node-C9VB9NlX.js} +9 -9
  36. package/dist/index.node-C9VB9NlX.js.map +1 -0
  37. package/dist/main.js +24 -24
  38. package/dist/{model-DGMe-TTm.js → model-oHA3YhOd.js} +5 -1
  39. package/dist/model-oHA3YhOd.js.map +1 -0
  40. package/dist/node.js +11 -11
  41. package/dist/node.js.map +1 -1
  42. package/dist/platform.browser.js +5 -5
  43. package/dist/platform.node.js +4 -4
  44. package/dist/{property-DwPD283A.js → property-Brgr5RdT.js} +11 -11
  45. package/dist/{property-DwPD283A.js.map → property-Brgr5RdT.js.map} +1 -1
  46. package/dist/propertyValidationRules-CDRitiiK.js +51 -0
  47. package/dist/propertyValidationRules-CDRitiiK.js.map +1 -0
  48. package/dist/{publishDraftGraph-BOn3_Occ.js → publishDraftGraph-C37ibxb5.js} +6 -6
  49. package/dist/{publishDraftGraph-BOn3_Occ.js.map → publishDraftGraph-C37ibxb5.js.map} +1 -1
  50. package/dist/{resetAmbiguousLegacyItemData-BkYmBeJc.js → resetAmbiguousLegacyItemData-CcLFRREE.js} +2 -2
  51. package/dist/{resetAmbiguousLegacyItemData-BkYmBeJc.js.map → resetAmbiguousLegacyItemData-CcLFRREE.js.map} +1 -1
  52. package/dist/{resolveModelForSyncedSeed-BL24nLa7.js → resolveModelForSyncedSeed-BTAeCOJE.js} +2 -2
  53. package/dist/{resolveModelForSyncedSeed-BL24nLa7.js.map → resolveModelForSyncedSeed-BTAeCOJE.js.map} +1 -1
  54. package/dist/src/Item/Item.d.ts +6 -2
  55. package/dist/src/Item/Item.d.ts.map +1 -1
  56. package/dist/src/Item/errors.d.ts +23 -0
  57. package/dist/src/Item/errors.d.ts.map +1 -0
  58. package/dist/src/ItemProperty/ItemProperty.d.ts.map +1 -1
  59. package/dist/src/ItemProperty/service/actors/hydrateFromDb.d.ts.map +1 -1
  60. package/dist/src/ItemProperty/service/actors/loadOrCreateProperty.d.ts.map +1 -1
  61. package/dist/src/ItemProperty/service/actors/saveValueToDb/analyzeInput.d.ts.map +1 -1
  62. package/dist/src/ItemProperty/service/actors/saveValueToDb/saveFile.d.ts +19 -0
  63. package/dist/src/ItemProperty/service/actors/saveValueToDb/saveFile.d.ts.map +1 -1
  64. package/dist/src/ItemProperty/service/actors/saveValueToDb/saveImage.d.ts.map +1 -1
  65. package/dist/src/ItemProperty/service/actors/saveValueToDb/saveItemStorage.d.ts.map +1 -1
  66. package/dist/src/ItemProperty/service/propertyMachine.d.ts.map +1 -1
  67. package/dist/src/Model/Model.d.ts +2 -0
  68. package/dist/src/Model/Model.d.ts.map +1 -1
  69. package/dist/src/Model/service/actors/createModelProperties.d.ts.map +1 -1
  70. package/dist/src/ModelProperty/ModelProperty.d.ts +2 -0
  71. package/dist/src/ModelProperty/ModelProperty.d.ts.map +1 -1
  72. package/dist/src/Schema/Schema.d.ts +11 -2
  73. package/dist/src/Schema/Schema.d.ts.map +1 -1
  74. package/dist/src/Schema/service/actors/checkExistingSchema.d.ts.map +1 -1
  75. package/dist/src/Schema/service/actors/loadOrCreateSchema.d.ts.map +1 -1
  76. package/dist/src/Schema/service/schemaMachine.d.ts.map +1 -1
  77. package/dist/src/Schema/service/validation/SchemaValidationService.d.ts +4 -1
  78. package/dist/src/Schema/service/validation/SchemaValidationService.d.ts.map +1 -1
  79. package/dist/src/db/Db/BaseDb.d.ts +5 -2
  80. package/dist/src/db/Db/BaseDb.d.ts.map +1 -1
  81. package/dist/src/db/write/updateItemPropertyValue.d.ts.map +1 -1
  82. package/dist/src/events/item/syncDbWithEas.d.ts.map +1 -1
  83. package/dist/src/helpers/db.d.ts.map +1 -1
  84. package/dist/src/helpers/entity/draftSaveErrors.d.ts +4 -0
  85. package/dist/src/helpers/entity/draftSaveErrors.d.ts.map +1 -0
  86. package/dist/src/helpers/entity/entityUnload.d.ts +2 -1
  87. package/dist/src/helpers/entity/entityUnload.d.ts.map +1 -1
  88. package/dist/src/helpers/entity/evictionEpoch.d.ts +27 -2
  89. package/dist/src/helpers/entity/evictionEpoch.d.ts.map +1 -1
  90. package/dist/src/helpers/isSqliteUniqueConstraintError.d.ts.map +1 -1
  91. package/dist/src/helpers/model.d.ts.map +1 -1
  92. package/dist/src/helpers/propertyValidationRules.d.ts +12 -0
  93. package/dist/src/helpers/propertyValidationRules.d.ts.map +1 -0
  94. package/dist/src/helpers/propertyWriteQueue.d.ts +15 -0
  95. package/dist/src/helpers/propertyWriteQueue.d.ts.map +1 -0
  96. package/dist/src/helpers/schema.d.ts.map +1 -1
  97. package/dist/src/helpers/storageFileName.d.ts +7 -0
  98. package/dist/src/helpers/storageFileName.d.ts.map +1 -0
  99. package/dist/src/index.d.ts +1 -0
  100. package/dist/src/index.d.ts.map +1 -1
  101. package/dist/src/node/db/Db.d.ts +1 -1
  102. package/dist/src/node/db/Db.d.ts.map +1 -1
  103. package/dist/src/node/index.d.ts +1 -0
  104. package/dist/src/node/index.d.ts.map +1 -1
  105. package/dist/src/types/index.d.ts +12 -0
  106. package/dist/src/types/index.d.ts.map +1 -1
  107. package/dist/{syncDbWithEas-Bv2Fe38J.js → syncDbWithEas-B-Ho0IOB.js} +50 -27
  108. package/dist/syncDbWithEas-B-Ho0IOB.js.map +1 -0
  109. package/dist/{tabEvents-9s2WCYw-.js → tabEvents-BTzckWrN.js} +4 -4
  110. package/dist/{tabEvents-9s2WCYw-.js.map → tabEvents-BTzckWrN.js.map} +1 -1
  111. package/dist/{tolerantWebAccess-iUu80pAP.js → tolerantWebAccess-DOm2Xv-f.js} +6 -6
  112. package/dist/{tolerantWebAccess-iUu80pAP.js.map → tolerantWebAccess-DOm2Xv-f.js.map} +1 -1
  113. package/dist/{updateSeedRevokedAt-zBfi931j.js → updateSeedRevokedAt-IHXnJI-i.js} +3 -3
  114. package/dist/{updateSeedRevokedAt-zBfi931j.js.map → updateSeedRevokedAt-IHXnJI-i.js.map} +1 -1
  115. package/package.json +5 -5
  116. package/dist/BasePathResolver-Cm4apKRb.js.map +0 -1
  117. package/dist/ClientManager-i3nJASkg.js.map +0 -1
  118. package/dist/Item-DBFchXpC.js.map +0 -1
  119. package/dist/ModelProperty-BS49g01Y.js.map +0 -1
  120. package/dist/Schema-CpMNEnUO.js.map +0 -1
  121. package/dist/SchemaValidationService-DieV4KL-.js.map +0 -1
  122. package/dist/index-8O3Uow-Y.js.map +0 -1
  123. package/dist/index-AVFTVp1m.js.map +0 -1
  124. package/dist/index-Cvt5UBz4.js.map +0 -1
  125. package/dist/index.node-CJhlcNHM.js.map +0 -1
  126. package/dist/model-DGMe-TTm.js.map +0 -1
  127. package/dist/syncDbWithEas-Bv2Fe38J.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { waitFor, fromCallback, setup, assign, stateIn, createActor, isMachineSnapshot } from 'xstate';
2
- import { n as normalizeDataType, E as BaseDb, C as versions, m as metadata, A as seeds, z as schemas, s as models, q as modelSchemas, aQ as getOwnedAddressesFromDb, a9 as ZERO_BYTES32, aB as normalizeAddressList, a0 as normalizeHexAddress, ay as getAddressesForItemsFilter, H as toSnakeCase$1, ad as INTERNAL_PROPERTY_NAMES, J as BaseFileManager, aS as getStorageTransactionIdForSeedUid, aT as convertTxIdToImage, i as isDataType, X as normalizePublisher, ax as ensureImageLocal, ap as ImageSize, aU as downloadTransactionIdWithDedupe, u as properties, M as ModelPropertyDataTypes, $ as generateId, ag as INTERNAL_DATA_TYPES, r as modelUids, L as resolveItemModelFileId, aV as getPropertyIdForSchemaFileId, K as getPropertyIdForModelAndName, aW as getDataTypeFromString, aX as getMimeType, am as INTERNAL_STORAGE_MODEL_FILE_IDS, V as getItemStorageSubdir, W as getItemStorageLocalFileName, g as normalizePropertyRecordSchema, aY as PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP, a5 as getCorrectId, G as eventEmitter, ae as isStorageSeedRef } from './BasePathResolver-Cm4apKRb.js';
2
+ import { n as normalizeDataType, E as BaseDb, C as versions, m as metadata, A as seeds, z as schemas, s as models, q as modelSchemas, aQ as getOwnedAddressesFromDb, a9 as ZERO_BYTES32, aB as normalizeAddressList, a0 as normalizeHexAddress, ay as getAddressesForItemsFilter, H as toSnakeCase$1, ad as INTERNAL_PROPERTY_NAMES, J as BaseFileManager, aS as getStorageTransactionIdForSeedUid, aT as convertTxIdToImage, i as isDataType, X as normalizePublisher, ax as ensureImageLocal, ap as ImageSize, aU as downloadTransactionIdWithDedupe, u as properties, M as ModelPropertyDataTypes, $ as generateId, ag as INTERNAL_DATA_TYPES, r as modelUids, L as resolveItemModelFileId, aV as getPropertyIdForSchemaFileId, K as getPropertyIdForModelAndName, aW as getDataTypeFromString, aX as getMimeType, am as INTERNAL_STORAGE_MODEL_FILE_IDS, V as getItemStorageSubdir, W as getItemStorageLocalFileName, g as normalizePropertyRecordSchema, aY as PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP, a5 as getCorrectId, G as eventEmitter, ae as isStorageSeedRef } from './BasePathResolver-DxdS0wJ0.js';
3
3
  import { or, isNull, eq, max, count, and, getTableColumns, sql, desc, inArray, isNotNull, gt } from 'drizzle-orm';
4
4
  import pluralize from 'pluralize';
5
5
  import debug from 'debug';
@@ -8,8 +8,8 @@ import { startCase, upperFirst, camelCase, orderBy } from 'lodash-es';
8
8
  import { toSnakeCase } from 'drizzle-orm/casing';
9
9
  import { isValidEasAttestationUid, isPlaceholderUid, BaseQueryClient, BaseEasClient, GET_SCHEMAS, getEasSchemaUidForSchemaDefinition, getSchemaUidForModelFromCache, cachedSchemaLookup, setSchemaUidForModel, getEasSchemaUidForExactDefinition } from '@seedprotocol/eas';
10
10
  import { fetchArweaveRawTextAcrossGateways } from '@seedprotocol/arweave';
11
- import { d as notifyFileSaved, f as withTabLock } from './tabEvents-9s2WCYw-.js';
12
- import { modelPropertiesToObject } from './model-DGMe-TTm.js';
11
+ import { d as notifyFileSaved, f as withTabLock } from './tabEvents-BTzckWrN.js';
12
+ import { modelPropertiesToObject } from './model-oHA3YhOd.js';
13
13
 
14
14
  /**
15
15
  * Default readyTimeout for create/find/all with waitForReady. Loads that touch OPFS and the DB can take
@@ -724,9 +724,9 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
724
724
  try {
725
725
  const itemPropertyMod = await Promise.resolve().then(function () { return ItemProperty$1; });
726
726
  const { ItemProperty } = itemPropertyMod;
727
- const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
728
- const _mod_0 = await import('./index-8O3Uow-Y.js');
729
- const _ns_0 = _mod_0.f;
727
+ const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
728
+ const _mod_0 = await import('./errors-Cl8rbtKR.js');
729
+ const _ns_0 = _mod_0.h;
730
730
  const { Model } = _ns_0;
731
731
  // Resolve Model and build property schemas (use getByNameAsync for models not yet in cache)
732
732
  let propertySchemas = {};
@@ -743,7 +743,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
743
743
  const schemaNameToTry = schemaName ?? model?.schemaName;
744
744
  if (schemaNameToTry) {
745
745
  try {
746
- const _mod_1 = await import('./Schema-CpMNEnUO.js');
746
+ const _mod_1 = await import('./Schema-Dc5EA8Yb.js');
747
747
  const _ns_1 = _mod_1.b;
748
748
  const { Schema } = _ns_1;
749
749
  const schemaInstance = Schema.create(schemaNameToTry, { waitForReady: false });
@@ -759,7 +759,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
759
759
  }
760
760
  if (Object.keys(propertySchemas).length === 0) {
761
761
  try {
762
- const _mod_2 = await import('./ClientManager-i3nJASkg.js');
762
+ const _mod_2 = await import('./ClientManager-De-vKHGe.js');
763
763
  const _ns_2 = _mod_2.K;
764
764
  const { loadAllSchemasFromDb } = _ns_2;
765
765
  const allSchemas = await loadAllSchemasFromDb();
@@ -780,11 +780,11 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
780
780
  }
781
781
  if (Object.keys(propertySchemas).length === 0) {
782
782
  try {
783
- const _mod_3 = await import('./ClientManager-i3nJASkg.js');
783
+ const _mod_3 = await import('./ClientManager-De-vKHGe.js');
784
784
  const _ns_3 = _mod_3.K;
785
785
  const { listCompleteSchemaFiles } = _ns_3;
786
- const _mod_4 = await import('./BasePathResolver-Cm4apKRb.js');
787
- const _ns_4 = _mod_4.a_;
786
+ const _mod_4 = await import('./BasePathResolver-DxdS0wJ0.js');
787
+ const _ns_4 = _mod_4.a$;
788
788
  const { BaseFileManager } = _ns_4;
789
789
  const schemaFiles = await listCompleteSchemaFiles();
790
790
  for (const { filePath } of schemaFiles) {
@@ -804,7 +804,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
804
804
  }
805
805
  }
806
806
  if (Object.keys(propertySchemas).length === 0) {
807
- const schemaMod = await import('./index-Cvt5UBz4.js');
807
+ const schemaMod = await import('./index-CqnU-5i0.js');
808
808
  const { ModelPropertyDataTypes } = schemaMod;
809
809
  const KNOWN_MODEL_FALLBACKS = {
810
810
  Post: {
@@ -821,7 +821,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
821
821
  }
822
822
  }
823
823
  // Fallbacks above may return schema-file shape ({ type, model, items }); normalize to dataType/ref/refValueType.
824
- const { normalizePropertyRecordSchema } = await import('./property-DwPD283A.js');
824
+ const { normalizePropertyRecordSchema } = await import('./property-Brgr5RdT.js');
825
825
  propertySchemas = Object.fromEntries(Object.entries(propertySchemas).map(([name, def]) => [name, normalizePropertyRecordSchema(def)]));
826
826
  // Collapse rows that map to the same instance key (e.g. authorIdentityIds + authors -> authors).
827
827
  // ItemProperty.create cache does not sync propertyValue on hit; processing order would otherwise
@@ -854,7 +854,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
854
854
  // Infer propertyRecordSchema from metadata when schema is missing (enables persistence)
855
855
  let propSchema = propertySchemas[propertyName];
856
856
  if (!propSchema && isRefTypeFromMeta) {
857
- const schemaMod = await import('./index-Cvt5UBz4.js');
857
+ const schemaMod = await import('./index-CqnU-5i0.js');
858
858
  const { ModelPropertyDataTypes } = schemaMod;
859
859
  propSchema = {
860
860
  dataType: refSeedType === 'html' ? ModelPropertyDataTypes.Html
@@ -1860,8 +1860,8 @@ const getItemsData = async ({ modelName, modelFileId, schemaName, deleted, inclu
1860
1860
  conditions.push(eq(seeds.type, toSnakeCase(modelName)));
1861
1861
  }
1862
1862
  if (!modelFileId && schemaName && modelName) {
1863
- const _mod_5 = await import('./BasePathResolver-Cm4apKRb.js');
1864
- const _ns_5 = _mod_5.b1;
1863
+ const _mod_5 = await import('./BasePathResolver-DxdS0wJ0.js');
1864
+ const _ns_5 = _mod_5.b2;
1865
1865
  const { resolveModelRecord } = _ns_5;
1866
1866
  modelFileId = (await resolveModelRecord(modelName, { schemaName }))?.schemaFileId ?? undefined;
1867
1867
  if (!modelFileId)
@@ -2143,7 +2143,7 @@ const resolveRelatedValue = fromCallback(({ sendBack, input: { context } }) => {
2143
2143
  const { isRelation, propertyValue, propertyName, seedUid, propertyRecordSchema, populatedFromDb, schemaUid, } = context;
2144
2144
  const _resolveRelatedValue = async () => {
2145
2145
  // Use dynamic import to break circular dependency
2146
- const schemaMod = await import('./index-Cvt5UBz4.js');
2146
+ const schemaMod = await import('./index-CqnU-5i0.js');
2147
2147
  const { ModelPropertyDataTypes } = schemaMod;
2148
2148
  if (!propertyValue || !isRelation || populatedFromDb) {
2149
2149
  return;
@@ -2578,8 +2578,8 @@ async function readHtmlBodyFromChildStorageArweave(seedLocalId) {
2578
2578
  /* offline / bad tx id */
2579
2579
  }
2580
2580
  try {
2581
- const _mod_6 = await import('./BasePathResolver-Cm4apKRb.js');
2582
- const _ns_6 = _mod_6.b3;
2581
+ const _mod_6 = await import('./BasePathResolver-DxdS0wJ0.js');
2582
+ const _ns_6 = _mod_6.b4;
2583
2583
  const { downloadTransactionIdWithDedupe } = _ns_6;
2584
2584
  await downloadTransactionIdWithDedupe(txId);
2585
2585
  const retryFp = BaseFileManager.getFilesPath('html', `${seedLocalId}.html`);
@@ -2639,7 +2639,7 @@ const hydrateFromDb = fromCallback(({ sendBack, input: { context } }) => {
2639
2639
  // to use dynamically imported ModelPropertyDataTypes
2640
2640
  const _hydrateFromDb = async () => {
2641
2641
  // Use dynamic import to break circular dependency
2642
- const schemaMod = await import('./index-Cvt5UBz4.js');
2642
+ const schemaMod = await import('./index-CqnU-5i0.js');
2643
2643
  const { ModelPropertyDataTypes } = schemaMod;
2644
2644
  const appDb = BaseDb.getAppDb();
2645
2645
  const whereClauses = [];
@@ -2772,7 +2772,9 @@ const hydrateFromDb = fromCallback(({ sendBack, input: { context } }) => {
2772
2772
  }
2773
2773
  if (filePath) {
2774
2774
  localStorageDir = `/${dir}`;
2775
- renderValue = await BaseFileManager.readFileAsString(filePath);
2775
+ // The same content URL saveFile sets, so the value reads the same before and after a reload.
2776
+ refResolvedDisplayValue = await BaseFileManager.getContentUrlFromPath(filePath);
2777
+ renderValue = refResolvedDisplayValue;
2776
2778
  }
2777
2779
  }
2778
2780
  catch (e) {
@@ -2918,12 +2920,12 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
2918
2920
  const modelNameForNew = context.modelName;
2919
2921
  if (modelNameForNew) {
2920
2922
  try {
2921
- const _mod_7 = await import('./index-8O3Uow-Y.js');
2922
- const _ns_7 = _mod_7.f;
2923
+ const _mod_7 = await import('./errors-Cl8rbtKR.js');
2924
+ const _ns_7 = _mod_7.h;
2923
2925
  const { Model } = _ns_7;
2924
- const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
2925
- const _mod_8 = await import('./BasePathResolver-Cm4apKRb.js');
2926
- const _ns_8 = _mod_8.b1;
2926
+ const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
2927
+ const _mod_8 = await import('./BasePathResolver-DxdS0wJ0.js');
2928
+ const _ns_8 = _mod_8.b2;
2927
2929
  const { resolveItemModelFileId } = _ns_8;
2928
2930
  const normalizedModelName = upperFirst(camelCase(modelNameForNew));
2929
2931
  const itemModelFileId = await resolveItemModelFileId({
@@ -2976,8 +2978,8 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
2976
2978
  // It ends up in the context below, and later lookups by name (Model.getByName) can't match it.
2977
2979
  const modelName = context.modelName || (metadataRecord.modelType ? upperFirst(camelCase(metadataRecord.modelType)) : undefined);
2978
2980
  // Model names are only unique per schema: pin lookups to the item's own model row.
2979
- const _mod_9 = await import('./BasePathResolver-Cm4apKRb.js');
2980
- const _ns_9 = _mod_9.b1;
2981
+ const _mod_9 = await import('./BasePathResolver-DxdS0wJ0.js');
2982
+ const _ns_9 = _mod_9.b2;
2981
2983
  const { resolveItemModelFileId, resolveModelRecord } = _ns_9;
2982
2984
  const modelFileId = await resolveItemModelFileId({
2983
2985
  modelFileId: context.modelFileId,
@@ -3020,47 +3022,13 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
3020
3022
  filenameSuffix: propRecord.filenameSuffix || undefined,
3021
3023
  required: propRecord.required ?? undefined,
3022
3024
  };
3023
- // Merge with schema from file/DB to get validation rules (enum, pattern, etc.) - properties table doesn't store these
3024
- try {
3025
- const { getPropertySchema } = await import('./property-DwPD283A.js');
3026
- let schemaFromFile = await getPropertySchema(normalizedModelName, propertyName, {
3027
- modelFileId: modelRecord?.schemaFileId ?? modelFileId,
3028
- });
3029
- if (!schemaFromFile?.validation) {
3030
- // Fallback: get validation from schemaData in database (Schema context may not be loaded yet)
3031
- const _mod_10 = await import('./BasePathResolver-Cm4apKRb.js');
3032
- const _ns_10 = _mod_10.a$;
3033
- const { schemas: schemasTable } = _ns_10;
3034
- const _mod_11 = await import('./BasePathResolver-Cm4apKRb.js');
3035
- const _ns_11 = _mod_11.b0;
3036
- const { modelSchemas } = _ns_11;
3037
- const modelSchemaRows = await db
3038
- .select({ schemaId: modelSchemas.schemaId })
3039
- .from(modelSchemas)
3040
- .where(eq(modelSchemas.modelId, modelRecords[0].id))
3041
- .limit(1);
3042
- if (modelSchemaRows.length > 0 && modelSchemaRows[0].schemaId) {
3043
- const schemaRows = await db
3044
- .select({ schemaData: schemasTable.schemaData })
3045
- .from(schemasTable)
3046
- .where(eq(schemasTable.id, modelSchemaRows[0].schemaId))
3047
- .limit(1);
3048
- if (schemaRows.length > 0 && schemaRows[0].schemaData) {
3049
- const parsed = JSON.parse(schemaRows[0].schemaData);
3050
- const modelDef = parsed?.models?.[normalizedModelName];
3051
- const propDef = modelDef?.properties?.[propertyName];
3052
- if (propDef?.validation) {
3053
- propertyRecordSchema = { ...propertyRecordSchema, validation: propDef.validation };
3054
- }
3055
- }
3056
- }
3057
- }
3058
- else {
3059
- propertyRecordSchema = { ...propertyRecordSchema, validation: schemaFromFile.validation };
3060
- }
3061
- }
3062
- catch {
3063
- // Schema not loaded or lookup failed - continue with DB schema only
3025
+ // Validation rules (enum, pattern, ...) aren't in the properties table
3026
+ const { resolvePropertyValidationRules } = await import('./propertyValidationRules-CDRitiiK.js');
3027
+ const validation = await resolvePropertyValidationRules(normalizedModelName, propertyName, {
3028
+ modelFileId: modelRecord?.schemaFileId ?? modelFileId,
3029
+ });
3030
+ if (validation) {
3031
+ propertyRecordSchema = { ...propertyRecordSchema, validation };
3064
3032
  }
3065
3033
  }
3066
3034
  }
@@ -3072,10 +3040,10 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
3072
3040
  }
3073
3041
  if (!propertyRecordSchema && modelName) {
3074
3042
  try {
3075
- const _mod_12 = await import('./index-8O3Uow-Y.js');
3076
- const _ns_12 = _mod_12.f;
3077
- const { Model } = _ns_12;
3078
- const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
3043
+ const _mod_10 = await import('./errors-Cl8rbtKR.js');
3044
+ const _ns_10 = _mod_10.h;
3045
+ const { Model } = _ns_10;
3046
+ const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
3079
3047
  const normalizedModelName = upperFirst(camelCase(modelName));
3080
3048
  // Try PascalCase first ("post" -> "Post"); then findByModelType for names with spaces ("new_model" -> "New model")
3081
3049
  let model = Model.resolve(normalizedModelName, { modelFileId });
@@ -3226,7 +3194,8 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
3226
3194
  filePath = await resolveMatchingFilePath(dir, metadataRecord.refResolvedValue);
3227
3195
  }
3228
3196
  if (filePath) {
3229
- renderValue = await BaseFileManager.readFileAsString(filePath);
3197
+ // The content URL saveFile and hydrateFromDb set, so the value reads the same everywhere.
3198
+ renderValue = await BaseFileManager.getContentUrlFromPath(filePath);
3230
3199
  }
3231
3200
  }
3232
3201
  catch (e) {
@@ -3356,12 +3325,16 @@ const updateItemPropertyValue = async ({ localId: localIdParam, propertyName, ne
3356
3325
  if (localId == null)
3357
3326
  return;
3358
3327
  // Use Drizzle update API for proper parameterization (avoids SQL injection from filenames with quotes)
3328
+ const now = Date.now();
3359
3329
  const updatePayload = {
3360
3330
  propertyValue: safeNewValue ?? null,
3361
3331
  refSeedType: refSeedType ?? null,
3362
3332
  refResolvedValue: refResolvedValue ?? null,
3363
3333
  refResolvedDisplayValue: refResolvedDisplayValue ?? null,
3364
- updatedAt: Date.now(),
3334
+ // Readers take the newest row by COALESCE(attestation_created_at, created_at), so a draft's
3335
+ // time is when its value was last set: a synced value older than this edit mustn't win.
3336
+ createdAt: now,
3337
+ updatedAt: now,
3365
3338
  };
3366
3339
  if (localStorageDir !== undefined) {
3367
3340
  updatePayload.localStorageDir = localStorageDir ?? null;
@@ -3434,6 +3407,48 @@ const updateItemPropertyValue = async ({ localId: localIdParam, propertyName, ne
3434
3407
  };
3435
3408
  };
3436
3409
 
3410
+ const queues = new Map();
3411
+ let nextTicket = 0;
3412
+ const propertyWriteKey = (seedId, propertyName) => (seedId && propertyName ? `${seedId}:${propertyName}` : undefined);
3413
+ const reservePropertyWrite = (key) => {
3414
+ let queue = queues.get(key);
3415
+ if (!queue) {
3416
+ queue = { tail: Promise.resolve(), latest: 0, pending: 0 };
3417
+ queues.set(key, queue);
3418
+ }
3419
+ const q = queue;
3420
+ const ticket = ++nextTicket;
3421
+ q.latest = ticket;
3422
+ q.pending += 1;
3423
+ let released = false;
3424
+ const release = () => {
3425
+ if (released)
3426
+ return;
3427
+ released = true;
3428
+ q.pending -= 1;
3429
+ if (q.pending === 0 && queues.get(key) === q)
3430
+ queues.delete(key);
3431
+ };
3432
+ const run = async (write) => {
3433
+ const previous = q.tail;
3434
+ let done;
3435
+ const mine = new Promise((resolve) => (done = resolve));
3436
+ q.tail = previous.then(() => mine);
3437
+ try {
3438
+ await previous;
3439
+ if (q.latest !== ticket)
3440
+ return { skipped: true };
3441
+ return { skipped: false, result: await write() };
3442
+ }
3443
+ finally {
3444
+ done();
3445
+ release();
3446
+ }
3447
+ };
3448
+ return { run, release };
3449
+ };
3450
+ const hasPendingPropertyWrite = (key) => !!key && (queues.get(key)?.pending ?? 0) > 0;
3451
+
3437
3452
  const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
3438
3453
  const { localId, propertyName: propertyNameRaw, seedLocalId, versionLocalId, versionUid, propertyValue: existingValue, propertyRecordSchema, modelName, } = context;
3439
3454
  let { schemaUid } = context;
@@ -3447,6 +3462,10 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
3447
3462
  if (!propertyRecordSchema) {
3448
3463
  throw new Error('Missing propertyRecordSchema');
3449
3464
  }
3465
+ // Reserved now, before the async checks below, so a newer save always replaces this one.
3466
+ const writeKey = propertyWriteKey(seedLocalId ?? context.seedUid, propertyNameRaw);
3467
+ const writeSlot = writeKey ? reservePropertyWrite(writeKey) : undefined;
3468
+ const writeValue = (write) => writeSlot ? writeSlot.run(write) : write().then((result) => ({ skipped: false, result }));
3450
3469
  const _analyzeInput = async () => {
3451
3470
  // Assignment writes straight to the DB, so check ownership here as save()/destroy()/publish() do.
3452
3471
  const { isItemOwned, OwnershipError } = await Promise.resolve().then(function () { return ownership; });
@@ -3455,9 +3474,9 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
3455
3474
  return false;
3456
3475
  }
3457
3476
  // Use dynamic import to break circular dependency
3458
- const schemaMod = await import('./index-Cvt5UBz4.js');
3477
+ const schemaMod = await import('./index-CqnU-5i0.js');
3459
3478
  const { ModelPropertyDataTypes } = schemaMod;
3460
- const { SchemaValidationService } = await import('./SchemaValidationService-DieV4KL-.js');
3479
+ const { SchemaValidationService } = await import('./SchemaValidationService-DViJ056F.js');
3461
3480
  let propertyName = propertyNameRaw;
3462
3481
  if (!propertyName) {
3463
3482
  throw new Error('propertyName is required');
@@ -3541,7 +3560,7 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
3541
3560
  // List (including list of relations / primitives): JSON in DB, array in context for publish (bytes32[])
3542
3561
  if (normalizedDataType === ModelPropertyDataTypes.List && Array.isArray(newValue)) {
3543
3562
  const stringValue = JSON.stringify(newValue);
3544
- const result = await updateItemPropertyValue({
3563
+ const written = await writeValue(() => updateItemPropertyValue({
3545
3564
  localId,
3546
3565
  propertyName: propertyName,
3547
3566
  newValue: stringValue,
@@ -3552,7 +3571,11 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
3552
3571
  schemaUid,
3553
3572
  dataType: propertyRecordSchema.dataType,
3554
3573
  refValueType: propertyRecordSchema.refValueType,
3555
- });
3574
+ }));
3575
+ // A newer save replaced this one: it writes, and sets the context, instead.
3576
+ if (written.skipped)
3577
+ return true;
3578
+ const result = written.result;
3556
3579
  const updatedContext = {
3557
3580
  propertyValue: newValue,
3558
3581
  renderValue: newValue,
@@ -3572,7 +3595,7 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
3572
3595
  const stringValue = newValue !== null && newValue !== undefined
3573
3596
  ? (typeof newValue === 'string' ? newValue : String(newValue))
3574
3597
  : null;
3575
- const result = await updateItemPropertyValue({
3598
+ const written = await writeValue(() => updateItemPropertyValue({
3576
3599
  localId,
3577
3600
  propertyName: propertyName,
3578
3601
  newValue: stringValue,
@@ -3583,7 +3606,10 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
3583
3606
  schemaUid,
3584
3607
  dataType: propertyRecordSchema.dataType,
3585
3608
  refValueType: propertyRecordSchema.refValueType,
3586
- }); // Type assertion needed because newValue is not in MetadataType but is accepted by the function
3609
+ })); // Type assertion needed because newValue is not in MetadataType but is accepted by the function
3610
+ if (written.skipped)
3611
+ return true;
3612
+ const result = written.result;
3587
3613
  const stringValueForContext = typeof newValue === 'string' ? newValue : (newValue !== null && newValue !== undefined ? String(newValue) : undefined);
3588
3614
  let updatedContext = {
3589
3615
  propertyValue: stringValueForContext,
@@ -3607,7 +3633,7 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
3607
3633
  });
3608
3634
  return true;
3609
3635
  };
3610
- _analyzeInput().then((isDone) => {
3636
+ _analyzeInput().finally(() => writeSlot?.release()).then((isDone) => {
3611
3637
  if (isDone) {
3612
3638
  sendBack({ type: 'saveValueToDbSuccess' });
3613
3639
  }
@@ -3749,7 +3775,7 @@ const createMetadata = async (metadataValues, propertyRecordSchema, options) =>
3749
3775
  propertyRecordSchema?.validation &&
3750
3776
  metadataValues.propertyValue != null &&
3751
3777
  metadataValues.propertyValue !== '') {
3752
- const { SchemaValidationService } = await import('./SchemaValidationService-DieV4KL-.js');
3778
+ const { SchemaValidationService } = await import('./SchemaValidationService-DViJ056F.js');
3753
3779
  const validationService = new SchemaValidationService();
3754
3780
  const validationResult = validationService.validatePropertyValue(metadataValues.propertyValue, normalizeDataType(propertyRecordSchema.dataType), propertyRecordSchema.validation, propertyRecordSchema.refValueType
3755
3781
  ? normalizeDataType(String(propertyRecordSchema.refValueType))
@@ -3839,6 +3865,13 @@ const createMetadata = async (metadataValues, propertyRecordSchema, options) =>
3839
3865
  return inserted[0];
3840
3866
  };
3841
3867
 
3868
+ /**
3869
+ * Name of a new Image or File seed's file in the shared `images/` or `files/` folder. Uploads keep
3870
+ * their own name (and so their extension, which publish reads for the content type), prefixed with
3871
+ * the new seed's local id: two posts that each upload `photo.png` mustn't write the same file.
3872
+ */
3873
+ const storageFileNameForNewSeed = (seedLocalId, name) => `${seedLocalId}-${name}`;
3874
+
3842
3875
  /** Fetch image from URL (including blob:) and return { buffer, mimeType } for saving as binary. */
3843
3876
  const fetchImageAsBuffer = async (url) => {
3844
3877
  const response = await fetch(url);
@@ -3922,6 +3955,9 @@ const saveImage = fromCallback(({ sendBack, input: { context, event } }) => {
3922
3955
  fileName += `.${mimeType.split('/')[1]}`;
3923
3956
  }
3924
3957
  }
3958
+ else if (!isExistingFileReference) {
3959
+ fileName = storageFileNameForNewSeed(newImageSeedLocalId, fileName);
3960
+ }
3925
3961
  const filePath = BaseFileManager.getFilesPath('images', fileName);
3926
3962
  await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('images'));
3927
3963
  await createVersion({
@@ -4035,6 +4071,35 @@ const saveImage = fromCallback(({ sendBack, input: { context, event } }) => {
4035
4071
  });
4036
4072
 
4037
4073
  let fileSchemaUid;
4074
+ /**
4075
+ * What a string assigned to a File property means:
4076
+ * - `data:` URL: its decoded bytes
4077
+ * - `http(s):` or `blob:` URL: fetched
4078
+ * - the name of a file already in the files folder: a reference to it
4079
+ * - anything else: the file's text content
4080
+ * (Bare strings used to be decoded as base64 when they looked like it, so "hello" became
4081
+ * garbage, and names like "photo.jpg" were fetched as URLs.)
4082
+ */
4083
+ async function classifyFileString(value) {
4084
+ const dataUrl = /^data:([^,]*?)(;base64)?,(.*)$/s.exec(value);
4085
+ if (dataUrl) {
4086
+ const [, , isBase64, payload] = dataUrl;
4087
+ const bytes = isBase64
4088
+ ? Uint8Array.from(atob(payload), (c) => c.charCodeAt(0))
4089
+ : new TextEncoder().encode(decodeURIComponent(payload));
4090
+ return { kind: 'dataUrl', bytes: bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) };
4091
+ }
4092
+ if (/^(https?:\/\/|blob:)/i.test(value)) {
4093
+ return { kind: 'url' };
4094
+ }
4095
+ if (!/[\\/]/.test(value) && value.length < 256) {
4096
+ const existingFilePath = BaseFileManager.getFilesPath('files', value);
4097
+ if (await BaseFileManager.pathExists(existingFilePath)) {
4098
+ return { kind: 'existing' };
4099
+ }
4100
+ }
4101
+ return { kind: 'text' };
4102
+ }
4038
4103
  const saveFile = fromCallback(({ sendBack, input: { context, event } }) => {
4039
4104
  const { localId, propertyName: propertyNameRaw, propertyValue: existingValue, propertyRecordSchema, modelName, seedLocalId, seedUid, versionLocalId, versionUid, } = context;
4040
4105
  let { schemaUid } = context;
@@ -4074,22 +4139,22 @@ const saveFile = fromCallback(({ sendBack, input: { context, event } }) => {
4074
4139
  const fetchedSchemaUid = await getEasSchemaUidForModel('File');
4075
4140
  fileSchemaUid = fetchedSchemaUid ?? undefined;
4076
4141
  }
4142
+ let isExistingFileReference = false;
4077
4143
  if (typeof newValue === 'string') {
4078
- const newValueType = getDataTypeFromString(newValue);
4079
- if (newValueType === 'base64') {
4080
- const base64Data = newValue.split(',')[1] || newValue;
4081
- const binaryString = atob(base64Data);
4082
- const binaryArray = new Uint8Array(binaryString.length);
4083
- for (let i = 0; i < binaryString.length; i++) {
4084
- binaryArray[i] = binaryString.charCodeAt(i);
4085
- }
4086
- fileData = binaryArray.buffer;
4144
+ const source = await classifyFileString(newValue);
4145
+ if (source.kind === 'dataUrl') {
4146
+ fileData = source.bytes;
4087
4147
  }
4088
- else if (newValueType === 'url') {
4148
+ else if (source.kind === 'url') {
4089
4149
  const response = await fetch(newValue);
4090
4150
  fileData = await response.arrayBuffer();
4091
- const urlPath = new URL(newValue);
4092
- fileName = urlPath.pathname.split('/').pop();
4151
+ if (!newValue.startsWith('blob:')) {
4152
+ fileName = new URL(newValue).pathname.split('/').pop() || undefined;
4153
+ }
4154
+ }
4155
+ else if (source.kind === 'existing') {
4156
+ isExistingFileReference = true;
4157
+ fileName = newValue;
4093
4158
  }
4094
4159
  else {
4095
4160
  fileData = newValue;
@@ -4099,18 +4164,6 @@ const saveFile = fromCallback(({ sendBack, input: { context, event } }) => {
4099
4164
  fileName = newValue.name;
4100
4165
  fileData = await newValue.arrayBuffer(); // Blob API: works in browsers and Node (no FileReader in Node)
4101
4166
  }
4102
- // Handle existing file reference: filename from listFiles() that exists in files folder
4103
- let isExistingFileReference = false;
4104
- if (typeof newValue === 'string' &&
4105
- getDataTypeFromString(newValue) === null) {
4106
- const existingFilePath = BaseFileManager.getFilesPath('files', newValue);
4107
- const pathExistsResult = await BaseFileManager.pathExists(existingFilePath);
4108
- if (pathExistsResult) {
4109
- isExistingFileReference = true;
4110
- fileName = newValue;
4111
- fileData = undefined;
4112
- }
4113
- }
4114
4167
  if (!fileData && !isExistingFileReference) {
4115
4168
  throw new Error('No file data found');
4116
4169
  }
@@ -4121,6 +4174,9 @@ const saveFile = fromCallback(({ sendBack, input: { context, event } }) => {
4121
4174
  if (!fileName) {
4122
4175
  fileName = newFileSeedLocalId;
4123
4176
  }
4177
+ else if (!isExistingFileReference) {
4178
+ fileName = storageFileNameForNewSeed(newFileSeedLocalId, fileName);
4179
+ }
4124
4180
  const filePath = BaseFileManager.getFilesPath('files', fileName);
4125
4181
  await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('files'));
4126
4182
  await createVersion({
@@ -4331,7 +4387,7 @@ const saveRelation = fromCallback(({ sendBack, input: { context, event } }) => {
4331
4387
  }
4332
4388
  const _saveRelation = async () => {
4333
4389
  // Use dynamic import to break circular dependency
4334
- const schemaMod = await import('./index-Cvt5UBz4.js');
4390
+ const schemaMod = await import('./index-CqnU-5i0.js');
4335
4391
  const { ModelPropertyDataTypes } = schemaMod;
4336
4392
  if (!propertyNameRaw) {
4337
4393
  throw new Error('propertyName is required');
@@ -4623,6 +4679,9 @@ const saveItemStorage = fromCallback(({ sendBack, input: { context, event } }) =
4623
4679
  .set({
4624
4680
  refResolvedValue: fileName,
4625
4681
  localStorageDir,
4682
+ // The draft is as new as its content (see updateItemPropertyValue).
4683
+ createdAt: Date.now(),
4684
+ updatedAt: Date.now(),
4626
4685
  // Same shape as a row the migration or publish converted (convertVerbatimItemStorageRow).
4627
4686
  ...(clearsVerbatimValue && { propertyValue: null, refValueType: 'file' }),
4628
4687
  })
@@ -4669,6 +4728,30 @@ const withListRelationStorageName = (context) => {
4669
4728
  return context;
4670
4729
  return { ...context, propertyName: storageName, isRelation: true };
4671
4730
  };
4731
+ /**
4732
+ * List values are stored as JSON array strings. Whichever actor or event delivers one, a List
4733
+ * property holds the array, so `value` reads the same on a new item and after a reload.
4734
+ */
4735
+ const withListValueParsed = (context) => {
4736
+ if (normalizePropertyRecordSchema(context.propertyRecordSchema ?? {})?.dataType !== 'List')
4737
+ return context;
4738
+ const parse = (value) => {
4739
+ if (typeof value !== 'string' || !value.trimStart().startsWith('['))
4740
+ return value;
4741
+ try {
4742
+ const parsed = JSON.parse(value);
4743
+ return Array.isArray(parsed) ? parsed : value;
4744
+ }
4745
+ catch {
4746
+ return value;
4747
+ }
4748
+ };
4749
+ const propertyValue = parse(context.propertyValue);
4750
+ const renderValue = parse(context.renderValue);
4751
+ if (propertyValue === context.propertyValue && renderValue === context.renderValue)
4752
+ return context;
4753
+ return { ...context, propertyValue, renderValue };
4754
+ };
4672
4755
  const propertyMachine = setup({
4673
4756
  types: {
4674
4757
  context: {},
@@ -4736,9 +4819,7 @@ const propertyMachine = setup({
4736
4819
  }
4737
4820
  newContext[key] = event[key];
4738
4821
  }
4739
- return 'propertyRecordSchema' in event
4740
- ? withListRelationStorageName(newContext)
4741
- : newContext;
4822
+ return withListValueParsed('propertyRecordSchema' in event ? withListRelationStorageName(newContext) : newContext);
4742
4823
  }),
4743
4824
  },
4744
4825
  destroyStarted: {
@@ -4790,7 +4871,7 @@ const propertyMachine = setup({
4790
4871
  target: 'idle',
4791
4872
  actions: assign(({ context, event }) => {
4792
4873
  const property = event.property;
4793
- return withListRelationStorageName({
4874
+ return withListValueParsed(withListRelationStorageName({
4794
4875
  ...context,
4795
4876
  propertyName: property.propertyName || context.propertyName,
4796
4877
  propertyValue: property.propertyValue !== undefined ? property.propertyValue : context.propertyValue,
@@ -4808,7 +4889,7 @@ const propertyMachine = setup({
4808
4889
  refResolvedValue: property.refResolvedValue !== undefined ? property.refResolvedValue : context.refResolvedValue,
4809
4890
  refResolvedDisplayValue: property.refResolvedDisplayValue !== undefined ? property.refResolvedDisplayValue : context.refResolvedDisplayValue,
4810
4891
  localStorageDir: property.localStorageDir !== undefined ? property.localStorageDir : context.localStorageDir,
4811
- });
4892
+ }));
4812
4893
  }),
4813
4894
  },
4814
4895
  loadOrCreatePropertyError: {
@@ -5025,12 +5106,12 @@ const getPropertyData = async ({ propertyName, seedLocalId, seedUid, modelName,
5025
5106
  let names = [...getMetadataPropertyNamesForQuery(propertyName)];
5026
5107
  if (modelName) {
5027
5108
  try {
5028
- const _mod_13 = await import('./index-8O3Uow-Y.js');
5029
- const _ns_13 = _mod_13.f;
5030
- const { Model } = _ns_13;
5031
- const _mod_14 = await import('./BasePathResolver-Cm4apKRb.js');
5032
- const _ns_14 = _mod_14.b1;
5033
- const { resolveItemModelFileId } = _ns_14;
5109
+ const _mod_11 = await import('./errors-Cl8rbtKR.js');
5110
+ const _ns_11 = _mod_11.h;
5111
+ const { Model } = _ns_11;
5112
+ const _mod_12 = await import('./BasePathResolver-DxdS0wJ0.js');
5113
+ const _ns_12 = _mod_12.b2;
5114
+ const { resolveItemModelFileId } = _ns_12;
5034
5115
  // Model names are only unique per schema: use the seed's own model when it is recorded.
5035
5116
  const modelFileId = await resolveItemModelFileId({ seedLocalId, seedUid });
5036
5117
  const model = await Model.resolveAsync(modelName, { modelFileId });
@@ -5076,31 +5157,17 @@ var getPropertyData$1 = /*#__PURE__*/Object.freeze({
5076
5157
  });
5077
5158
 
5078
5159
  /**
5079
- * Unload an entity instance and clean up all resources
5160
+ * Release one reference to a cached entity instance. When none remain, remove it from the
5161
+ * caches, clean up its subscriptions and stop its service
5080
5162
  *
5081
5163
  * @param instance - Entity instance to unload
5082
5164
  * @param config - Unload configuration
5083
5165
  */
5084
5166
  function unloadEntity(instance, config) {
5085
- // Clean up liveQuery subscriptions
5086
- const instanceState = config.instanceState.get(instance);
5087
- if (instanceState) {
5088
- for (const key of ['liveQuerySubscription', 'schemaLiveQuerySubscription']) {
5089
- const sub = instanceState[key];
5090
- if (sub?.unsubscribe) {
5091
- try {
5092
- sub.unsubscribe();
5093
- instanceState[key] = null;
5094
- }
5095
- catch (error) {
5096
- // Ignore errors during cleanup
5097
- }
5098
- }
5099
- }
5100
- }
5101
5167
  // Get cache keys for this instance
5102
5168
  const cacheKeys = config.getCacheKeys(instance);
5103
5169
  // Remove from all caches (decrement refCount, delete if 0)
5170
+ let stillReferenced = false;
5104
5171
  for (const cache of config.caches) {
5105
5172
  for (const key of cacheKeys) {
5106
5173
  const entry = cache.get(key);
@@ -5117,6 +5184,27 @@ function unloadEntity(instance, config) {
5117
5184
  }
5118
5185
  else {
5119
5186
  cache.set(key, entry);
5187
+ stillReferenced = true;
5188
+ }
5189
+ }
5190
+ }
5191
+ }
5192
+ // Other holders (e.g. another hook that created the same cached instance) still use it:
5193
+ // keep its subscriptions and service running. Stopping here broke them.
5194
+ if (stillReferenced)
5195
+ return;
5196
+ // Clean up liveQuery subscriptions
5197
+ const instanceState = config.instanceState.get(instance);
5198
+ if (instanceState) {
5199
+ for (const key of ['liveQuerySubscription', 'schemaLiveQuerySubscription']) {
5200
+ const sub = instanceState[key];
5201
+ if (sub?.unsubscribe) {
5202
+ try {
5203
+ sub.unsubscribe();
5204
+ instanceState[key] = null;
5205
+ }
5206
+ catch (error) {
5207
+ // Ignore errors during cleanup
5120
5208
  }
5121
5209
  }
5122
5210
  }
@@ -5222,9 +5310,9 @@ const HTML_PROP_SEED_UID_RE = /^0x[a-fA-F0-9]{64}$/;
5222
5310
  */
5223
5311
  const resolvePropertyRecordSchemaFromSchemaData = async (modelName, propertyName, modelType, schemaName) => {
5224
5312
  try {
5225
- const _mod_15 = await import('./ClientManager-i3nJASkg.js');
5226
- const _ns_15 = _mod_15.K;
5227
- const { loadAllSchemasFromDb } = _ns_15;
5313
+ const _mod_13 = await import('./ClientManager-De-vKHGe.js');
5314
+ const _ns_13 = _mod_13.K;
5315
+ const { loadAllSchemasFromDb } = _ns_13;
5228
5316
  const allSchemas = await loadAllSchemasFromDb();
5229
5317
  const modelNameAlt = modelType ? upperFirst(camelCase(modelType)) : '';
5230
5318
  for (const { schema } of allSchemas) {
@@ -5276,13 +5364,13 @@ hints = {}) => {
5276
5364
  return undefined;
5277
5365
  }
5278
5366
  try {
5279
- const _mod_16 = await import('./index-8O3Uow-Y.js');
5280
- const _ns_16 = _mod_16.f;
5281
- const { Model } = _ns_16;
5282
- const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
5283
- const _mod_17 = await import('./BasePathResolver-Cm4apKRb.js');
5284
- const _ns_17 = _mod_17.b1;
5285
- const { resolveItemModelFileId } = _ns_17;
5367
+ const _mod_14 = await import('./errors-Cl8rbtKR.js');
5368
+ const _ns_14 = _mod_14.h;
5369
+ const { Model } = _ns_14;
5370
+ const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
5371
+ const _mod_15 = await import('./BasePathResolver-DxdS0wJ0.js');
5372
+ const _ns_15 = _mod_15.b2;
5373
+ const { resolveItemModelFileId } = _ns_15;
5286
5374
  const modelFileId = await resolveItemModelFileId(hints);
5287
5375
  let model = modelFileId
5288
5376
  ? await Model.resolveAsync(modelName || modelTypeToModelName(modelType ?? ''), { modelFileId })
@@ -5440,7 +5528,7 @@ class ItemProperty {
5440
5528
  return;
5441
5529
  }
5442
5530
  // Use dynamic import to break circular dependency
5443
- const schemaMod = await import('./index-Cvt5UBz4.js');
5531
+ const schemaMod = await import('./index-CqnU-5i0.js');
5444
5532
  const { ModelPropertyDataTypes } = schemaMod;
5445
5533
  const { context } = snapshot;
5446
5534
  const { propertyRecordSchema } = context;
@@ -5611,9 +5699,9 @@ class ItemProperty {
5611
5699
  const normalizedRefValueType = normalizeDataType(propertyRecordSchema?.refValueType);
5612
5700
  const propertyNames = getMetadataPropertyNamesForQuery(propertyName, normalizedDataType, normalizedRefValueType);
5613
5701
  const propertyNameVariant = propertyNames.length > 1 ? propertyNames[1] : undefined;
5614
- const _mod_18 = await import('./index-AVFTVp1m.js');
5615
- const _ns_18 = _mod_18.s;
5616
- const seedSchemaMod = _ns_18;
5702
+ const _mod_16 = await import('./index-DAl9U4rn.js');
5703
+ const _ns_16 = _mod_16.s;
5704
+ const seedSchemaMod = _ns_16;
5617
5705
  const { metadata } = seedSchemaMod;
5618
5706
  const drizzleMod = await import('drizzle-orm');
5619
5707
  const { eq, and, or } = drizzleMod;
@@ -5745,6 +5833,14 @@ class ItemProperty {
5745
5833
  return;
5746
5834
  const metaRow = metadataRows[0];
5747
5835
  logger(`[ItemProperty._setupLiveQuerySubscription] Metadata updated in database for propertyName: ${propertyName}`);
5836
+ // While this property has a save pending, the row is older than the value in memory
5837
+ // (the user may still be typing): showing it would drop keystrokes, and another tab's
5838
+ // write would replace the value being typed. The save sets the context itself.
5839
+ const { context } = this._service.getSnapshot();
5840
+ if (context.isSaving ||
5841
+ hasPendingPropertyWrite(propertyWriteKey(context.seedLocalId ?? context.seedUid, context.propertyName))) {
5842
+ return;
5843
+ }
5748
5844
  // Update context with metadata changes
5749
5845
  this._service.send({
5750
5846
  type: 'updateContext',
@@ -5827,9 +5923,9 @@ class ItemProperty {
5827
5923
  const ctx = this._service.getSnapshot().context;
5828
5924
  let modelFileId;
5829
5925
  try {
5830
- const _mod_19 = await import('./BasePathResolver-Cm4apKRb.js');
5831
- const _ns_19 = _mod_19.b1;
5832
- const { resolveItemModelFileId } = _ns_19;
5926
+ const _mod_17 = await import('./BasePathResolver-DxdS0wJ0.js');
5927
+ const _ns_17 = _mod_17.b2;
5928
+ const { resolveItemModelFileId } = _ns_17;
5833
5929
  modelFileId = await resolveItemModelFileId({
5834
5930
  modelFileId: ctx.modelFileId,
5835
5931
  seedLocalId: ctx.seedLocalId,
@@ -6190,9 +6286,9 @@ class ItemProperty {
6190
6286
  const propertiesData = await getItemProperties({ seedLocalId, seedUid });
6191
6287
  const instances = [];
6192
6288
  const seenNormalized = new Set();
6193
- const _mod_20 = await import('./BasePathResolver-Cm4apKRb.js');
6194
- const _ns_20 = _mod_20.b1;
6195
- const { resolveItemModelFileId } = _ns_20;
6289
+ const _mod_18 = await import('./BasePathResolver-DxdS0wJ0.js');
6290
+ const _ns_18 = _mod_18.b2;
6291
+ const { resolveItemModelFileId } = _ns_18;
6196
6292
  const itemModelFileId = await resolveItemModelFileId({ seedLocalId, seedUid });
6197
6293
  for (const data of propertiesData) {
6198
6294
  const d = data;
@@ -6208,10 +6304,10 @@ class ItemProperty {
6208
6304
  }
6209
6305
  else if (baseName) {
6210
6306
  try {
6211
- const _mod_21 = await import('./index-8O3Uow-Y.js');
6212
- const _ns_21 = _mod_21.f;
6213
- const { Model } = _ns_21;
6214
- const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
6307
+ const _mod_19 = await import('./errors-Cl8rbtKR.js');
6308
+ const _ns_19 = _mod_19.h;
6309
+ const { Model } = _ns_19;
6310
+ const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
6215
6311
  const model = await Model.resolveAsync(modelName, { modelFileId });
6216
6312
  if (model?.properties) {
6217
6313
  const schemas = modelPropertiesToObject(model.properties);
@@ -6225,10 +6321,10 @@ class ItemProperty {
6225
6321
  }
6226
6322
  if (modelName && propertyName) {
6227
6323
  try {
6228
- const _mod_22 = await import('./index-8O3Uow-Y.js');
6229
- const _ns_22 = _mod_22.f;
6230
- const { Model } = _ns_22;
6231
- const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
6324
+ const _mod_20 = await import('./errors-Cl8rbtKR.js');
6325
+ const _ns_20 = _mod_20.h;
6326
+ const { Model } = _ns_20;
6327
+ const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
6232
6328
  const model = await Model.resolveAsync(modelName, { modelFileId });
6233
6329
  if (model?.properties?.length) {
6234
6330
  const schemas = modelPropertiesToObject(model.properties);
@@ -6557,9 +6653,9 @@ class ItemProperty {
6557
6653
  if (!propertyName || (!seedLocalId && !seedUid))
6558
6654
  return;
6559
6655
  if (db) {
6560
- const _mod_23 = await import('./index-AVFTVp1m.js');
6561
- const _ns_23 = _mod_23.s;
6562
- const seedSchemaMod = _ns_23;
6656
+ const _mod_21 = await import('./index-DAl9U4rn.js');
6657
+ const _ns_21 = _mod_21.s;
6658
+ const seedSchemaMod = _ns_21;
6563
6659
  const { metadata } = seedSchemaMod;
6564
6660
  const drizzleMod = await import('drizzle-orm');
6565
6661
  const { and, eq } = drizzleMod;
@@ -6602,9 +6698,9 @@ const createNewItem = async ({ modelName, modelFileId, ...propertyData }) => {
6602
6698
  }
6603
6699
  const seedType = toSnakeCase(modelName);
6604
6700
  // Dynamic import to break circular dependency
6605
- const _mod_24 = await import('./index-8O3Uow-Y.js');
6606
- const _ns_24 = _mod_24.f;
6607
- const modelMod = _ns_24;
6701
+ const _mod_22 = await import('./errors-Cl8rbtKR.js');
6702
+ const _ns_22 = _mod_22.h;
6703
+ const modelMod = _ns_22;
6608
6704
  const { Model } = modelMod;
6609
6705
  const model = await Model.resolveAsync(modelName, { modelFileId });
6610
6706
  const propertySchemas = model?.properties ? modelPropertiesToObject(model.properties) : undefined;
@@ -6785,9 +6881,9 @@ const getModel = () => {
6785
6881
  // the fragile `import(...).then(n => n.X)` chunk-namespace pattern.
6786
6882
  if (!modelImportPromise) {
6787
6883
  modelImportPromise = (async () => {
6788
- const _mod_25 = await import('./index-8O3Uow-Y.js');
6789
- const _ns_25 = _mod_25.f;
6790
- const mod = _ns_25;
6884
+ const _mod_23 = await import('./errors-Cl8rbtKR.js');
6885
+ const _ns_23 = _mod_23.h;
6886
+ const mod = _ns_23;
6791
6887
  ModelClass = mod.Model;
6792
6888
  return mod;
6793
6889
  })();
@@ -6953,14 +7049,14 @@ class Item {
6953
7049
  };
6954
7050
  this.getPublishUploads = async (options) => {
6955
7051
  // Use dynamic import to break circular dependency
6956
- const getPublishUploadsMod = await import('./getPublishUploads-SFHCbf_y.js');
7052
+ const getPublishUploadsMod = await import('./getPublishUploads-DJ1UPh7i.js');
6957
7053
  const { getPublishUploads } = getPublishUploadsMod;
6958
7054
  return await getPublishUploads(this, [], undefined, options);
6959
7055
  };
6960
7056
  this.getPublishPayload = async (uploadedTransactions, options) => {
6961
- const _mod_26 = await import('./getPublishPayload-CTCvRUoU.js');
6962
- const _ns_26 = _mod_26.g;
6963
- const getPublishPayloadMod = _ns_26;
7057
+ const _mod_24 = await import('./getPublishPayload-C278kK9P.js');
7058
+ const _ns_24 = _mod_24.g;
7059
+ const getPublishPayloadMod = _ns_24;
6964
7060
  const { getPublishPayload } = getPublishPayloadMod;
6965
7061
  return await getPublishPayload(this, uploadedTransactions, options);
6966
7062
  };
@@ -7494,26 +7590,32 @@ class Item {
7494
7590
  const db = BaseDb.getAppDb();
7495
7591
  if (db && props.modelName) {
7496
7592
  // Model names are only unique per schema: resolve the exact models row from the most specific scope.
7497
- const _mod_27 = await import('./BasePathResolver-Cm4apKRb.js');
7498
- const _ns_27 = _mod_27.b1;
7499
- const { resolveModelRecord } = _ns_27;
7593
+ const _mod_25 = await import('./BasePathResolver-DxdS0wJ0.js');
7594
+ const _ns_25 = _mod_25.b2;
7595
+ const { resolveModelRecord } = _ns_25;
7500
7596
  const modelRecord = await resolveModelRecord(props.modelName, {
7501
7597
  modelFileId: props.modelFileId ?? modelInstance?.id,
7502
7598
  schemaName: schemaName ?? modelInstance?.schemaName,
7503
7599
  });
7504
7600
  const modelRecords = modelRecord ? [modelRecord] : [];
7601
+ if (!modelRecord) {
7602
+ const _mod_26 = await import('./errors-Cl8rbtKR.js');
7603
+ const _ns_26 = _mod_26.j;
7604
+ const { UnknownModelError } = _ns_26;
7605
+ throw new UnknownModelError(props.modelName, schemaName ?? modelInstance?.schemaName);
7606
+ }
7505
7607
  if (modelRecord?.schemaFileId) {
7506
7608
  props.modelFileId = modelRecord.schemaFileId;
7507
7609
  }
7508
7610
  // Scope the constructor's Model lookup to this model's schema (as getItemData does on reload),
7509
7611
  // so a same-named model cached from another schema can't supply the property set.
7510
7612
  if (modelRecord && !props.schemaName) {
7511
- const _mod_28 = await import('./BasePathResolver-Cm4apKRb.js');
7613
+ const _mod_27 = await import('./BasePathResolver-DxdS0wJ0.js');
7614
+ const _ns_27 = _mod_27.b1;
7615
+ const { modelSchemas } = _ns_27;
7616
+ const _mod_28 = await import('./BasePathResolver-DxdS0wJ0.js');
7512
7617
  const _ns_28 = _mod_28.b0;
7513
- const { modelSchemas } = _ns_28;
7514
- const _mod_29 = await import('./BasePathResolver-Cm4apKRb.js');
7515
- const _ns_29 = _mod_29.a$;
7516
- const { schemas: schemasTable } = _ns_29;
7618
+ const { schemas: schemasTable } = _ns_28;
7517
7619
  const schemaRows = await db
7518
7620
  .select({ schemaName: schemasTable.name })
7519
7621
  .from(modelSchemas)
@@ -7567,6 +7669,12 @@ class Item {
7567
7669
  modelPropertyData[key] = value;
7568
7670
  }
7569
7671
  }
7672
+ // Strict by default: unknown keys and invalid values reject before anything is written.
7673
+ // Values that go through the property save pipeline (files, Html, ItemStorage) are
7674
+ // validated there.
7675
+ if (propertyNames.length > 0 && options?.validate !== false) {
7676
+ await Item.assertValidCreateValues(props, propertyNames, dataTypeByPropertyName, new Set(pipelineValues.map(([key]) => key)));
7677
+ }
7570
7678
  const { seedLocalId, versionLocalId, } = await createNewItem(modelPropertyData);
7571
7679
  props.seedLocalId = seedLocalId;
7572
7680
  props.latestVersionLocalId = versionLocalId;
@@ -7864,9 +7972,9 @@ class Item {
7864
7972
  if (!appDb || Item.instanceCache.size === 0) {
7865
7973
  return;
7866
7974
  }
7867
- const _mod_30 = await import('./index-AVFTVp1m.js');
7868
- const _ns_30 = _mod_30.s;
7869
- const { metadata } = _ns_30;
7975
+ const _mod_29 = await import('./index-DAl9U4rn.js');
7976
+ const _ns_29 = _mod_29.s;
7977
+ const { metadata } = _ns_29;
7870
7978
  const { eq, and } = await import('drizzle-orm');
7871
7979
  const dedupedInstances = new Map();
7872
7980
  for (const entry of Item.instanceCache.values()) {
@@ -8025,7 +8133,64 @@ class Item {
8025
8133
  });
8026
8134
  state.definedPropertyNames.add(propertyName);
8027
8135
  }
8028
- /** Same as `item.publish(options)`; requires @seedprotocol/publish. */
8136
+ /** Throws ItemCreateValidationError for unknown keys and values that break their property's rules. */
8137
+ static async assertValidCreateValues(props, propertyNames, dataTypeByPropertyName, skipKeys) {
8138
+ const _mod_30 = await import('./errors-Cl8rbtKR.js');
8139
+ const _ns_30 = _mod_30.j;
8140
+ const { ItemCreateValidationError } = _ns_30;
8141
+ const { getPropertySchema } = await import('./property-Brgr5RdT.js');
8142
+ const { SchemaValidationService } = await import('./SchemaValidationService-DViJ056F.js');
8143
+ const validationService = new SchemaValidationService();
8144
+ const modelName = props.modelName;
8145
+ const known = new Set(propertyNames);
8146
+ const problems = [];
8147
+ for (const [key, value] of Object.entries(props)) {
8148
+ if (Item.CREATE_METADATA_KEYS.has(key) || skipKeys.has(key))
8149
+ continue;
8150
+ if (!known.has(key)) {
8151
+ problems.push({
8152
+ property: key,
8153
+ code: 'unknown_property',
8154
+ message: `${modelName} has no property "${key}"`,
8155
+ });
8156
+ continue;
8157
+ }
8158
+ if (value === undefined || value === null)
8159
+ continue;
8160
+ const propertySchema = await getPropertySchema(modelName, key, {
8161
+ modelFileId: props.modelFileId,
8162
+ schemaName: props.schemaName,
8163
+ });
8164
+ const dataType = normalizeDataType(propertySchema?.dataType ?? dataTypeByPropertyName.get(key) ?? '');
8165
+ if (!dataType)
8166
+ continue;
8167
+ // Lists may be passed as the JSON array string they are stored as.
8168
+ let checked = value;
8169
+ if (dataType === ModelPropertyDataTypes.List && typeof value === 'string') {
8170
+ try {
8171
+ const parsed = JSON.parse(value);
8172
+ if (Array.isArray(parsed))
8173
+ checked = parsed;
8174
+ }
8175
+ catch {
8176
+ // Not JSON: validated as given, and rejected as a non-array
8177
+ }
8178
+ }
8179
+ const { resolvePropertyValidationRules } = await import('./propertyValidationRules-CDRitiiK.js');
8180
+ const rules = propertySchema?.validation ??
8181
+ (await resolvePropertyValidationRules(modelName, key, {
8182
+ modelFileId: props.modelFileId,
8183
+ schemaName: props.schemaName,
8184
+ }));
8185
+ const result = validationService.validatePropertyValue(checked, dataType, rules, propertySchema?.refValueType);
8186
+ for (const error of result.errors) {
8187
+ problems.push({ property: key, code: error.code, message: error.message });
8188
+ }
8189
+ }
8190
+ if (problems.length > 0) {
8191
+ throw new ItemCreateValidationError(modelName, problems);
8192
+ }
8193
+ }
8029
8194
  /**
8030
8195
  * Set `publisher` on loaded Items for these seeds (after claimUnpublishedDrafts stamped
8031
8196
  * their rows). Items that aren't loaded read it from the DB when they load.
@@ -8342,7 +8507,7 @@ class Item {
8342
8507
  itemActor.send(event);
8343
8508
  };
8344
8509
  try {
8345
- const _mod_31 = await import('./index-AVFTVp1m.js');
8510
+ const _mod_31 = await import('./index-DAl9U4rn.js');
8346
8511
  const _ns_31 = _mod_31.s;
8347
8512
  const seedSchemaMod = _ns_31;
8348
8513
  const { seeds, versions, metadata } = seedSchemaMod;
@@ -8691,6 +8856,15 @@ class Item {
8691
8856
  }
8692
8857
  }
8693
8858
  Item.instanceCache = new Map();
8859
+ /** Same as `item.publish(options)`; requires @seedprotocol/publish. */
8860
+ /** Keys Item.create accepts besides the model's properties. */
8861
+ Item.CREATE_METADATA_KEYS = new Set([
8862
+ 'modelName', 'schemaName', 'modelInstance', 'modelFileId', 'type',
8863
+ 'seedLocalId', 'seedUid', 'schemaUid', 'attestationCreatedAt',
8864
+ 'latestVersionUid', 'latestVersionLocalId', 'publishedVersionUid', 'publishedVersionLocalId',
8865
+ 'versionsCount', 'lastVersionPublishedAt', 'lastLocalUpdateAt',
8866
+ 'createdAt', 'updatedAt', 'publisher', 'revokedAt',
8867
+ ]);
8694
8868
 
8695
8869
  var Item$1 = /*#__PURE__*/Object.freeze({
8696
8870
  __proto__: null,
@@ -8698,4 +8872,4 @@ var Item$1 = /*#__PURE__*/Object.freeze({
8698
8872
  });
8699
8873
 
8700
8874
  export { getInvariantSafePropertyDescriptor as $, getGetPublisherForNewSeeds as A, getMetadataLatest as B, ClientManagerState as C, DEFAULT_READY_TIMEOUT_MS as D, getPublishExecutor as E, getRevokeExecutor as F, getUploadExecutor as G, getVersionData$1 as H, Item as I, isLocalUnsealedDraft as J, isSeedRowOwned as K, localUnsealedDraftSql as L, METADATA_LATEST_FIRST_ORDER_SQL as M, ownedPublisherSql as N, OwnershipError as O, PUBLISH_NOT_CONFIGURED_MESSAGE as P, ownedSeedsSql as Q, pickLatestMetadataRowPerProperty as R, placeholderUidSql as S, propertyMachine as T, publisherInAddressListSql as U, publisherIsInOwnedSet as V, setAdditionalSyncAddresses as W, setGetPublisherForNewSeeds as X, setPublishExecutor as Y, setRevokeExecutor as Z, setUploadExecutor as _, chunkValues as a, clearDestroySubscriptions as a0, unloadEntity as a1, ClientManagerEvents as a2, withLockedItemStorageRow as a3, getItemStorageFilePath as a4, writeItemStorageFile as a5, resolvePublisherFromSeedRow as a6, getPropertyData$1 as a7, Item$1 as a8, rowsPerInsert as b, compareMetadataRowsLatestFirst as c, getGetAdditionalSyncAddresses as d, ItemProperty as e, ItemPropertySaveValidationError as f, getItemData as g, assertItemOwned as h, isItemOwned as i, getEasSchemaUidForModel as j, getLatestPublishedVersionRow as k, listRelationEasPropertyName as l, isVersionRevoked as m, waitForEntityIdle as n, createReactiveProxy as o, parseListPropertyValueFromStorage as p, findEntity as q, resolveStorageNameToSchemaName as r, selectInBatches as s, forceRemoveFromCaches as t, runDestroyLifecycle as u, isPublishedMetadataRow as v, writeInBatches as w, MachineIds as x, createNewItem as y, getEasSchemaForItemProperty as z };
8701
- //# sourceMappingURL=Item-DBFchXpC.js.map
8875
+ //# sourceMappingURL=Item-cq9VcsAY.js.map