@seedprotocol/sdk 0.1.54 → 0.1.55

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 (43) hide show
  1. package/dist/{index-NmD9sjcJ.js → index-BkzKfVvD.js} +3 -3
  2. package/dist/index-BkzKfVvD.js.map +1 -0
  3. package/dist/{index-DQKd-s2Q.js → index-D4my8yy8.js} +2162 -1889
  4. package/dist/index-D4my8yy8.js.map +1 -0
  5. package/dist/main.js +2 -2
  6. package/dist/{seed.schema.config-OyHsE0Zl.js → seed.schema.config-BHZSMMmL.js} +2 -2
  7. package/dist/{seed.schema.config-OyHsE0Zl.js.map → seed.schema.config-BHZSMMmL.js.map} +1 -1
  8. package/dist/src/createMetadata.ts +1 -1
  9. package/dist/src/download.ts +6 -2
  10. package/dist/src/getItemProperty.ts +0 -1
  11. package/dist/src/propertyMachine.ts +62 -16
  12. package/dist/src/resolveRelatedValue.ts +4 -0
  13. package/dist/src/saveImageSrc.ts +200 -0
  14. package/dist/src/saveItemStorage.ts +145 -0
  15. package/dist/src/saveRelation.ts +112 -0
  16. package/dist/src/write.ts +27 -7
  17. package/dist/types/src/browser/db/read/getItemProperty.d.ts.map +1 -1
  18. package/dist/types/src/browser/db/write.d.ts.map +1 -1
  19. package/dist/types/src/browser/events/files/download.d.ts.map +1 -1
  20. package/dist/types/src/browser/item/Item.d.ts.map +1 -1
  21. package/dist/types/src/browser/property/ItemProperty.d.ts +20 -11
  22. package/dist/types/src/browser/property/ItemProperty.d.ts.map +1 -1
  23. package/dist/types/src/browser/property/actors/resolveRelatedValue.d.ts.map +1 -1
  24. package/dist/types/src/browser/property/actors/saveValueToDb/index.d.ts +8 -0
  25. package/dist/types/src/browser/property/actors/saveValueToDb/index.d.ts.map +1 -0
  26. package/dist/types/src/browser/property/actors/saveValueToDb/saveImageSrc.d.ts +5 -0
  27. package/dist/types/src/browser/property/actors/saveValueToDb/saveImageSrc.d.ts.map +1 -0
  28. package/dist/types/src/browser/property/actors/saveValueToDb/saveItemStorage.d.ts +5 -0
  29. package/dist/types/src/browser/property/actors/saveValueToDb/saveItemStorage.d.ts.map +1 -0
  30. package/dist/types/src/browser/property/actors/saveValueToDb/saveRelation.d.ts +5 -0
  31. package/dist/types/src/browser/property/actors/saveValueToDb/saveRelation.d.ts.map +1 -0
  32. package/dist/types/src/browser/property/propertyMachine.d.ts.map +1 -1
  33. package/dist/types/src/browser/schema/file/fetchAll/actors.d.ts.map +1 -1
  34. package/dist/types/src/shared/helpers/index.d.ts +1 -1
  35. package/dist/types/src/shared/helpers/index.d.ts.map +1 -1
  36. package/dist/types/src/types/property.d.ts +6 -0
  37. package/dist/types/src/types/property.d.ts.map +1 -1
  38. package/package.json +1 -1
  39. package/dist/index-DQKd-s2Q.js.map +0 -1
  40. package/dist/index-NmD9sjcJ.js.map +0 -1
  41. package/dist/src/saveValueToDb.ts +0 -208
  42. package/dist/types/src/browser/property/actors/saveValueToDb.d.ts +0 -10
  43. package/dist/types/src/browser/property/actors/saveValueToDb.d.ts.map +0 -1
@@ -3,7 +3,7 @@ import path, { basename } from 'path';
3
3
  import 'reflect-metadata';
4
4
  import { Type } from '@sinclair/typebox';
5
5
  import { fromCallback, assign, createActor, waitFor, setup, emit, raise } from 'xstate';
6
- import { sql, relations, and, eq, max, or, inArray, like, count, isNotNull, isNull, getTableColumns, gt } from 'drizzle-orm';
6
+ import { sql, relations, and, eq, max, or, count, isNotNull, isNull, inArray, like, getTableColumns, gt } from 'drizzle-orm';
7
7
  import { fs, configureSingle } from '@zenfs/core';
8
8
  import 'dayjs';
9
9
  import { customAlphabet } from 'nanoid';
@@ -16,6 +16,7 @@ import { QueryClient } from '@tanstack/react-query';
16
16
  import { GraphQLClient } from 'graphql-request';
17
17
  import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister';
18
18
  import { persistQueryClient } from '@tanstack/react-query-persist-client';
19
+ import { useState, useEffect, useRef, useCallback } from 'react';
19
20
  import { BehaviorSubject } from 'rxjs';
20
21
  import { immerable, produce, enableMapSet } from 'immer';
21
22
  import pluralize from 'pluralize';
@@ -23,7 +24,6 @@ import { createBrowserInspector } from '@statelyai/inspect';
23
24
  import { drizzle } from 'drizzle-orm/sqlite-proxy';
24
25
  import { WebAccess } from '@zenfs/dom';
25
26
  import Arweave from 'arweave';
26
- import { useState, useEffect, useRef, useCallback } from 'react';
27
27
  import { useImmer } from 'use-immer';
28
28
  import { useSelector } from '@xstate/react';
29
29
 
@@ -250,20 +250,22 @@ const getMimeType = (base64) => {
250
250
  return null; // MIME type could not be determined
251
251
  }
252
252
  };
253
- const getImageDataType = (data) => {
253
+ const getDataTypeFromString = (data) => {
254
+ const nonImageBase64Regex = /^(?!data:image\/(?:jpeg|png|gif|bmp|webp);base64,)[A-Za-z0-9+/=]+$/;
255
+ if (nonImageBase64Regex.test(data)) {
256
+ return 'base64';
257
+ }
254
258
  // Regular expression for base64 (simple version, checking for base64 format)
255
- const base64Regex = /^data:image\/[a-zA-Z]+;base64,[A-Za-z0-9+/]+={0,2}$/;
259
+ const imageBase64Regex = /^data:image\/[a-zA-Z]+;base64,[A-Za-z0-9+/]+={0,2}$/;
260
+ if (imageBase64Regex.test(data)) {
261
+ return 'imageBase64';
262
+ }
256
263
  // Regular expression for URL (simple version, checking for common URL format)
257
264
  const urlRegex = /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/;
258
- if (base64Regex.test(data)) {
259
- return 'base64';
260
- }
261
- else if (urlRegex.test(data)) {
265
+ if (urlRegex.test(data)) {
262
266
  return 'url';
263
267
  }
264
- else {
265
- return null;
266
- }
268
+ return null;
267
269
  };
268
270
  const convertTxIdToImageSrc = (txId) => __awaiter(void 0, void 0, void 0, function* () {
269
271
  const imageFilePath = `/files/images/${txId}`;
@@ -514,6 +516,9 @@ const refResolvedValueToContentUrl = new Map();
514
516
  const seedUidToContentUrl = new Map();
515
517
  const resolveRelatedValue = fromCallback(({ sendBack, input: { context } }) => {
516
518
  const { isRelation, propertyValue, propertyName, seedUid, propertyRecordSchema, seedLocalId, schemaUid, } = context;
519
+ if (seedLocalId === 'AhiILhtcVq') {
520
+ console.log('[resolveRelatedValue] seedLocalId', seedLocalId);
521
+ }
517
522
  const _resolveRelatedValue = () => __awaiter(void 0, void 0, void 0, function* () {
518
523
  if (!propertyValue || !isRelation) {
519
524
  return;
@@ -985,7 +990,7 @@ const hydrateFromDb = fromCallback(({ sendBack, input: { context } }) => {
985
990
  renderValue: refResolvedDisplayValue,
986
991
  });
987
992
  if (propertyNameFromDb === 'storageTransactionId') {
988
- const { Item } = yield import('./index-NmD9sjcJ.js');
993
+ const { Item } = yield import('./index-BkzKfVvD.js');
989
994
  const item = yield Item.find({
990
995
  seedLocalId,
991
996
  modelName: itemModelName,
@@ -1092,6 +1097,35 @@ const createVersion = (_a) => __awaiter(void 0, [_a], void 0, function* ({ seedL
1092
1097
  return newVersionLocalId;
1093
1098
  });
1094
1099
 
1100
+ const createMetadata = (metadataValues, propertyRecordSchema) => __awaiter(void 0, void 0, void 0, function* () {
1101
+ const appDb = getAppDb();
1102
+ metadataValues.localId = generateId();
1103
+ if (propertyRecordSchema &&
1104
+ propertyRecordSchema.localStorageDir &&
1105
+ propertyRecordSchema.storageType === 'ItemStorage') {
1106
+ metadataValues.refResolvedValue = `${metadataValues.seedLocalId}${propertyRecordSchema.filenameSuffix}`;
1107
+ metadataValues.refValueType = 'file';
1108
+ }
1109
+ return appDb
1110
+ .insert(metadata)
1111
+ .values(Object.assign(Object.assign({}, metadataValues), { createdAt: Date.now(), updatedAt: Date.now() }))
1112
+ .returning();
1113
+ });
1114
+
1115
+ const modelStore = new Map();
1116
+ const getModels = () => {
1117
+ return Object.fromEntries(modelStore);
1118
+ };
1119
+ const getModel = (modelName) => {
1120
+ return modelStore.get(modelName);
1121
+ };
1122
+ const getModelNames = () => {
1123
+ return Array.from(modelStore.keys());
1124
+ };
1125
+ const setModel = (modelName, model) => {
1126
+ modelStore.set(modelName, model);
1127
+ };
1128
+
1095
1129
  const logger$l = debug('app:write');
1096
1130
  const sendItemUpdateEvent = ({ modelName, seedLocalId, seedUid }) => {
1097
1131
  if (!modelName || (!seedLocalId && !seedUid)) {
@@ -1111,19 +1145,36 @@ const createSeed = (_a) => __awaiter(void 0, [_a], void 0, function* ({ type, se
1111
1145
  return newSeedLocalId;
1112
1146
  });
1113
1147
  const createNewItem = (_a) => __awaiter(void 0, void 0, void 0, function* () {
1148
+ var _b;
1114
1149
  var { modelName } = _a, propertyData = __rest(_a, ["modelName"]);
1115
1150
  if (!modelName) {
1116
1151
  throw new Error('A model name is required for createNewItem');
1117
1152
  }
1118
- const appDb = getAppDb();
1153
+ getAppDb();
1119
1154
  const seedType = modelName.toLowerCase();
1120
1155
  const newSeedId = yield createSeed({ type: seedType });
1121
1156
  const newVersionId = yield createVersion({ seedLocalId: newSeedId });
1157
+ const propertySchemas = (_b = getModel(modelName)) === null || _b === void 0 ? void 0 : _b.schema;
1122
1158
  for (const [propertyName, propertyValue] of Object.entries(propertyData)) {
1123
- yield appDb.run(sql.raw(`INSERT INTO metadata (seed_local_id, version_local_id, property_name, property_value, model_type, created_at,
1124
- attestation_created_at)
1125
- VALUES ('${newSeedId}', '${newVersionId}', '${propertyName}', '${propertyValue}', '${seedType}', ${Date.now()},
1126
- ${Date.now()});`));
1159
+ let propertyRecordSchema;
1160
+ if (propertySchemas && propertySchemas[propertyName]) {
1161
+ propertyRecordSchema = propertySchemas[propertyName];
1162
+ }
1163
+ yield createMetadata({
1164
+ seedLocalId: newSeedId,
1165
+ versionLocalId: newVersionId,
1166
+ propertyName,
1167
+ propertyValue,
1168
+ modelName,
1169
+ }, propertyRecordSchema);
1170
+ // await appDb.run(
1171
+ // sql.raw(
1172
+ // `INSERT INTO metadata (seed_local_id, version_local_id, property_name, property_value, model_type, created_at,
1173
+ // attestation_created_at)
1174
+ // VALUES ('${newSeedId}', '${newVersionId}', '${propertyName}', '${propertyValue}', '${seedType}', ${Date.now()},
1175
+ // ${Date.now()});`,
1176
+ // ),
1177
+ // )
1127
1178
  }
1128
1179
  // eventEmitter.emit(`item.requestAll`, { modelName })
1129
1180
  return {
@@ -1417,20 +1468,255 @@ const updateMachineContext = {
1417
1468
  }),
1418
1469
  };
1419
1470
 
1420
- const modelStore = new Map();
1421
- const getModels = () => {
1422
- return Object.fromEntries(modelStore);
1423
- };
1424
- const getModel = (modelName) => {
1425
- return modelStore.get(modelName);
1426
- };
1427
- const getModelNames = () => {
1428
- return Array.from(modelStore.keys());
1429
- };
1430
- const setModel = (modelName, model) => {
1431
- modelStore.set(modelName, model);
1471
+ const readFileAsArrayBuffer = (file) => __awaiter(void 0, void 0, void 0, function* () {
1472
+ return new Promise((resolve) => {
1473
+ const reader = new FileReader();
1474
+ reader.onload = (e) => __awaiter(void 0, void 0, void 0, function* () {
1475
+ const arrayBuffer = e.target.result;
1476
+ resolve(arrayBuffer);
1477
+ });
1478
+ reader.readAsArrayBuffer(file);
1479
+ });
1480
+ });
1481
+ const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
1482
+ const response = yield fetch(url);
1483
+ const mimeType = response.headers.get('Content-Type');
1484
+ const imageBuffer = yield response.arrayBuffer();
1485
+ const bytes = new Uint8Array(imageBuffer);
1486
+ const binaryString = bytes.reduce((acc, byte) => acc + String.fromCharCode(byte), '');
1487
+ let base64 = btoa(binaryString);
1488
+ if (mimeType) {
1489
+ base64 = `data:${mimeType};base64,${base64}`;
1490
+ }
1491
+ return base64;
1492
+ });
1493
+ const saveImageSrc = fromCallback(({ sendBack, input: { context, event } }) => {
1494
+ const { localId, propertyName: propertyNameRaw, propertyValue: existingValue, propertyRecordSchema, itemModelName, seedLocalId, seedUid, versionLocalId, versionUid, schemaUid, } = context;
1495
+ let newValue;
1496
+ if (event) {
1497
+ newValue = event.newValue;
1498
+ }
1499
+ if (existingValue === newValue) {
1500
+ sendBack({ type: 'saveValueToDbSuccess' });
1501
+ return;
1502
+ }
1503
+ const _saveImageSrc = () => __awaiter(void 0, void 0, void 0, function* () {
1504
+ let propertyName = propertyNameRaw;
1505
+ if (!propertyNameRaw.endsWith('Id')) {
1506
+ propertyName = `${propertyName}Id`;
1507
+ }
1508
+ let newValueType;
1509
+ let fileData;
1510
+ let mimeType;
1511
+ let fileName;
1512
+ if (typeof newValue === 'string') {
1513
+ newValueType = getDataTypeFromString(newValue);
1514
+ }
1515
+ if (newValueType === 'imageBase64') {
1516
+ mimeType = getMimeType(newValue);
1517
+ }
1518
+ if (newValueType === 'url') {
1519
+ fileData = yield fetchImage(newValue);
1520
+ }
1521
+ if (newValue instanceof File) {
1522
+ fileName = newValue.name;
1523
+ mimeType = newValue.type;
1524
+ fileData = yield readFileAsArrayBuffer(newValue);
1525
+ }
1526
+ if (!fileData) {
1527
+ throw new Error('No file data found');
1528
+ }
1529
+ const newImageSeedLocalId = yield createSeed({
1530
+ type: 'image',
1531
+ });
1532
+ if (!fileName) {
1533
+ fileName = newImageSeedLocalId;
1534
+ if (mimeType) {
1535
+ fileName += `.${mimeType.split('/')[1]}`;
1536
+ }
1537
+ }
1538
+ const filePath = `/files/images/${fileName}`;
1539
+ yield createVersion({
1540
+ seedLocalId: newImageSeedLocalId,
1541
+ seedType: 'image',
1542
+ });
1543
+ if (fileData instanceof ArrayBuffer) {
1544
+ yield fs.promises.writeFile(filePath, new Uint8Array(fileData));
1545
+ }
1546
+ if (typeof fileData === 'string') {
1547
+ yield fs.promises.writeFile(filePath, fileData);
1548
+ }
1549
+ const refResolvedDisplayValue = yield getContentUrlFromPath(filePath);
1550
+ if (!localId) {
1551
+ yield createMetadata({
1552
+ propertyName,
1553
+ propertyValue: newImageSeedLocalId,
1554
+ seedLocalId,
1555
+ seedUid,
1556
+ versionLocalId,
1557
+ versionUid,
1558
+ modelName: itemModelName,
1559
+ schemaUid,
1560
+ refSeedType: 'image',
1561
+ refResolvedDisplayValue,
1562
+ refResolvedValue: fileName,
1563
+ }, propertyRecordSchema);
1564
+ }
1565
+ if (localId) {
1566
+ yield updateItemPropertyValue({
1567
+ propertyLocalId: localId,
1568
+ propertyName: propertyNameRaw,
1569
+ newValue: newImageSeedLocalId,
1570
+ seedLocalId,
1571
+ versionLocalId,
1572
+ modelName: itemModelName,
1573
+ schemaUid,
1574
+ refSeedType: 'image',
1575
+ refResolvedDisplayValue,
1576
+ refResolvedValue: fileName,
1577
+ });
1578
+ }
1579
+ sendBack({
1580
+ type: 'updateContext',
1581
+ propertyValue: newImageSeedLocalId,
1582
+ refSeedType: 'image',
1583
+ renderValue: refResolvedDisplayValue,
1584
+ resolvedDisplayValue: refResolvedDisplayValue,
1585
+ resolvedValue: fileName,
1586
+ });
1587
+ });
1588
+ _saveImageSrc().then(() => {
1589
+ sendBack({ type: 'saveImageSrcSuccess' });
1590
+ });
1591
+ });
1592
+
1593
+ const saveRelation = fromCallback(({ sendBack, input: { context, event } }) => {
1594
+ const { localId, propertyName: propertyNameRaw, versionLocalId, seedUid, seedLocalId, propertyValue: existingValue, propertyRecordSchema, } = context;
1595
+ if (!propertyRecordSchema) {
1596
+ throw new Error('Missing propertyRecordSchema');
1597
+ }
1598
+ let newValue;
1599
+ if (event) {
1600
+ newValue = event.newValue;
1601
+ }
1602
+ const _saveRelation = () => __awaiter(void 0, void 0, void 0, function* () {
1603
+ let propertyName = propertyNameRaw;
1604
+ if (!propertyName.endsWith('Id')) {
1605
+ propertyName = `${propertyName}Id`;
1606
+ }
1607
+ let newValueType;
1608
+ if (typeof newValue === 'string') {
1609
+ newValueType = getDataTypeFromString(newValue);
1610
+ }
1611
+ if (newValue instanceof File) {
1612
+ newValueType = 'file';
1613
+ }
1614
+ if (propertyRecordSchema.dataType === 'ImageSrc') {
1615
+ sendBack({
1616
+ type: 'saveImageSrc',
1617
+ newValue,
1618
+ newValueType,
1619
+ });
1620
+ return false;
1621
+ }
1622
+ return true;
1623
+ // let fileType
1624
+ //
1625
+ // const dirs = await fs.promises.readdir('/files')
1626
+ //
1627
+ // for (const dir of dirs) {
1628
+ // const files = await fs.promises.readdir(`/files/${dir}`)
1629
+ // if (newValue && files.includes(newValue as string)) {
1630
+ // fileType = dir
1631
+ // break
1632
+ // }
1633
+ // }
1634
+ //
1635
+ // if (newValue && fileType === 'images') {
1636
+ // const filePath = `/files/images/${newValue}`
1637
+ // refResolvedDisplayValue = await getContentUrlFromPath(filePath)
1638
+ // refSeedType = 'image'
1639
+ // newValue = await createSeed({
1640
+ // type: refSeedType,
1641
+ // })
1642
+ // await createVersion({
1643
+ // seedLocalId,
1644
+ // seedUid,
1645
+ // seedType: refSeedType,
1646
+ // })
1647
+ // }
1648
+ //
1649
+ // await updateItemPropertyValue({
1650
+ // propertyLocalId: localId,
1651
+ // propertyName,
1652
+ // newValue,
1653
+ // seedLocalId,
1654
+ // refSeedType,
1655
+ // refResolvedValue,
1656
+ // refResolvedDisplayValue,
1657
+ // versionLocalId,
1658
+ // modelName: itemModelName,
1659
+ // schemaUid,
1660
+ // })
1661
+ });
1662
+ _saveRelation().then((isDone) => {
1663
+ if (isDone) {
1664
+ sendBack({ type: 'saveRelationSuccess' });
1665
+ }
1666
+ });
1667
+ });
1668
+
1669
+ const getVersionData = () => {
1670
+ const appDb = getAppDb();
1671
+ return appDb.$with('versionData').as(appDb
1672
+ .select({
1673
+ seedLocalId: versions.seedLocalId,
1674
+ seedUid: versions.seedUid,
1675
+ latestVersionUid: versions.uid,
1676
+ latestVersionLocalId: versions.localId,
1677
+ versionsCount: count(versions.localId).as('versionsCount'),
1678
+ lastVersionPublishedAt: max(versions.attestationCreatedAt).as('lastVersionPublishedAt'),
1679
+ lastLocalUpdateAt: max(versions.createdAt).as('lastLocalUpdateAt'),
1680
+ })
1681
+ .from(versions)
1682
+ .groupBy(versions.seedLocalId));
1432
1683
  };
1433
1684
 
1685
+ const getItemsData = (_a) => __awaiter(void 0, [_a], void 0, function* ({ modelName, deleted, }) {
1686
+ const appDb = getAppDb();
1687
+ const conditions = [];
1688
+ if (modelName) {
1689
+ conditions.push(eq(seeds.type, modelName.toLowerCase()));
1690
+ }
1691
+ if (deleted) {
1692
+ conditions.push(or(isNotNull(seeds._markedForDeletion), eq(seeds._markedForDeletion, 1)));
1693
+ }
1694
+ if (!deleted) {
1695
+ conditions.push(or(isNull(seeds._markedForDeletion), eq(seeds._markedForDeletion, 0)));
1696
+ }
1697
+ const versionData = getVersionData();
1698
+ let query = appDb
1699
+ .with(versionData)
1700
+ .select({
1701
+ seedLocalId: seeds.localId,
1702
+ seedUid: seeds.uid,
1703
+ schemaUid: seeds.schemaUid,
1704
+ modelName: sql `${modelName}`,
1705
+ attestationCreatedAt: seeds.attestationCreatedAt,
1706
+ versionsCount: versionData.versionsCount,
1707
+ lastVersionPublishedAt: versionData.lastVersionPublishedAt,
1708
+ lastLocalUpdateAt: versionData.lastLocalUpdateAt,
1709
+ createdAt: seeds.createdAt,
1710
+ })
1711
+ .from(seeds)
1712
+ .leftJoin(versionData, eq(seeds.localId, versionData.seedLocalId))
1713
+ .where(and(...conditions))
1714
+ .orderBy(sql.raw('COALESCE(attestation_created_at, created_at) DESC'))
1715
+ .groupBy(seeds.localId);
1716
+ const itemsData = (yield query);
1717
+ return itemsData;
1718
+ });
1719
+
1434
1720
  var _a$2;
1435
1721
  const logger$k = debug('app:property:class');
1436
1722
  const namesThatEndWithId = [];
@@ -2613,7 +2899,7 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
2613
2899
  if (!models$1) {
2614
2900
  return;
2615
2901
  }
2616
- const { models: SeedModels } = yield import('./seed.schema.config-OyHsE0Zl.js');
2902
+ const { models: SeedModels } = yield import('./seed.schema.config-BHZSMMmL.js');
2617
2903
  const allModels = Object.assign(Object.assign({}, SeedModels), models$1);
2618
2904
  let hasModelsInDb = false;
2619
2905
  const schemaDefsByModelName = new Map();
@@ -3585,57 +3871,6 @@ const getArweave = () => {
3585
3871
  });
3586
3872
  };
3587
3873
 
3588
- const getVersionData = () => {
3589
- const appDb = getAppDb();
3590
- return appDb.$with('versionData').as(appDb
3591
- .select({
3592
- seedLocalId: versions.seedLocalId,
3593
- seedUid: versions.seedUid,
3594
- latestVersionUid: versions.uid,
3595
- latestVersionLocalId: versions.localId,
3596
- versionsCount: count(versions.localId).as('versionsCount'),
3597
- lastVersionPublishedAt: max(versions.attestationCreatedAt).as('lastVersionPublishedAt'),
3598
- lastLocalUpdateAt: max(versions.createdAt).as('lastLocalUpdateAt'),
3599
- })
3600
- .from(versions)
3601
- .groupBy(versions.seedLocalId));
3602
- };
3603
-
3604
- const getItemsData = (_a) => __awaiter(void 0, [_a], void 0, function* ({ modelName, deleted, }) {
3605
- const appDb = getAppDb();
3606
- const conditions = [];
3607
- if (modelName) {
3608
- conditions.push(eq(seeds.type, modelName.toLowerCase()));
3609
- }
3610
- if (deleted) {
3611
- conditions.push(or(isNotNull(seeds._markedForDeletion), eq(seeds._markedForDeletion, 1)));
3612
- }
3613
- if (!deleted) {
3614
- conditions.push(or(isNull(seeds._markedForDeletion), eq(seeds._markedForDeletion, 0)));
3615
- }
3616
- const versionData = getVersionData();
3617
- let query = appDb
3618
- .with(versionData)
3619
- .select({
3620
- seedLocalId: seeds.localId,
3621
- seedUid: seeds.uid,
3622
- schemaUid: seeds.schemaUid,
3623
- modelName: sql `${modelName}`,
3624
- attestationCreatedAt: seeds.attestationCreatedAt,
3625
- versionsCount: versionData.versionsCount,
3626
- lastVersionPublishedAt: versionData.lastVersionPublishedAt,
3627
- lastLocalUpdateAt: versionData.lastLocalUpdateAt,
3628
- createdAt: seeds.createdAt,
3629
- })
3630
- .from(seeds)
3631
- .leftJoin(versionData, eq(seeds.localId, versionData.seedLocalId))
3632
- .where(and(...conditions))
3633
- .orderBy(sql.raw('COALESCE(attestation_created_at, created_at) DESC'))
3634
- .groupBy(seeds.localId);
3635
- const itemsData = (yield query);
3636
- return itemsData;
3637
- });
3638
-
3639
3874
  const getMetadata = (props) => __awaiter(void 0, void 0, void 0, function* () {
3640
3875
  const appDb = getAppDb();
3641
3876
  let storageTransactionId;
@@ -3804,7 +4039,7 @@ const downloadAllFilesBinaryRequestHandler = () => __awaiter(void 0, void 0, voi
3804
4039
  if (contentType !== 'json' &&
3805
4040
  contentType !== 'base64' &&
3806
4041
  contentType !== 'html') {
3807
- const possibleImageType = getImageDataType(dataString);
4042
+ const possibleImageType = getDataTypeFromString(dataString);
3808
4043
  if (!possibleImageType) {
3809
4044
  logger$b(`[fetchAll/actors] [fetchAllBinaryData] transaction ${transactionId} data not in expected format: ${possibleImageType}`);
3810
4045
  continue;
@@ -4822,1806 +5057,1802 @@ const createPublishAttempt = fromCallback(({ sendBack, input: { context } }) =>
4822
5057
  });
4823
5058
  });
4824
5059
 
4825
- const logger$5 = debug('app:react:services');
4826
- const finalStrings = ['idle', 'ready', 'done', 'success'];
4827
- const getServiceName = (service) => {
4828
- let name = 'actor';
4829
- if (service && service.uniqueKey) {
4830
- name = service.uniqueKey;
4831
- }
4832
- if (service && !service.uniqueKey && service.logic && service.logic.config) {
4833
- name = getServiceUniqueKey(service);
4834
- }
4835
- return name;
4836
- };
4837
- const getServiceValue = (service) => {
4838
- let value;
4839
- if (service && service.getSnapshot() && service.getSnapshot().value) {
4840
- value = service.getSnapshot().value;
4841
- }
4842
- if (getServiceName(service) === 'global') {
4843
- if (value &&
4844
- typeof value === 'object' &&
4845
- Object.keys(value).length > 0 &&
4846
- Object.keys(value)[0] === 'initialized') {
4847
- value = 'ready';
4848
- }
4849
- }
4850
- if (value && typeof value === 'object') {
4851
- value = JSON.stringify(value);
4852
- }
4853
- return value;
4854
- };
4855
- const getServiceUniqueKey = (service) => {
4856
- if (!service || !service.logic || !service.logic.config) {
4857
- return;
4858
- }
4859
- const config = service.logic.config;
4860
- if (!config.id) {
4861
- return;
4862
- }
4863
- let uniqueKey = config.id;
4864
- if (config.id.includes('@seedSdk/')) {
4865
- uniqueKey = config.id.match(/^.*@seedSdk\/(\w+)[\.\w]*/)[1];
4866
- }
4867
- let snapshot;
4868
- try {
4869
- snapshot = service.getSnapshot();
4870
- }
4871
- catch (error) {
4872
- logger$5('Error:', error);
4873
- return uniqueKey;
4874
- }
4875
- if (snapshot) {
4876
- const context = snapshot.context;
4877
- if (context && context.dbName) {
4878
- uniqueKey = context.dbName;
5060
+ const preparePublishRequestData = fromCallback(({ sendBack, input: { context } }) => {
5061
+ const { localId } = context;
5062
+ const _preparePublishRequestData = () => __awaiter(void 0, void 0, void 0, function* () {
5063
+ const item = yield Item.find({ seedLocalId: localId });
5064
+ if (!item) {
5065
+ return false;
4879
5066
  }
4880
- if (context && context.modelNamePlural) {
4881
- uniqueKey = context.modelNamePlural;
5067
+ const appDb = getAppDb();
5068
+ const modelsRows = yield appDb
5069
+ .select({
5070
+ modelName: models.name,
5071
+ schemaUid: modelUids.uid,
5072
+ })
5073
+ .from(models)
5074
+ .leftJoin(modelUids, eq(modelUids.modelId, models.id))
5075
+ .where(eq(models.name, 'Version'));
5076
+ if (!modelsRows || modelsRows.length === 0) {
5077
+ sendBack({ type: 'preparePublishRequestDataError' });
5078
+ return false;
4882
5079
  }
4883
- if (context && context.modelName) {
4884
- uniqueKey = pluralize(context.modelName.toLowerCase());
5080
+ const versionSchemaUid = modelsRows[0].schemaUid;
5081
+ yield item.getEditedProperties();
5082
+ yield getModelSchemas();
5083
+ // const dataEncoder = new SchemaEncoder(modelProperty.schemaDefinition,)
5084
+ // const encodedData = dataEncoder.encodeData(data,)
5085
+ //
5086
+ // itemData.listOfAttestations.push({
5087
+ // schema : modelProperty.schemaUid,
5088
+ // data : [
5089
+ // {
5090
+ // ...defaultAttestationData,
5091
+ // data : encodedData,
5092
+ // },
5093
+ // ],
5094
+ // },)
5095
+ const publishRequestData = {
5096
+ seedIsRevocable: false,
5097
+ seedSchemaUid: item.schemaUid,
5098
+ seedUid: item.seedUid,
5099
+ versionSchemaUid,
5100
+ versionUid: item.latestVersionUid,
5101
+ listOfAttestations: [],
5102
+ };
5103
+ sendBack(Object.assign({ type: 'updateContext' }, publishRequestData));
5104
+ return true;
5105
+ });
5106
+ _preparePublishRequestData().then((success) => {
5107
+ if (success) {
5108
+ sendBack({ type: 'preparePublishRequestDataSuccess' });
4885
5109
  }
4886
- }
4887
- return uniqueKey;
4888
- };
4889
- const useIsDbReady = () => {
4890
- const [isDbReady, setIsDbReady] = useState(false);
4891
- const { internalStatus } = useGlobalServiceStatus();
4892
- useEffect(() => {
4893
- if (internalStatus === 'ready') {
4894
- setIsDbReady(true);
5110
+ });
5111
+ });
5112
+
5113
+ const logger$5 = debug('app:services:publish:actors:upload');
5114
+ const upload = fromCallback(({ sendBack, input: { context } }) => {
5115
+ const { localId } = context;
5116
+ const _upload = () => __awaiter(void 0, void 0, void 0, function* () {
5117
+ const item = yield Item.find({ seedLocalId: localId });
5118
+ if (!item) {
5119
+ logger$5('no item with localId', localId);
5120
+ return false;
4895
5121
  }
4896
- }, [internalStatus]);
4897
- return isDbReady;
4898
- };
4899
- const useServices = () => {
4900
- const [actors, setActors] = useState([]);
4901
- const [percentComplete, setPercentComplete] = useState(5);
4902
- const actorsMap = new Map();
4903
- useEffect(() => {
4904
- const globalServiceListener = (event) => {
4905
- if (event && event.type === 'init') {
4906
- return;
5122
+ const editedProperties = yield item.getEditedProperties();
5123
+ for (const propertyData of editedProperties) {
5124
+ if (propertyData.refSeedType === 'image') ;
5125
+ }
5126
+ const uploadItems = [];
5127
+ for (const editedPropertyData of editedProperties) {
5128
+ const propertyName = editedPropertyData.propertyName;
5129
+ const editedProperty = item.properties[propertyName];
5130
+ if (!editedProperty || !editedProperty.propertyDef) {
5131
+ continue;
4907
5132
  }
4908
- if (event.actorRef &&
4909
- event.actorRef.logic &&
4910
- event.actorRef.logic.config) {
4911
- const service = event.actorRef;
4912
- const services = [service];
4913
- if (service.logic.config.id === MachineIds.GLOBAL) {
4914
- const context = service.getSnapshot().context;
4915
- const keys = Object.keys(context);
4916
- for (const key of keys) {
4917
- if (!key.startsWith('internal') && key.endsWith('Service')) {
4918
- const allItemsService = context[key];
4919
- services.push(allItemsService);
4920
- }
4921
- }
4922
- }
4923
- services.forEach((innerService) => {
4924
- const uniqueKey = getServiceUniqueKey(innerService);
4925
- if (!uniqueKey) {
4926
- return;
4927
- }
4928
- innerService.uniqueKey = uniqueKey;
4929
- actorsMap.set(uniqueKey, innerService);
4930
- });
4931
- let actorsArray = Array.from(actorsMap.values());
4932
- actorsArray = orderBy(actorsArray, (a) => a.logic.config.id, ['asc']);
4933
- setActors(produce(actors, (draft) => {
4934
- return actorsArray;
4935
- }));
5133
+ if (editedProperty.propertyDef.refValueType &&
5134
+ editedProperty.propertyDef.refValueType === 'ImageSrc') {
5135
+ const context = editedProperty.getService().getSnapshot().context;
5136
+ const imageSeedId = context.propertyValue;
5137
+ getCorrectId(imageSeedId);
4936
5138
  }
4937
- };
4938
- eventEmitter.addListener('inspect.globalService', globalServiceListener);
4939
- return () => {
4940
- eventEmitter.removeListener('inspect.globalService', globalServiceListener);
4941
- };
4942
- }, []);
4943
- useEffect(() => {
4944
- const globalService = actors.find((actor) => getServiceName(actor) === 'global');
4945
- const internalService = actors.find((actor) => getServiceName(actor) === 'internal');
4946
- if (!globalService || !internalService) {
4947
- return;
5139
+ if (editedProperty.propertyDef.storageType === 'ItemStorage' &&
5140
+ editedProperty.propertyDef.localStorageDir) ;
4948
5141
  }
4949
- if (getServiceValue(globalService) === 'ready' &&
4950
- getServiceValue(internalService) === 'ready') {
4951
- const denominator = actors.length;
4952
- const finishedActors = actors.filter((actor) => {
4953
- const value = getServiceValue(actor);
4954
- return finalStrings.includes(value);
4955
- });
4956
- const numerator = finishedActors.length;
4957
- const percentComplete = (numerator / denominator) * 100;
4958
- setPercentComplete(percentComplete);
5142
+ if (uploadItems.length === 0) {
5143
+ return true;
4959
5144
  }
4960
- }, [actors]);
4961
- return {
4962
- services: actors,
4963
- percentComplete,
4964
- };
4965
- };
4966
- const useGlobalServiceStatus = () => {
4967
- const globalService = getGlobalService();
4968
- const status = useSelector(globalService, (snapshot) => {
4969
- return snapshot.value;
5145
+ // const turbo = TurboFactory.unauthenticated()
5146
+ // turbo.uploadSignedDataItem()
5147
+ //
5148
+ // const { id, owner, dataCaches, fastFinalityIndexes } = await turbo.uploadFile(() => {
5149
+ // fileStreamFactory => () => fs.createReadStream(filePath),
5150
+ // fileSizeFactory => () => fileSize,
5151
+ // });
5152
+ return false;
4970
5153
  });
4971
- const internalStatus = useSelector(globalService.getSnapshot().context.internalService, (snapshot) => {
4972
- if (!snapshot) {
4973
- return;
5154
+ _upload().then((isValid) => {
5155
+ if (isValid) {
5156
+ sendBack({ type: 'uploadSuccess' });
4974
5157
  }
4975
- return snapshot.value;
4976
- });
4977
- useSelector(globalService, (snapshot) => {
4978
- return snapshot.context.internalService;
4979
5158
  });
4980
- return {
4981
- status,
4982
- internalStatus,
4983
- };
4984
- };
5159
+ });
4985
5160
 
4986
- const logger$4 = debug('app:react:item');
4987
- const useItem = ({ modelName, seedLocalId, seedUid }) => {
4988
- const [itemData, setItemData] = useImmer({});
4989
- const [item, setItem] = useState();
4990
- const [itemSubscription, setItemSubscription] = useState();
4991
- const { status, internalStatus } = useGlobalServiceStatus();
4992
- const isReadingDb = useRef(false);
4993
- const itemStatus = useSelector(item === null || item === void 0 ? void 0 : item.getService(), (snapshot) => snapshot === null || snapshot === void 0 ? void 0 : snapshot.value);
4994
- const updateItem = useCallback((newItem) => {
4995
- setItemData((draft) => {
4996
- Object.keys(newItem.properties).forEach((propertyName) => {
4997
- const value = newItem[propertyName];
4998
- draft[propertyName] = value;
4999
- });
5000
- });
5001
- }, []);
5002
- const readFromDb = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
5003
- if (isReadingDb.current ||
5004
- internalStatus !== 'ready' ||
5005
- (!seedUid && !seedLocalId)) {
5006
- return;
5007
- }
5008
- isReadingDb.current = true;
5009
- const foundItem = yield Item.find({
5010
- modelName,
5011
- seedLocalId,
5012
- seedUid,
5013
- });
5014
- if (!foundItem) {
5015
- logger$4('[useItem] [getItemFromDb] no item found', modelName, seedLocalId);
5016
- return;
5017
- }
5018
- setItem(foundItem);
5019
- updateItem(foundItem);
5020
- isReadingDb.current = false;
5021
- }), [internalStatus]);
5022
- const listenerRef = useRef(readFromDb);
5023
- useEffect(() => {
5024
- listenerRef.current = readFromDb;
5025
- }, [readFromDb]);
5026
- useEffect(() => {
5027
- if (internalStatus === 'ready') {
5028
- listenerRef.current();
5029
- }
5030
- }, [internalStatus, status]);
5031
- useEffect(() => {
5032
- if (item && !itemSubscription) {
5033
- const subscription = item.subscribe((_) => __awaiter(void 0, void 0, void 0, function* () {
5034
- const newItem = yield Item.find({ modelName, seedLocalId, seedUid });
5035
- if (!newItem) {
5036
- logger$4('[useItem] [itemSubscription] no item found', modelName, seedLocalId);
5037
- return;
5038
- }
5039
- updateItem(newItem);
5040
- setItem(newItem);
5041
- }));
5042
- setItemSubscription(subscription);
5043
- }
5044
- return () => {
5045
- itemSubscription === null || itemSubscription === void 0 ? void 0 : itemSubscription.unsubscribe();
5046
- };
5047
- }, [item, itemSubscription]);
5048
- useEffect(() => {
5049
- const seedId = seedUid || seedLocalId;
5050
- eventEmitter.addListener(`item.${modelName}.${seedId}.update`, () => {
5051
- listenerRef.current();
5052
- });
5053
- return () => {
5054
- eventEmitter.removeListener(`item.${modelName}.${seedId}.update`, readFromDb);
5055
- };
5056
- }, []);
5057
- return {
5058
- item,
5059
- itemData,
5060
- itemStatus,
5061
- };
5062
- };
5063
- const useItems = ({ modelName, deleted }) => {
5064
- const [items, setItems] = useImmer([]);
5065
- const [isReadingDb, setIsReadingDb] = useState(false);
5066
- const [isInitialized, setIsInitialized] = useState(false);
5067
- const isDbReady = useIsDbReady();
5068
- const modelNameRef = useRef(modelName);
5069
- const readFromDb = useCallback((event) => __awaiter(void 0, void 0, void 0, function* () {
5070
- if (!event ||
5071
- !event.modelName ||
5072
- event.modelName !== modelNameRef.current ||
5073
- isReadingDb) {
5074
- return;
5075
- }
5076
- setIsReadingDb(true);
5077
- const allItems = yield Item.all(modelNameRef.current, deleted);
5078
- setItems(() => allItems);
5079
- setIsReadingDb(false);
5080
- }), [modelName, isReadingDb]);
5081
- useEffect(() => {
5082
- if (isDbReady && !isInitialized) {
5083
- const _fetchItems = () => __awaiter(void 0, void 0, void 0, function* () {
5084
- yield readFromDb({ modelName });
5085
- setIsInitialized(true);
5086
- });
5087
- _fetchItems();
5088
- }
5089
- }, [isInitialized, isDbReady]);
5090
- useEffect(() => {
5091
- eventEmitter.addListener('item.requestAll', readFromDb);
5092
- return () => {
5093
- eventEmitter.removeListener('item.requestAll');
5094
- };
5095
- }, []);
5096
- return {
5097
- items: orderBy(items, [
5098
- (item) => item.lastVersionPublishedAt ||
5099
- item.attestationCreatedAt ||
5100
- item.createdAt,
5101
- ], ['desc']).slice(0, 10),
5102
- isReadingDb,
5103
- isInitialized,
5104
- };
5105
- };
5106
- const useItemIsReady = () => {
5107
- const [itemListenersReady, setItemListenersReady] = useState(false);
5108
- const itemEventListenersHandler = useCallback((_) => {
5109
- setItemListenersReady(true);
5110
- }, []);
5111
- useEffect(() => {
5112
- const areReady = getAreItemEventHandlersReady();
5113
- if (areReady) {
5114
- itemEventListenersHandler(true);
5115
- }
5116
- eventEmitter.addListener('item.events.setupAllItemsEventHandlers', itemEventListenersHandler);
5117
- return () => {
5118
- eventEmitter.removeListener('item.events.setupAllItemsEventHandlers');
5119
- };
5120
- }, []);
5121
- return {
5122
- isReady: itemListenersReady,
5123
- };
5124
- };
5125
- const useCreateItem = (modelName) => {
5126
- const [isCreatingItem, setIsCreatingItem] = useState(false);
5127
- const { isReady } = useItemIsReady();
5128
- const createItem = useCallback((itemData) => __awaiter(void 0, void 0, void 0, function* () {
5129
- if (!isReady) {
5130
- console.error(`[useCreateItem] [createItem] called before listeners are ready`, itemData);
5131
- return;
5132
- }
5133
- if (isCreatingItem) {
5134
- // TODO: should we setup a queue for this?
5135
- console.error(`[useCreateItem] [createItem] already creating item`, itemData);
5136
- return;
5137
- }
5138
- setIsCreatingItem(true);
5139
- const { seedLocalId } = yield createNewItem(Object.assign({ modelName }, itemData));
5140
- yield Item.find({ modelName, seedLocalId });
5141
- eventEmitter.emit('item.requestAll', { modelName });
5142
- setIsCreatingItem(false);
5143
- }), [isCreatingItem, isReady]);
5144
- return {
5145
- createItem,
5146
- isCreatingItem,
5147
- };
5148
- };
5161
+ const { VALIDATING_ITEM_DATA, CREATING_PUBLISH_ATTEMPT, PREPARING_PUBLISH_REQUEST_DATA, UPLOADING, PUBLISHING, IDLE, } = PublishMachineStates;
5162
+ const publishMachine = setup({
5163
+ types: {
5164
+ context: {},
5165
+ input: {},
5166
+ },
5167
+ actors: {
5168
+ validateItemData,
5169
+ createPublishAttempt,
5170
+ upload,
5171
+ preparePublishRequestData,
5172
+ },
5173
+ }).createMachine({
5174
+ id: 'publish',
5175
+ initial: VALIDATING_ITEM_DATA,
5176
+ context: ({ input }) => input,
5177
+ on: {
5178
+ updateContext: updateMachineContext,
5179
+ },
5180
+ states: {
5181
+ [VALIDATING_ITEM_DATA]: {
5182
+ on: {
5183
+ validateItemDataSuccess: [CREATING_PUBLISH_ATTEMPT],
5184
+ },
5185
+ invoke: {
5186
+ src: 'validateItemData',
5187
+ input: ({ context }) => ({ context }),
5188
+ },
5189
+ },
5190
+ [CREATING_PUBLISH_ATTEMPT]: {
5191
+ on: {
5192
+ createPublishAttemptSuccess: [UPLOADING],
5193
+ },
5194
+ invoke: {
5195
+ src: 'createPublishAttempt',
5196
+ input: ({ context }) => ({ context }),
5197
+ },
5198
+ },
5199
+ [UPLOADING]: {
5200
+ on: {
5201
+ uploadingSuccess: [PREPARING_PUBLISH_REQUEST_DATA],
5202
+ },
5203
+ invoke: {
5204
+ src: 'upload',
5205
+ input: ({ context }) => ({ context }),
5206
+ },
5207
+ },
5208
+ [PREPARING_PUBLISH_REQUEST_DATA]: {
5209
+ on: {
5210
+ preparePublishRequestDataSuccess: [UPLOADING],
5211
+ },
5212
+ invoke: {
5213
+ src: 'preparePublishRequestData',
5214
+ input: ({ context }) => ({ context }),
5215
+ },
5216
+ },
5217
+ [PUBLISHING]: {},
5218
+ [IDLE]: {},
5219
+ },
5220
+ });
5221
+
5222
+ const { UNINITIALIZED, INITIALIZING, INITIALIZED, PUBLISHING_ITEM, ADDING_MODELS_TO_DB, } = GlobalState;
5223
+ createBrowserInspector({
5224
+ autoStart: false,
5225
+ });
5226
+ const globalMachine = setup({
5227
+ types: {
5228
+ context: {},
5229
+ input: {},
5230
+ },
5231
+ actors: {
5232
+ initialize: initialize$1,
5233
+ addModelsToDb,
5234
+ getSchemaForModel,
5235
+ },
5236
+ }).createMachine({
5237
+ id: MachineIds.GLOBAL,
5238
+ initial: UNINITIALIZED,
5239
+ context: ({ input }) => input,
5240
+ states: {
5241
+ [UNINITIALIZED]: {
5242
+ on: {
5243
+ init: {
5244
+ target: INITIALIZING,
5245
+ guard: ({ context }) => {
5246
+ return typeof window !== 'undefined';
5247
+ },
5248
+ actions: [
5249
+ assign({
5250
+ isInitialized: false,
5251
+ addedModelRecordsToDb: false,
5252
+ models: ({ event }) => event.models,
5253
+ endpoints: ({ event }) => event.endpoints,
5254
+ internalService: ({ spawn, context }) => {
5255
+ return spawn(internalMachine, {
5256
+ systemId: MachineIds.INTERNAL,
5257
+ input: {
5258
+ endpoints: context.endpoints,
5259
+ },
5260
+ });
5261
+ },
5262
+ }),
5263
+ ],
5264
+ },
5265
+ },
5266
+ meta: {
5267
+ displayText: 'Booting up',
5268
+ percentComplete: 5,
5269
+ },
5270
+ tags: ['loading'],
5271
+ },
5272
+ [INITIALIZING]: {
5273
+ on: {
5274
+ [GLOBAL_INITIALIZING_SEND_CONFIG]: {
5275
+ actions: assign({
5276
+ endpoints: ({ event }) => event.endpoints,
5277
+ environment: ({ event }) => event.environment,
5278
+ addresses: ({ event }) => event.addresses,
5279
+ isInitialized: true,
5280
+ }),
5281
+ },
5282
+ [GLOBAL_INITIALIZING_INTERNAL_SERVICE_READY]: ADDING_MODELS_TO_DB,
5283
+ [GLOBAL_INITIALIZING_CREATE_ALL_ITEMS_SERVICES]: {
5284
+ actions: [
5285
+ assign(({ event, spawn }) => {
5286
+ const allItemsServices = {};
5287
+ for (const [modelName, ModelClass] of Object.entries(event.create)) {
5288
+ const service = spawn(itemMachineAll, {
5289
+ systemId: modelName,
5290
+ input: {
5291
+ modelName,
5292
+ ModelClass,
5293
+ modelSchema: ModelClass.schema,
5294
+ items: [],
5295
+ },
5296
+ });
5297
+ allItemsServices[`${modelName}Service`] = service;
5298
+ }
5299
+ for (const [modelName, snapshot] of Object.entries(event.restore)) {
5300
+ const service = createActor(itemMachineAll, {
5301
+ snapshot,
5302
+ });
5303
+ service.start();
5304
+ allItemsServices[`${modelName}Service`] = service;
5305
+ }
5306
+ return allItemsServices;
5307
+ }),
5308
+ raise({ type: 'allItemsServicesCreated' }),
5309
+ ],
5310
+ },
5311
+ },
5312
+ invoke: {
5313
+ src: 'initialize',
5314
+ input: ({ event, context }) => ({ event, context }),
5315
+ meta: {
5316
+ displayText: 'Initializing Seed SDK',
5317
+ percentComplete: 10,
5318
+ },
5319
+ tags: ['loading'],
5320
+ },
5321
+ },
5322
+ [ADDING_MODELS_TO_DB]: {
5323
+ on: {
5324
+ [GLOBAL_ADDING_MODELS_TO_DB_SUCCESS]: {
5325
+ target: INITIALIZED,
5326
+ actions: assign({
5327
+ addedModelRecordsToDb: true,
5328
+ }),
5329
+ },
5330
+ },
5331
+ invoke: {
5332
+ src: 'addModelsToDb',
5333
+ input: ({ context }) => ({ context }),
5334
+ meta: {
5335
+ displayText: 'Adding models to database',
5336
+ },
5337
+ tags: ['loading'],
5338
+ },
5339
+ },
5340
+ [INITIALIZED]: {
5341
+ type: 'parallel',
5342
+ on: {
5343
+ publishItemRequest: `.${PUBLISHING_ITEM}`,
5344
+ },
5345
+ meta: {
5346
+ displayText: 'Global service ready',
5347
+ percentComplete: 40,
5348
+ },
5349
+ tags: ['loading'],
5350
+ states: {
5351
+ [PUBLISHING_ITEM]: {
5352
+ entry: [
5353
+ assign({
5354
+ publishItemService: ({ spawn, event }) => spawn(publishMachine, {
5355
+ id: 'publishService',
5356
+ input: {
5357
+ modelName: event.modelName,
5358
+ localId: event.seedLocalId,
5359
+ },
5360
+ }),
5361
+ }),
5362
+ ],
5363
+ meta: {
5364
+ displayText: 'Publishing item',
5365
+ },
5366
+ tags: ['publishing'],
5367
+ },
5368
+ },
5369
+ },
5370
+ },
5371
+ // on: {
5372
+ // '*': {
5373
+ // actions: emit(({ event }) => {
5374
+ // return event
5375
+ // }),
5376
+ // },
5377
+ // },
5378
+ });
5379
+ const globalService = createActor(globalMachine, {
5380
+ input: {},
5381
+ // inspect,
5382
+ inspect: (inspEvent) => {
5383
+ eventEmitter.emit('inspect.globalService', inspEvent);
5384
+ // console.log('[sdk] [service/index] inspEvent', inspEvent)
5385
+ // eventEmitter.emit('globalService', inspEvent)
5386
+ // let eventType: string = inspEvent.type
5387
+ // if (inspEvent.event && inspEvent.event.type) {
5388
+ // eventType = inspEvent.event.type
5389
+ // }
5390
+ //
5391
+ // if (typeof eventType === 'object') {
5392
+ // eventType = JSON.stringify(eventType)
5393
+ // }
5394
+ //
5395
+ // let srcId = inspEvent.actorRef.id
5396
+ //
5397
+ // if (!srcId.includes('seedSdk')) {
5398
+ // srcId = inspEvent.actorRef.logic.config.id
5399
+ // }
5400
+ //
5401
+ // if (inspEvent.type === '@xstate.snapshot') {
5402
+ // if (
5403
+ // inspEvent.event.type === CHILD_SNAPSHOT &&
5404
+ // inspEvent.snapshot &&
5405
+ // inspEvent.snapshot.machine.id === MachineIds.GLOBAL
5406
+ // ) {
5407
+ // return
5408
+ // }
5409
+ // if (inspEvent.snapshot && inspEvent.snapshot.value) {
5410
+ // if (typeof window !== 'undefined') {
5411
+ // eventEmitter.emit('globalService', {
5412
+ // type: eventType,
5413
+ // src: srcId,
5414
+ // snapshot: inspEvent.snapshot,
5415
+ // })
5416
+ // }
5417
+ // }
5418
+ // } else {
5419
+ // if (typeof window !== 'undefined') {
5420
+ // let snapshot
5421
+ //
5422
+ // try {
5423
+ // snapshot = inspEvent.actorRef.getSnapshot()
5424
+ // } catch (e) {
5425
+ // // This fails if the actor hasn't initialized yet, but that's OK I think
5426
+ // // console.log('[sdk] [service/index] ERROR', e)
5427
+ // }
5428
+ //
5429
+ // eventEmitter.emit('globalService', {
5430
+ // type: eventType,
5431
+ // src: srcId,
5432
+ // snapshot,
5433
+ // })
5434
+ // }
5435
+ // }
5436
+ },
5437
+ });
5438
+ globalService.start();
5439
+ const getGlobalService = () => globalService;
5149
5440
 
5150
- const logger$3 = debug('app:react:property');
5151
- const useItemProperty = ({ propertyName, seedLocalId, seedUid, }) => {
5152
- const [property, setProperty] = useState();
5153
- const [isReadingFromDb, setIsReadingFromDb] = useState(false);
5154
- const [isInitialized, setIsInitialized] = useState(false);
5155
- // const isDbReady = useMemo(() => useIsDbReady(), [])
5156
- const { internalStatus } = useGlobalServiceStatus();
5157
- const value = useSelector(property === null || property === void 0 ? void 0 : property.getService(), (snapshot) => {
5158
- if (!snapshot || !snapshot.context) {
5441
+ const publishItemRequestHandler = (_a) => __awaiter(void 0, [_a], void 0, function* ({ modelName, seedLocalId, }) {
5442
+ const globalService = getGlobalService();
5443
+ globalService.subscribe((snapshot) => {
5444
+ if (!snapshot ||
5445
+ !snapshot.context ||
5446
+ !snapshot.context.publishItemService) {
5159
5447
  return;
5160
5448
  }
5161
- return snapshot.context.renderValue || snapshot.context.propertyValue;
5162
5449
  });
5163
- const status = useSelector(property === null || property === void 0 ? void 0 : property.getService(), (snapshot) => snapshot === null || snapshot === void 0 ? void 0 : snapshot.value);
5164
- // useEffect(() => {
5165
- // if (property && property.value !== value) {
5166
- // readFromDb()
5167
- // }
5168
- // }, [property, value])
5169
- const readFromDb = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
5170
- if (internalStatus !== 'ready' ||
5171
- isReadingFromDb ||
5172
- (!seedLocalId && !seedUid)) {
5173
- return;
5174
- }
5175
- setIsReadingFromDb(true);
5176
- const foundProperty = yield ItemProperty.find({
5177
- propertyName,
5178
- seedLocalId,
5179
- seedUid,
5180
- });
5181
- setIsReadingFromDb(false);
5182
- if (!foundProperty) {
5183
- logger$3(`[useItemPropertyTest] [readFromDb] no property found for Item.${seedLocalId}.${propertyName}`);
5184
- return;
5185
- }
5186
- if (foundProperty.status === 'waitingForDb') {
5187
- foundProperty.getService().send({ type: 'waitForDbSuccess' });
5188
- }
5189
- setProperty(foundProperty);
5190
- setIsInitialized(true);
5191
- }), [internalStatus, isReadingFromDb]);
5192
- // let count = 0
5193
- //
5194
- // const refresh = useCallback(() => {
5195
- // count++
5196
- // console.log('[useItemPropertyTest] [refresh] property', property)
5197
- // }, [property])
5198
- useEffect(() => {
5199
- if (internalStatus === 'ready') {
5200
- readFromDb();
5201
- }
5202
- }, [internalStatus]);
5203
- // useEffect(() => {
5204
- // eventEmitter.addListener(
5205
- // `property.${seedUid || seedLocalId}.${propertyName}.update`,
5206
- // (event) => {
5207
- // refresh()
5208
- // },
5209
- // )
5210
- //
5211
- // return () => {
5212
- // eventEmitter.removeListener(
5213
- // `property.${seedUid || seedLocalId}.${propertyName}.update`,
5214
- // )
5215
- // }
5216
- // }, [])
5217
- return {
5218
- property,
5219
- isInitialized,
5220
- isReadingFromDb,
5221
- value,
5222
- status,
5223
- };
5224
- };
5225
- const useItemProperties = (item) => {
5226
- const [propertyObj, setPropertyObj] = useImmer({});
5227
- useState(false);
5228
- const updatePropertyObj = useCallback((event) => {
5229
- if (!item) {
5230
- console.error('[XXXXXX] [updatePropertyObj] no item when expected');
5231
- return;
5232
- }
5233
- const { propertyName, propertyValue } = event;
5234
- if (!propertyName) {
5235
- return;
5236
- }
5237
- setPropertyObj((draft) => {
5238
- draft[propertyName] = propertyValue;
5239
- });
5240
- }, [item]);
5241
- useEffect(() => {
5242
- if (!item) {
5243
- return;
5244
- }
5245
- const eventKey = `item.${item.seedLocalId}.property.update`;
5246
- eventEmitter.addListener(eventKey, updatePropertyObj);
5247
- return () => {
5248
- eventEmitter.removeListener(eventKey, updatePropertyObj);
5249
- };
5250
- }, [item]);
5251
- return {
5252
- properties: propertyObj,
5253
- };
5254
- };
5255
-
5256
- debug('app:react:db');
5257
-
5258
- const deleteItem = (_a) => __awaiter(void 0, [_a], void 0, function* ({ seedLocalId, seedUid }) {
5259
- const appDb = getAppDb();
5260
- yield appDb
5261
- .update(seeds)
5262
- .set({
5263
- _markedForDeletion: 1,
5264
- })
5265
- .where(or(eq(seeds.localId, seedLocalId), eq(seeds.uid, seedUid)));
5450
+ globalService.send({
5451
+ type: 'publishItemRequest',
5452
+ modelName,
5453
+ seedLocalId,
5454
+ });
5266
5455
  });
5267
5456
 
5268
- const useDeleteItem = () => {
5269
- const [isDeletingItem, setIsDeletingItem] = useState(false);
5270
- const destroy = useCallback((item) => __awaiter(void 0, void 0, void 0, function* () {
5271
- if (!item) {
5272
- return;
5273
- }
5274
- setIsDeletingItem(true);
5275
- const { modelName } = item.getService().getSnapshot().context;
5276
- yield deleteItem({ seedLocalId: item.seedLocalId });
5277
- eventEmitter.emit('item.requestAll', { modelName });
5278
- setIsDeletingItem(false);
5279
- }), [isDeletingItem]);
5280
- useEffect(() => { }, []);
5281
- return {
5282
- deleteItem: destroy,
5283
- isDeletingItem,
5284
- };
5285
- };
5286
-
5287
- const logger$2 = debug('app:services:events');
5288
- const handleServiceSaveState = (event) => {
5289
- const { state, serviceId } = event;
5290
- logger$2(`[browser] [service.saveState.request] serviceId: ${serviceId}`);
5291
- localStorage.setItem(`seed_sdk_service_${serviceId}`, JSON.stringify(state));
5292
- };
5293
- const setupServicesEventHandlers = () => {
5294
- eventEmitter.addListener('service.saveState.request', handleServiceSaveState);
5457
+ let areReady = false;
5458
+ const setupAllItemsEventHandlers = () => {
5459
+ // eventEmitter.addListener('item.request', itemRequestHandler)
5460
+ // eventEmitter.addListener('item.requestAll', itemRequestAllHandler)
5461
+ // eventEmitter.addListener(
5462
+ // 'item.propertyValuesForSeedUid.request',
5463
+ // propertyValuesForSeedUid,
5464
+ // )
5465
+ // eventEmitter.addListener('item.create.request', createItemRequestHandler)
5466
+ // eventEmitter.addListener('item.delete.request', itemDeleteRequestHandler)
5467
+ // eventEmitter.addListener('item.update', itemUpdateHandler)
5468
+ eventEmitter.addListener('syncDbWithEas', syncDbWithEasHandler);
5469
+ eventEmitter.addListener('item.publish.request', publishItemRequestHandler);
5470
+ //
5471
+ // eventEmitter.emit('item.events.setupAllItemsEventHandlers')
5472
+ areReady = true;
5295
5473
  };
5296
-
5297
- const saveServiceHandler = (event) => __awaiter(void 0, void 0, void 0, function* () {
5298
- const globalService = getGlobalService();
5299
- if (!globalService || !globalService.getSnapshot().context) {
5300
- return;
5301
- }
5302
- const { modelName } = event;
5303
- const nameOfService = `${modelName}Service`;
5304
- const service = globalService.getSnapshot().context[nameOfService];
5305
- yield writeAppState(`snapshot__${modelName}`, JSON.stringify(service.getPersistedSnapshot()));
5306
- });
5307
-
5308
- const setupServiceHandlers = () => {
5309
- eventEmitter.addListener('service.save', saveServiceHandler);
5474
+ const getAreItemEventHandlersReady = () => {
5475
+ return areReady;
5310
5476
  };
5311
5477
 
5312
- const client = {
5313
- init: ({ config, addresses }) => {
5314
- const { endpoints, models } = config;
5315
- for (const [key, value] of Object.entries(models)) {
5316
- setModel(key, value);
5317
- }
5318
- setupFsListeners();
5319
- setupAllItemsEventHandlers();
5320
- setupServicesEventHandlers();
5321
- setupServiceHandlers();
5322
- if (areFsListenersReady()) {
5323
- eventEmitter.emit('fs.init');
5324
- }
5325
- if (!areFsListenersReady()) {
5326
- console.error('fs listeners not ready during init');
5327
- }
5328
- globalService.send({ type: 'init', endpoints, models, addresses });
5329
- import('./seed.schema.config-OyHsE0Zl.js').then(({ models }) => {
5330
- for (const [key, value] of Object.entries(models)) {
5331
- setModel(key, value);
5478
+ const waitForEvent = (_a) => __awaiter(void 0, [_a], void 0, function* ({ req, res }) {
5479
+ const eventId = generateId();
5480
+ return new Promise((resolve) => {
5481
+ const internalHandler = (event) => {
5482
+ if (!event) {
5483
+ return;
5484
+ }
5485
+ const { eventId: _eventId } = event;
5486
+ if (_eventId && _eventId === eventId) {
5487
+ eventEmitter.removeListener(res.eventLabel, internalHandler);
5488
+ resolve(event);
5332
5489
  }
5333
- });
5334
- },
5335
- subscribe: (callback) => {
5336
- callback({
5337
- type: '@xstate.snapshot',
5338
- actorRef: globalService,
5339
- snapshot: globalService.getSnapshot(),
5340
- });
5341
- eventEmitter.addListener('globalService', callback);
5342
- return {
5343
- unsubscribe: () => {
5344
- eventEmitter.removeListener('globalService', callback);
5345
- },
5346
- };
5347
- },
5348
- on: (outerEvent, callback) => {
5349
- eventEmitter.addListener(outerEvent, callback);
5350
- return {
5351
- unsubscribe: () => {
5352
- eventEmitter.removeListener(outerEvent, callback);
5353
- },
5354
5490
  };
5355
- },
5356
- getSeedClass: () => __awaiter(void 0, void 0, void 0, function* () {
5357
- return new Promise((resolve) => {
5358
- const subscription = globalService.subscribe((snapshot) => {
5359
- if (snapshot.status === 'done') {
5360
- resolve(snapshot.output);
5361
- }
5362
- });
5363
- globalService.send({ type: 'getSeed' });
5364
- subscription.unsubscribe();
5365
- });
5366
- }),
5367
- getModel: (modelName) => {
5368
- return getModel(modelName);
5369
- },
5370
- getModels: () => {
5371
- return getModels();
5372
- },
5373
- getModelNames: () => {
5374
- return getModelNames();
5375
- },
5376
- };
5491
+ eventEmitter.addListener(res.eventLabel, internalHandler);
5492
+ eventEmitter.emit(req.eventLabel, Object.assign(Object.assign({}, req.data), { eventId }));
5493
+ });
5494
+ });
5377
5495
 
5378
- const preparePublishRequestData = fromCallback(({ sendBack, input: { context } }) => {
5379
- const { localId } = context;
5380
- const _preparePublishRequestData = () => __awaiter(void 0, void 0, void 0, function* () {
5381
- const item = yield Item.find({ seedLocalId: localId });
5382
- if (!item) {
5496
+ const hydrateExistingItem = fromCallback(({ sendBack, input: { event, context } }) => {
5497
+ const { existingItem } = event;
5498
+ const { seedUid, seedLocalId, ModelClass } = context;
5499
+ if (!ModelClass) {
5500
+ throw new Error('ModelClass not found');
5501
+ }
5502
+ const modelName = ModelClass.originalConstructor.name;
5503
+ const _checkForItemOnAllItemsService = () => __awaiter(void 0, void 0, void 0, function* () {
5504
+ if (!existingItem.seedLocalId && !existingItem.seedUid) {
5505
+ console.warn('[singleItemActors] [hydrateExistingItem] No seedLocalId or seedUid found on existingItem');
5383
5506
  return false;
5384
5507
  }
5385
- const appDb = getAppDb();
5386
- const modelsRows = yield appDb
5387
- .select({
5388
- modelName: models.name,
5389
- schemaUid: modelUids.uid,
5390
- })
5391
- .from(models)
5392
- .leftJoin(modelUids, eq(modelUids.modelId, models.id))
5393
- .where(eq(models.name, 'Version'));
5394
- if (!modelsRows || modelsRows.length === 0) {
5395
- sendBack({ type: 'preparePublishRequestDataError' });
5508
+ if (!seedUid && !seedLocalId) {
5396
5509
  return false;
5397
5510
  }
5398
- const versionSchemaUid = modelsRows[0].schemaUid;
5399
- yield item.getEditedProperties();
5400
- yield getModelSchemas();
5401
- // const dataEncoder = new SchemaEncoder(modelProperty.schemaDefinition,)
5402
- // const encodedData = dataEncoder.encodeData(data,)
5403
- //
5404
- // itemData.listOfAttestations.push({
5405
- // schema : modelProperty.schemaUid,
5406
- // data : [
5407
- // {
5408
- // ...defaultAttestationData,
5409
- // data : encodedData,
5410
- // },
5411
- // ],
5412
- // },)
5413
- const publishRequestData = {
5414
- seedIsRevocable: false,
5415
- seedSchemaUid: item.schemaUid,
5416
- seedUid: item.seedUid,
5417
- versionSchemaUid,
5418
- versionUid: item.latestVersionUid,
5419
- listOfAttestations: [],
5420
- };
5421
- sendBack(Object.assign({ type: 'updateContext' }, publishRequestData));
5511
+ yield waitForEvent({
5512
+ req: {
5513
+ eventLabel: 'item.request',
5514
+ data: {
5515
+ modelName,
5516
+ seedUid,
5517
+ seedLocalId,
5518
+ source: 'hydrateExistingItem',
5519
+ },
5520
+ },
5521
+ res: {
5522
+ eventLabel: `item.${modelName}.${seedLocalId}.response`,
5523
+ },
5524
+ });
5422
5525
  return true;
5526
+ // return new Promise((resolve) => {
5527
+ // const timeStart = Date.now()
5528
+ //
5529
+ // const interval = setInterval(() => {
5530
+ // const timeElapsed = Date.now() - timeStart
5531
+ // if (timeElapsed > 2000) {
5532
+ // eventEmitter.emit('item.request', {
5533
+ // modelName,
5534
+ // versionUid,
5535
+ // versionLocalId,
5536
+ // source: 'hydrateExistingItem',
5537
+ // })
5538
+ // }
5539
+ // if (timeElapsed > 30000) {
5540
+ // clearInterval(interval)
5541
+ // console.error(
5542
+ // `[singleItemActors] [hydrateExistingItem] ${timeElapsed / 1000}s elapsed for ${modelName} ${versionLocalId}`,
5543
+ // context,
5544
+ // )
5545
+ // eventEmitter.removeListener(
5546
+ // `item.${modelName}.response`,
5547
+ // handleItemRequestResponse,
5548
+ // )
5549
+ // resolve(false)
5550
+ // }
5551
+ // }, 500)
5552
+ // const handleItemRequestResponse = (event) => {
5553
+ // if (
5554
+ // event.item &&
5555
+ // ((event.item.versionLocalId &&
5556
+ // event.item.versionLocalId === versionLocalId) ||
5557
+ // (event.item.versionUid && event.item.versionUid === versionUid))
5558
+ // ) {
5559
+ // clearInterval(interval)
5560
+ // eventEmitter.removeListener(
5561
+ // `item.${modelName}.response`,
5562
+ // handleItemRequestResponse,
5563
+ // )
5564
+ // resolve(true)
5565
+ // }
5566
+ // }
5567
+ //
5568
+ // eventEmitter.addListener(
5569
+ // `item.${modelName}.response`,
5570
+ // handleItemRequestResponse,
5571
+ // )
5572
+ //
5573
+ // eventEmitter.emit('item.request', {
5574
+ // modelName,
5575
+ // versionUid,
5576
+ // versionLocalId,
5577
+ // source: 'hydrateExistingItem',
5578
+ // })
5579
+ // })
5580
+ // if (existingItem.versionLocalId && !existingItem.versionLocalId) {
5581
+ // console.log(
5582
+ // `[singleItemActors] [hydrateExistingItem] versionLocalId: ${existingItem.versionLocalId} versionUid: ${existingItem.versionUid}`,
5583
+ // )
5584
+ //
5585
+ // return true
5586
+ // }
5587
+ //
5588
+ // console.log(
5589
+ // `[singleItemActors] [hydrateExistingItem] versionLocalId: ${existingItem.versionLocalId} versionUid: ${existingItem.versionUid}`,
5590
+ // )
5591
+ // return true
5423
5592
  });
5424
- _preparePublishRequestData().then((success) => {
5425
- if (success) {
5426
- sendBack({ type: 'preparePublishRequestDataSuccess' });
5427
- }
5428
- });
5429
- });
5430
-
5431
- const logger$1 = debug('app:services:publish:actors:upload');
5432
- const upload = fromCallback(({ sendBack, input: { context } }) => {
5433
- const { localId } = context;
5434
- const _upload = () => __awaiter(void 0, void 0, void 0, function* () {
5435
- const item = yield Item.find({ seedLocalId: localId });
5436
- if (!item) {
5437
- logger$1('no item with localId', localId);
5438
- return false;
5439
- }
5440
- const editedProperties = yield item.getEditedProperties();
5441
- for (const propertyData of editedProperties) {
5442
- if (propertyData.refSeedType === 'image') ;
5443
- }
5444
- const uploadItems = [];
5445
- for (const editedPropertyData of editedProperties) {
5446
- const propertyName = editedPropertyData.propertyName;
5447
- const editedProperty = item.properties[propertyName];
5448
- if (!editedProperty || !editedProperty.propertyDef) {
5449
- continue;
5450
- }
5451
- if (editedProperty.propertyDef.refValueType &&
5452
- editedProperty.propertyDef.refValueType === 'ImageSrc') {
5453
- const context = editedProperty.getService().getSnapshot().context;
5454
- const imageSeedId = context.propertyValue;
5455
- getCorrectId(imageSeedId);
5456
- }
5457
- if (editedProperty.propertyDef.storageType === 'ItemStorage' &&
5458
- editedProperty.propertyDef.localStorageDir) ;
5593
+ _checkForItemOnAllItemsService().then((shouldContinue) => {
5594
+ if (!shouldContinue) {
5595
+ sendBack({ type: 'hydrateExistingItemFailure' });
5596
+ return;
5459
5597
  }
5460
- if (uploadItems.length === 0) {
5461
- return true;
5598
+ // for (const [key, value] of Object.entries(existingItem)) {
5599
+ // sendBack({
5600
+ // type: 'updateValue',
5601
+ // propertyName: key,
5602
+ // propertyValue: value,
5603
+ // source: 'db',
5604
+ // })
5605
+ // }
5606
+ sendBack({ type: 'hydrateExistingItemSuccess' });
5607
+ });
5608
+ });
5609
+
5610
+ const hydrateNewItem = fromCallback(({ sendBack, input: { context } }) => {
5611
+ const { seedUid, versionUid, modelName } = context;
5612
+ let newSeedLocalId;
5613
+ const _hydrateNewItem = () => __awaiter(void 0, void 0, void 0, function* () {
5614
+ if (!modelName) {
5615
+ throw new Error('modelName is required');
5462
5616
  }
5463
- // const turbo = TurboFactory.unauthenticated()
5464
- // turbo.uploadSignedDataItem()
5465
- //
5466
- // const { id, owner, dataCaches, fastFinalityIndexes } = await turbo.uploadFile(() => {
5467
- // fileStreamFactory => () => fs.createReadStream(filePath),
5468
- // fileSizeFactory => () => fileSize,
5469
- // });
5470
- return false;
5617
+ newSeedLocalId = yield createSeed({
5618
+ type: modelName.toLowerCase(),
5619
+ seedUid: seedUid !== null && seedUid !== void 0 ? seedUid : 'NULL',
5620
+ });
5621
+ yield createVersion({
5622
+ seedLocalId: newSeedLocalId,
5623
+ seedType: modelName.toLowerCase(),
5624
+ uid: versionUid !== null && versionUid !== void 0 ? versionUid : 'NULL',
5625
+ });
5471
5626
  });
5472
- _upload().then((isValid) => {
5473
- if (isValid) {
5474
- sendBack({ type: 'uploadSuccess' });
5627
+ _hydrateNewItem().then(() => {
5628
+ sendBack({ type: 'hydrateNewItemSuccess' });
5629
+ });
5630
+ });
5631
+
5632
+ const fetchDataFromEas = fromCallback(({ sendBack, input: { context } }) => {
5633
+ const { ModelClass, modelTableName, versionUid } = context;
5634
+ const propertiesMetadata = new Map();
5635
+ // EAS is the final source of truth, so we need to see if our Item is
5636
+ // already represented there. Then we need to intelligently sync/merge
5637
+ // with whatever new data has been created on the device before the sync.
5638
+ for (const [propertyName, propertyMetadata] of Object.entries(ModelClass.schema)) {
5639
+ if (propertyMetadata) {
5640
+ propertiesMetadata.set(propertyName, propertyMetadata);
5475
5641
  }
5642
+ }
5643
+ sendBack({ type: 'updatePropertiesMetadata', propertiesMetadata });
5644
+ if (!versionUid) {
5645
+ // In this case this is a local only item, so we don't need to fetch anything
5646
+ return;
5647
+ }
5648
+ const _fetchDataFromEas = () => __awaiter(void 0, void 0, void 0, function* () {
5649
+ // Fetch Properties by versionUid
5650
+ const { itemProperties } = yield queryClient.fetchQuery({
5651
+ queryKey: ['getProperties', versionUid],
5652
+ queryFn: () => __awaiter(void 0, void 0, void 0, function* () {
5653
+ return easClient.request(GET_PROPERTIES, {
5654
+ where: {
5655
+ refUID: {
5656
+ in: [versionUid],
5657
+ },
5658
+ decodedDataJson: {
5659
+ not: {
5660
+ // The first of many filters to keep bad data out
5661
+ contains: '"value":"0x0000000000000000000000000000000000000000000000000000000000000020"',
5662
+ },
5663
+ },
5664
+ },
5665
+ });
5666
+ }),
5667
+ });
5668
+ // Filter properties by schemaId
5669
+ const selectedPropertiesMap = {};
5670
+ itemProperties.forEach((property) => {
5671
+ const existingProperties = selectedPropertiesMap[property.schemaId] || [];
5672
+ existingProperties.push(property);
5673
+ selectedPropertiesMap[property.schemaId] = existingProperties;
5674
+ });
5675
+ // For each schemaId, sort property Attestations by timeCreated DESC
5676
+ Object.keys(selectedPropertiesMap).forEach((schemaId) => {
5677
+ const sorted = selectedPropertiesMap[schemaId].sort((a, b) => {
5678
+ return a.timeCreated - b.timeCreated;
5679
+ });
5680
+ selectedPropertiesMap[schemaId] = sorted;
5681
+ });
5682
+ Object.keys(selectedPropertiesMap).forEach((schemaId) => {
5683
+ // TODO: Finish this logic
5684
+ // console.log('[singleItemActors] [fetchDataFromEas] schemaId', schemaId)
5685
+ // sendBack({ type: 'addPropertyAttestation', schemaId })
5686
+ });
5687
+ // Attach processed properties to the itemService/itemMachine context
5688
+ sendBack({
5689
+ type: 'updatedPropertiesBySchemaUid',
5690
+ propertiesBySchemaUid: selectedPropertiesMap,
5691
+ });
5692
+ });
5693
+ _fetchDataFromEas().then(() => {
5694
+ sendBack({ type: 'fetchDataFromEasSuccess' });
5476
5695
  });
5477
5696
  });
5478
5697
 
5479
- const { VALIDATING_ITEM_DATA, CREATING_PUBLISH_ATTEMPT, PREPARING_PUBLISH_REQUEST_DATA, UPLOADING, PUBLISHING, IDLE, } = PublishMachineStates;
5480
- const publishMachine = setup({
5698
+ const itemMachineSingle = setup({
5481
5699
  types: {
5482
5700
  context: {},
5483
5701
  input: {},
5484
5702
  },
5485
5703
  actors: {
5486
- validateItemData,
5487
- createPublishAttempt,
5488
- upload,
5489
- preparePublishRequestData,
5704
+ waitForDb,
5705
+ initialize: initialize$2,
5706
+ hydrateExistingItem,
5707
+ hydrateNewItem,
5708
+ fetchDataFromEas,
5490
5709
  },
5491
5710
  }).createMachine({
5492
- id: 'publish',
5493
- initial: VALIDATING_ITEM_DATA,
5711
+ id: MachineIds.ITEM,
5712
+ initial: 'waitingForDb',
5494
5713
  context: ({ input }) => input,
5495
5714
  on: {
5496
- updateContext: updateMachineContext,
5497
- },
5498
- states: {
5499
- [VALIDATING_ITEM_DATA]: {
5500
- on: {
5501
- validateItemDataSuccess: [CREATING_PUBLISH_ATTEMPT],
5502
- },
5503
- invoke: {
5504
- src: 'validateItemData',
5505
- input: ({ context }) => ({ context }),
5506
- },
5715
+ updatedPropertiesBySchemaUid: {
5716
+ actions: assign({
5717
+ propertiesBySchemaUid: ({ event }) => event.propertiesBySchemaUid,
5718
+ }),
5507
5719
  },
5508
- [CREATING_PUBLISH_ATTEMPT]: {
5509
- on: {
5510
- createPublishAttemptSuccess: [UPLOADING],
5511
- },
5512
- invoke: {
5513
- src: 'createPublishAttempt',
5514
- input: ({ context }) => ({ context }),
5515
- },
5720
+ updatePropertiesMetadata: {
5721
+ actions: assign({
5722
+ propertiesMetadata: ({ event }) => event.propertiesMetadata,
5723
+ }),
5516
5724
  },
5517
- [UPLOADING]: {
5518
- on: {
5519
- uploadingSuccess: [PREPARING_PUBLISH_REQUEST_DATA],
5520
- },
5521
- invoke: {
5522
- src: 'upload',
5523
- input: ({ context }) => ({ context }),
5524
- },
5725
+ updateProperties: {
5726
+ actions: assign({
5727
+ propertiesUpdatedAt: Date.now(),
5728
+ }),
5525
5729
  },
5526
- [PREPARING_PUBLISH_REQUEST_DATA]: {
5527
- on: {
5528
- preparePublishRequestDataSuccess: [UPLOADING],
5529
- },
5530
- invoke: {
5531
- src: 'preparePublishRequestData',
5532
- input: ({ context }) => ({ context }),
5533
- },
5730
+ updateValue: {
5731
+ actions: assign(({ event, context }) => {
5732
+ let { propertyInstances } = context;
5733
+ if (!propertyInstances) {
5734
+ propertyInstances = new Map();
5735
+ }
5736
+ const { propertyName, propertyValue } = event;
5737
+ if (!propertyInstances.has(propertyName)) {
5738
+ return {
5739
+ [propertyName]: propertyValue,
5740
+ };
5741
+ }
5742
+ const propertyInstance = propertyInstances.get(propertyName);
5743
+ propertyInstance.value = propertyValue;
5744
+ propertyInstances.set(propertyName, propertyInstance);
5745
+ // TODO: use immer here
5746
+ return {
5747
+ propertyInstances,
5748
+ };
5749
+ }),
5534
5750
  },
5535
- [PUBLISHING]: {},
5536
- [IDLE]: {},
5537
- },
5538
- });
5539
-
5540
- const { UNINITIALIZED, INITIALIZING, INITIALIZED, PUBLISHING_ITEM, ADDING_MODELS_TO_DB, } = GlobalState;
5541
- createBrowserInspector({
5542
- autoStart: false,
5543
- });
5544
- const globalMachine = setup({
5545
- types: {
5546
- context: {},
5547
- input: {},
5548
- },
5549
- actors: {
5550
- initialize: initialize$1,
5551
- addModelsToDb,
5552
- getSchemaForModel,
5751
+ addPropertyInstance: {
5752
+ actions: assign(({ context, event }) => {
5753
+ const propertyInstances = context.propertyInstances || new Map();
5754
+ propertyInstances.set(event.propertyName, event.propertyInstance);
5755
+ return {
5756
+ propertyInstances,
5757
+ };
5758
+ }),
5759
+ },
5760
+ // addPropertyAttestation: {
5761
+ // actions: assign(({ context, event }) => {
5762
+ // console.log('[singleItemMachine] [addPropertyAttestation] event', event)
5763
+ // const propertyInstances =
5764
+ // context.propertyInstances || new Map<string, typeof ItemProperty>()
5765
+ // propertyInstances.set(event.propertyName, event.propertyInstances)
5766
+ // return {
5767
+ // propertyInstances,
5768
+ // }
5769
+ // }),
5770
+ // },
5553
5771
  },
5554
- }).createMachine({
5555
- id: MachineIds.GLOBAL,
5556
- initial: UNINITIALIZED,
5557
- context: ({ input }) => input,
5558
5772
  states: {
5559
- [UNINITIALIZED]: {
5773
+ idle: {},
5774
+ waitingForDb: {
5560
5775
  on: {
5561
- init: {
5562
- target: INITIALIZING,
5563
- guard: ({ context }) => {
5564
- return typeof window !== 'undefined';
5565
- },
5566
- actions: [
5567
- assign({
5568
- isInitialized: false,
5569
- addedModelRecordsToDb: false,
5570
- models: ({ event }) => event.models,
5571
- endpoints: ({ event }) => event.endpoints,
5572
- internalService: ({ spawn, context }) => {
5573
- return spawn(internalMachine, {
5574
- systemId: MachineIds.INTERNAL,
5575
- input: {
5576
- endpoints: context.endpoints,
5577
- },
5578
- });
5579
- },
5580
- }),
5581
- ],
5582
- },
5776
+ waitForDbSuccess: 'initializing',
5583
5777
  },
5584
- meta: {
5585
- displayText: 'Booting up',
5586
- percentComplete: 5,
5778
+ invoke: {
5779
+ src: 'waitForDb',
5587
5780
  },
5588
- tags: ['loading'],
5589
5781
  },
5590
- [INITIALIZING]: {
5782
+ initializing: {
5591
5783
  on: {
5592
- [GLOBAL_INITIALIZING_SEND_CONFIG]: {
5784
+ hasExistingItem: {
5785
+ target: 'idle',
5593
5786
  actions: assign({
5594
- endpoints: ({ event }) => event.endpoints,
5595
- environment: ({ event }) => event.environment,
5596
- addresses: ({ event }) => event.addresses,
5597
- isInitialized: true,
5787
+ modelTableName: ({ event }) => event.modelTableName,
5788
+ modelNamePlural: ({ event }) => event.modelNamePlural,
5789
+ modelName: ({ event }) => event.modelName,
5790
+ existingItem: ({ event }) => event.existingItem,
5598
5791
  }),
5599
5792
  },
5600
- [GLOBAL_INITIALIZING_INTERNAL_SERVICE_READY]: ADDING_MODELS_TO_DB,
5601
- [GLOBAL_INITIALIZING_CREATE_ALL_ITEMS_SERVICES]: {
5602
- actions: [
5603
- assign(({ event, spawn }) => {
5604
- const allItemsServices = {};
5605
- for (const [modelName, ModelClass] of Object.entries(event.create)) {
5606
- const service = spawn(itemMachineAll, {
5607
- systemId: modelName,
5608
- input: {
5609
- modelName,
5610
- ModelClass,
5611
- modelSchema: ModelClass.schema,
5612
- items: [],
5613
- },
5614
- });
5615
- allItemsServices[`${modelName}Service`] = service;
5616
- }
5617
- for (const [modelName, snapshot] of Object.entries(event.restore)) {
5618
- const service = createActor(itemMachineAll, {
5619
- snapshot,
5620
- });
5621
- service.start();
5622
- allItemsServices[`${modelName}Service`] = service;
5623
- }
5624
- return allItemsServices;
5625
- }),
5626
- raise({ type: 'allItemsServicesCreated' }),
5627
- ],
5793
+ isNewItem: {
5794
+ target: 'idle',
5795
+ actions: assign({
5796
+ modelTableName: ({ event }) => event.modelTableName,
5797
+ modelNamePlural: ({ event }) => event.modelNamePlural,
5798
+ modelName: ({ event }) => event.modelName,
5799
+ }),
5628
5800
  },
5629
5801
  },
5630
5802
  invoke: {
5631
5803
  src: 'initialize',
5804
+ input: ({ context, event }) => ({ context, event }),
5805
+ },
5806
+ },
5807
+ hydratingExistingItem: {
5808
+ on: {
5809
+ hydrateExistingItemSuccess: 'idle',
5810
+ hydrateExistingItemFailure: 'destroying',
5811
+ },
5812
+ invoke: {
5813
+ src: 'hydrateExistingItem',
5632
5814
  input: ({ event, context }) => ({ event, context }),
5633
- meta: {
5634
- displayText: 'Initializing Seed SDK',
5635
- percentComplete: 10,
5636
- },
5637
- tags: ['loading'],
5638
5815
  },
5639
5816
  },
5640
- [ADDING_MODELS_TO_DB]: {
5817
+ hydratingNewItem: {
5641
5818
  on: {
5642
- [GLOBAL_ADDING_MODELS_TO_DB_SUCCESS]: {
5643
- target: INITIALIZED,
5644
- actions: assign({
5645
- addedModelRecordsToDb: true,
5646
- }),
5647
- },
5819
+ hydrateNewItemSuccess: 'idle',
5648
5820
  },
5649
5821
  invoke: {
5650
- src: 'addModelsToDb',
5822
+ src: 'hydrateNewItem',
5651
5823
  input: ({ context }) => ({ context }),
5652
- meta: {
5653
- displayText: 'Adding models to database',
5654
- },
5655
- tags: ['loading'],
5656
5824
  },
5657
5825
  },
5658
- [INITIALIZED]: {
5659
- type: 'parallel',
5826
+ fetchingRemoteData: {
5660
5827
  on: {
5661
- publishItemRequest: `.${PUBLISHING_ITEM}`,
5662
- },
5663
- meta: {
5664
- displayText: 'Global service ready',
5665
- percentComplete: 40,
5828
+ fetchRemoteDataSuccess: 'idle',
5666
5829
  },
5667
- tags: ['loading'],
5668
- states: {
5669
- [PUBLISHING_ITEM]: {
5670
- entry: [
5671
- assign({
5672
- publishItemService: ({ spawn, event }) => spawn(publishMachine, {
5673
- id: 'publishService',
5674
- input: {
5675
- modelName: event.modelName,
5676
- localId: event.seedLocalId,
5677
- },
5678
- }),
5679
- }),
5680
- ],
5681
- meta: {
5682
- displayText: 'Publishing item',
5683
- },
5684
- tags: ['publishing'],
5685
- },
5830
+ invoke: {
5831
+ src: 'fetchRemoteData',
5832
+ input: ({ context }) => ({ context }),
5686
5833
  },
5687
5834
  },
5835
+ // fetchingDataFromEas: {
5836
+ // on: {
5837
+ // fetchDataFromEasSuccess: 'savingDataToDb',
5838
+ // },
5839
+ // invoke: {
5840
+ // src: 'fetchDataFromEas',
5841
+ // input: ({ context }) => ({ context }),
5842
+ // },
5843
+ // },
5844
+ // savingDataToDb: {
5845
+ // on: {
5846
+ // saveDataToDbSuccess: 'idle',
5847
+ // },
5848
+ // invoke: {
5849
+ // src: 'saveDataToDb',
5850
+ // input: ({ context }) => ({ context }),
5851
+ // },
5852
+ // },
5853
+ destroying: {
5854
+ type: 'final',
5855
+ },
5688
5856
  },
5689
- // on: {
5690
- // '*': {
5691
- // actions: emit(({ event }) => {
5692
- // return event
5693
- // }),
5694
- // },
5695
- // },
5696
- });
5697
- const globalService = createActor(globalMachine, {
5698
- input: {},
5699
- // inspect,
5700
- inspect: (inspEvent) => {
5701
- eventEmitter.emit('inspect.globalService', inspEvent);
5702
- // console.log('[sdk] [service/index] inspEvent', inspEvent)
5703
- // eventEmitter.emit('globalService', inspEvent)
5704
- // let eventType: string = inspEvent.type
5705
- // if (inspEvent.event && inspEvent.event.type) {
5706
- // eventType = inspEvent.event.type
5707
- // }
5708
- //
5709
- // if (typeof eventType === 'object') {
5710
- // eventType = JSON.stringify(eventType)
5711
- // }
5712
- //
5713
- // let srcId = inspEvent.actorRef.id
5714
- //
5715
- // if (!srcId.includes('seedSdk')) {
5716
- // srcId = inspEvent.actorRef.logic.config.id
5717
- // }
5718
- //
5719
- // if (inspEvent.type === '@xstate.snapshot') {
5720
- // if (
5721
- // inspEvent.event.type === CHILD_SNAPSHOT &&
5722
- // inspEvent.snapshot &&
5723
- // inspEvent.snapshot.machine.id === MachineIds.GLOBAL
5724
- // ) {
5725
- // return
5726
- // }
5727
- // if (inspEvent.snapshot && inspEvent.snapshot.value) {
5728
- // if (typeof window !== 'undefined') {
5729
- // eventEmitter.emit('globalService', {
5730
- // type: eventType,
5731
- // src: srcId,
5732
- // snapshot: inspEvent.snapshot,
5733
- // })
5734
- // }
5735
- // }
5736
- // } else {
5737
- // if (typeof window !== 'undefined') {
5738
- // let snapshot
5739
- //
5740
- // try {
5741
- // snapshot = inspEvent.actorRef.getSnapshot()
5742
- // } catch (e) {
5743
- // // This fails if the actor hasn't initialized yet, but that's OK I think
5744
- // // console.log('[sdk] [service/index] ERROR', e)
5745
- // }
5746
- //
5747
- // eventEmitter.emit('globalService', {
5748
- // type: eventType,
5749
- // src: srcId,
5750
- // snapshot,
5751
- // })
5752
- // }
5753
- // }
5754
- },
5755
- });
5756
- globalService.start();
5757
- const getGlobalService = () => globalService;
5758
-
5759
- const publishItemRequestHandler = (_a) => __awaiter(void 0, [_a], void 0, function* ({ modelName, seedLocalId, }) {
5760
- const globalService = getGlobalService();
5761
- globalService.subscribe((snapshot) => {
5762
- if (!snapshot ||
5763
- !snapshot.context ||
5764
- !snapshot.context.publishItemService) {
5765
- return;
5766
- }
5767
- });
5768
- globalService.send({
5769
- type: 'publishItemRequest',
5770
- modelName,
5771
- seedLocalId,
5772
- });
5773
5857
  });
5774
5858
 
5775
- let areReady = false;
5776
- const setupAllItemsEventHandlers = () => {
5777
- // eventEmitter.addListener('item.request', itemRequestHandler)
5778
- // eventEmitter.addListener('item.requestAll', itemRequestAllHandler)
5779
- // eventEmitter.addListener(
5780
- // 'item.propertyValuesForSeedUid.request',
5781
- // propertyValuesForSeedUid,
5782
- // )
5783
- // eventEmitter.addListener('item.create.request', createItemRequestHandler)
5784
- // eventEmitter.addListener('item.delete.request', itemDeleteRequestHandler)
5785
- // eventEmitter.addListener('item.update', itemUpdateHandler)
5786
- eventEmitter.addListener('syncDbWithEas', syncDbWithEasHandler);
5787
- eventEmitter.addListener('item.publish.request', publishItemRequestHandler);
5788
- //
5789
- // eventEmitter.emit('item.events.setupAllItemsEventHandlers')
5790
- areReady = true;
5791
- };
5792
- const getAreItemEventHandlersReady = () => {
5793
- return areReady;
5794
- };
5795
-
5796
- const waitForEvent = (_a) => __awaiter(void 0, [_a], void 0, function* ({ req, res }) {
5797
- const eventId = generateId();
5798
- return new Promise((resolve) => {
5799
- const internalHandler = (event) => {
5800
- if (!event) {
5801
- return;
5802
- }
5803
- const { eventId: _eventId } = event;
5804
- if (_eventId && _eventId === eventId) {
5805
- eventEmitter.removeListener(res.eventLabel, internalHandler);
5806
- resolve(event);
5807
- }
5808
- };
5809
- eventEmitter.addListener(res.eventLabel, internalHandler);
5810
- eventEmitter.emit(req.eventLabel, Object.assign(Object.assign({}, req.data), { eventId }));
5811
- });
5859
+ const getItemProperties = (_a) => __awaiter(void 0, [_a], void 0, function* ({ seedLocalId, seedUid, edited, }) {
5860
+ const appDb = getAppDb();
5861
+ const whereClauses = [isNotNull(metadata.propertyName)];
5862
+ const uidWhereClause = seedUid
5863
+ ? eq(seeds.uid, seedUid)
5864
+ : isNull(seeds.uid);
5865
+ const localWhereClause = seedLocalId
5866
+ ? eq(seeds.localId, seedLocalId)
5867
+ : isNull(seeds.localId);
5868
+ whereClauses.push(or(localWhereClause, uidWhereClause));
5869
+ whereClauses.push(isNotNull(metadata.propertyName));
5870
+ whereClauses.push(isNotNull(metadata.easDataType));
5871
+ if (typeof edited !== 'undefined') {
5872
+ if (edited) {
5873
+ whereClauses.push(isNull(metadata.uid));
5874
+ }
5875
+ if (!edited) {
5876
+ whereClauses.push(isNotNull(metadata.uid));
5877
+ }
5878
+ }
5879
+ // if (!seedLocalId || !seedUid) {
5880
+ // const seedRows = await appDb
5881
+ // .select({
5882
+ // localId: seeds.localId,
5883
+ // uid: seeds.uid,
5884
+ // })
5885
+ // .from(seeds)
5886
+ // .where(or(localWhereClause, uidWhereClause))
5887
+ //
5888
+ // if (seedRows && seedRows.length > 0) {
5889
+ // seedUid = seedRows[0].uid as string
5890
+ // seedLocalId = seedRows[0].localId as string
5891
+ // }
5892
+ // }
5893
+ const metadataColumns = getTableColumns(metadata);
5894
+ const propertiesData = yield appDb
5895
+ .select(Object.assign({}, metadataColumns))
5896
+ .from(seeds)
5897
+ .leftJoin(metadata, eq(metadata.seedLocalId, seeds.localId))
5898
+ .leftJoin(versions, eq(versions.localId, seeds.localId))
5899
+ .where(and(...whereClauses))
5900
+ .groupBy(metadata.propertyName);
5901
+ return propertiesData;
5812
5902
  });
5903
+ // const localIdWhere = seedLocalId
5904
+ // ? `s.local_id = '${seedLocalId}'`
5905
+ // : 's.local_id IS NULL'
5906
+ // const uidWhere = seedUid ? `s.uid = '${seedUid}'` : 's.uid IS NULL'
5907
+ //
5908
+ // const queryStatement = `WITH LatestMetadata as (SELECT m.property_name,
5909
+ // m.property_value,
5910
+ // m.version_local_id,
5911
+ // MAX(m.attestation_created_at),
5912
+ // m.uid,
5913
+ // m.seed_local_id,
5914
+ // seed_uid
5915
+ // FROM metadata m
5916
+ // JOIN seeds s ON s.local_id = m.seed_local_id
5917
+ // GROUP BY m.property_name),
5918
+ //
5919
+ // LatestVersion as (SELECT v.local_id,
5920
+ // MAX(v.attestation_created_at) as attestation_created_at,
5921
+ // v.uid,
5922
+ // v.seed_local_id,
5923
+ // v.seed_uid
5924
+ // FROM versions v
5925
+ // JOIN seeds s ON s.local_id = v.seed_local_id
5926
+ // GROUP BY s.local_id)
5927
+ //
5928
+ //
5929
+ // SELECT s.local_id,
5930
+ // s.uid,
5931
+ // s.schema_uid,
5932
+ // m.property_name,
5933
+ // m.property_value,
5934
+ // COUNT(v.local_id) as versions_count,
5935
+ // m.model_type,
5936
+ // lv.attestation_created_at,
5937
+ // m.local_id,
5938
+ // m.uid,
5939
+ // MAX(m.attestation_created_at),
5940
+ // m.ref_seed_type,
5941
+ // m.ref_value_type,
5942
+ // m.seed_local_id,
5943
+ // m.seed_uid,
5944
+ // m.created_at,
5945
+ // m.updated_at,
5946
+ // m.version_uid
5947
+ // FROM seeds s
5948
+ // JOIN LatestMetadata lm ON s.local_id = m.seed_local_id
5949
+ // JOIN LatestVersion lv ON lv.seed_local_id = m.seed_local_id
5950
+ // JOIN metadata m ON m.property_name = lm.property_name OR lm.property_value = s.uid
5951
+ // JOIN versions v ON s.local_id = v.seed_local_id
5952
+ // WHERE ${localIdWhere}
5953
+ // OR ${uidWhere}
5954
+ // GROUP BY m.property_name;
5955
+ // `
5956
+ //
5957
+ // const { rows } = await runQueryForStatement(queryStatement)
5958
+ //
5959
+ // const propertiesDataOld: PropertyData[] = []
5960
+ //
5961
+ // for (const row of rows) {
5962
+ // propertiesDataOld.push({
5963
+ // localId: row[0],
5964
+ // uid: row[1],
5965
+ // schemaUid: row[2],
5966
+ // propertyName: row[3],
5967
+ // propertyValue: row[4],
5968
+ // versionsCount: row[5],
5969
+ // itemModelName: row[6],
5970
+ // attestationCreatedAt: row[7],
5971
+ // metadataLocalId: row[8],
5972
+ // metadataUid: row[9],
5973
+ // metadataAttestationCreatedAt: row[10],
5974
+ // refSeedType: row[11],
5975
+ // refValueType: row[12],
5976
+ // seedLocalId: row[13],
5977
+ // seedUid: row[14],
5978
+ // createdAt: row[15],
5979
+ // updatedAt: row[16],
5980
+ // versionUid: row[17],
5981
+ // })
5982
+ // }
5813
5983
 
5814
- const hydrateExistingItem = fromCallback(({ sendBack, input: { event, context } }) => {
5815
- const { existingItem } = event;
5816
- const { seedUid, seedLocalId, ModelClass } = context;
5817
- if (!ModelClass) {
5818
- throw new Error('ModelClass not found');
5984
+ const logger$4 = debug('app:db:queries:getItem');
5985
+ const getItemDataFromDb = (_a) => __awaiter(void 0, [_a], void 0, function* ({ modelName, seedLocalId, seedUid, }) {
5986
+ if (!seedLocalId && !seedUid) {
5987
+ throw new Error('[db/queries] [getItem] no seedLocalId or seedUid');
5819
5988
  }
5820
- const modelName = ModelClass.originalConstructor.name;
5821
- const _checkForItemOnAllItemsService = () => __awaiter(void 0, void 0, void 0, function* () {
5822
- if (!existingItem.seedLocalId && !existingItem.seedUid) {
5823
- console.warn('[singleItemActors] [hydrateExistingItem] No seedLocalId or seedUid found on existingItem');
5824
- return false;
5825
- }
5826
- if (!seedUid && !seedLocalId) {
5827
- return false;
5989
+ if (seedUid && !seedLocalId) {
5990
+ const seedData = yield getSeedData({ seedUid });
5991
+ if (!seedData) {
5992
+ logger$4('[db/queries] [getItem] no seedData seedUid', seedUid);
5993
+ return;
5828
5994
  }
5829
- yield waitForEvent({
5830
- req: {
5831
- eventLabel: 'item.request',
5832
- data: {
5833
- modelName,
5834
- seedUid,
5835
- seedLocalId,
5836
- source: 'hydrateExistingItem',
5837
- },
5838
- },
5839
- res: {
5840
- eventLabel: `item.${modelName}.${seedLocalId}.response`,
5841
- },
5842
- });
5843
- return true;
5844
- // return new Promise((resolve) => {
5845
- // const timeStart = Date.now()
5846
- //
5847
- // const interval = setInterval(() => {
5848
- // const timeElapsed = Date.now() - timeStart
5849
- // if (timeElapsed > 2000) {
5850
- // eventEmitter.emit('item.request', {
5851
- // modelName,
5852
- // versionUid,
5853
- // versionLocalId,
5854
- // source: 'hydrateExistingItem',
5855
- // })
5856
- // }
5857
- // if (timeElapsed > 30000) {
5858
- // clearInterval(interval)
5859
- // console.error(
5860
- // `[singleItemActors] [hydrateExistingItem] ${timeElapsed / 1000}s elapsed for ${modelName} ${versionLocalId}`,
5861
- // context,
5862
- // )
5863
- // eventEmitter.removeListener(
5864
- // `item.${modelName}.response`,
5865
- // handleItemRequestResponse,
5866
- // )
5867
- // resolve(false)
5868
- // }
5869
- // }, 500)
5870
- // const handleItemRequestResponse = (event) => {
5871
- // if (
5872
- // event.item &&
5873
- // ((event.item.versionLocalId &&
5874
- // event.item.versionLocalId === versionLocalId) ||
5875
- // (event.item.versionUid && event.item.versionUid === versionUid))
5876
- // ) {
5877
- // clearInterval(interval)
5878
- // eventEmitter.removeListener(
5879
- // `item.${modelName}.response`,
5880
- // handleItemRequestResponse,
5881
- // )
5882
- // resolve(true)
5883
- // }
5995
+ seedLocalId = seedData.localId;
5996
+ }
5997
+ const appDb = getAppDb();
5998
+ const _b = getTableColumns(seeds), rest = __rest(_b, ["localId", "uid"]);
5999
+ const whereClauses = [];
6000
+ if (modelName) {
6001
+ whereClauses.push(eq(seeds.type, modelName.toLowerCase()));
6002
+ }
6003
+ if (seedUid) {
6004
+ whereClauses.push(eq(seeds.uid, seedUid));
6005
+ }
6006
+ if (seedLocalId && !seedUid) {
6007
+ whereClauses.push(eq(seeds.localId, seedLocalId));
6008
+ }
6009
+ const versionData = getVersionData();
6010
+ const itemDataRows = yield appDb
6011
+ .with(versionData)
6012
+ .select(Object.assign(Object.assign({}, rest), { seedLocalId: seeds.localId, seedUid: seeds.uid, versionsCount: versionData.versionsCount, lastVersionPublishedAt: versionData.lastVersionPublishedAt, latestVersionUid: versionData.latestVersionUid, latestVersionLocalId: versionData.latestVersionLocalId }))
6013
+ .from(seeds)
6014
+ .leftJoin(versionData, eq(seeds.localId, versionData.seedLocalId))
6015
+ .where(and(...whereClauses, gt(versionData.versionsCount, 0)))
6016
+ .orderBy(sql.raw('COALESCE(attestation_created_at, created_at) DESC'))
6017
+ .groupBy(seeds.localId);
6018
+ if (!itemDataRows || itemDataRows.length === 0) {
6019
+ logger$4('[db/queries] [getItemDataFromDb] no itemDataRows');
6020
+ return;
6021
+ }
6022
+ let itemData = itemDataRows[0];
6023
+ const propertiesData = yield getItemProperties({ seedLocalId, seedUid });
6024
+ // const initObj: ItemData = {
6025
+ // seedLocalId,
6026
+ // seedUid,
6027
+ // modelName,
6028
+ // }
6029
+ if (!propertiesData || propertiesData.length === 0) {
6030
+ return itemData;
6031
+ }
6032
+ propertiesData[0];
6033
+ for (const propertyData of propertiesData) {
6034
+ const propertyName = propertyData.propertyName;
6035
+ const propertyValue = propertyData.propertyValue;
6036
+ // TODO: Find a better place for the property data below
6037
+ // Since initObj is used to initialize an Item, the following values
6038
+ // just overwrite each other for each property since they are Property
6039
+ // specific.
6040
+ // const refSeedType = propertyDbValues[11]
6041
+ // if (refSeedType) {
6042
+ // initObj.refSeedType = refSeedType
5884
6043
  // }
5885
- //
5886
- // eventEmitter.addListener(
5887
- // `item.${modelName}.response`,
5888
- // handleItemRequestResponse,
5889
- // )
5890
- //
5891
- // eventEmitter.emit('item.request', {
5892
- // modelName,
5893
- // versionUid,
5894
- // versionLocalId,
5895
- // source: 'hydrateExistingItem',
5896
- // })
5897
- // })
5898
- // if (existingItem.versionLocalId && !existingItem.versionLocalId) {
5899
- // console.log(
5900
- // `[singleItemActors] [hydrateExistingItem] versionLocalId: ${existingItem.versionLocalId} versionUid: ${existingItem.versionUid}`,
5901
- // )
5902
- //
5903
- // return true
6044
+ // const refValueType = propertyDbValues[12]
6045
+ // if (refValueType) {
6046
+ // initObj.refValueType = refValueType
5904
6047
  // }
5905
6048
  //
5906
- // console.log(
5907
- // `[singleItemActors] [hydrateExistingItem] versionLocalId: ${existingItem.versionLocalId} versionUid: ${existingItem.versionUid}`,
5908
- // )
5909
- // return true
5910
- });
5911
- _checkForItemOnAllItemsService().then((shouldContinue) => {
5912
- if (!shouldContinue) {
5913
- sendBack({ type: 'hydrateExistingItemFailure' });
5914
- return;
5915
- }
5916
- // for (const [key, value] of Object.entries(existingItem)) {
5917
- // sendBack({
5918
- // type: 'updateValue',
5919
- // propertyName: key,
5920
- // propertyValue: value,
5921
- // source: 'db',
5922
- // })
6049
+ // if (
6050
+ // refSeedType &&
6051
+ // refValueType === 'list' &&
6052
+ // propertyName.endsWith('Ids')
6053
+ // ) {
6054
+ // logger('[db/queries] [getItemDataFromDb] propertyName', propertyName)
5923
6055
  // }
5924
- sendBack({ type: 'hydrateExistingItemSuccess' });
5925
- });
6056
+ itemData[propertyName] = propertyValue;
6057
+ }
6058
+ return itemData;
5926
6059
  });
5927
6060
 
5928
- const hydrateNewItem = fromCallback(({ sendBack, input: { context } }) => {
5929
- const { seedUid, versionUid, modelName } = context;
5930
- let newSeedLocalId;
5931
- const _hydrateNewItem = () => __awaiter(void 0, void 0, void 0, function* () {
5932
- if (!modelName) {
5933
- throw new Error('modelName is required');
5934
- }
5935
- newSeedLocalId = yield createSeed({
5936
- type: modelName.toLowerCase(),
5937
- seedUid: seedUid !== null && seedUid !== void 0 ? seedUid : 'NULL',
5938
- });
5939
- yield createVersion({
5940
- seedLocalId: newSeedLocalId,
5941
- seedType: modelName.toLowerCase(),
5942
- uid: versionUid !== null && versionUid !== void 0 ? versionUid : 'NULL',
6061
+ var _a$1;
6062
+ class Item {
6063
+ constructor(initialValues) {
6064
+ this[_a$1] = true;
6065
+ this._propertiesSubject = new BehaviorSubject({});
6066
+ this.subscribe = (callback) => {
6067
+ return this._service.subscribe((snapshot) => {
6068
+ callback(snapshot.context);
6069
+ });
6070
+ };
6071
+ this.getService = () => {
6072
+ return this._service;
6073
+ };
6074
+ this.getEditedProperties = () => __awaiter(this, void 0, void 0, function* () {
6075
+ return yield getItemProperties({
6076
+ seedLocalId: this.seedLocalId,
6077
+ edited: true,
6078
+ });
5943
6079
  });
5944
- });
5945
- _hydrateNewItem().then(() => {
5946
- sendBack({ type: 'hydrateNewItemSuccess' });
5947
- });
5948
- });
5949
-
5950
- const fetchDataFromEas = fromCallback(({ sendBack, input: { context } }) => {
5951
- const { ModelClass, modelTableName, versionUid } = context;
5952
- const propertiesMetadata = new Map();
5953
- // EAS is the final source of truth, so we need to see if our Item is
5954
- // already represented there. Then we need to intelligently sync/merge
5955
- // with whatever new data has been created on the device before the sync.
5956
- for (const [propertyName, propertyMetadata] of Object.entries(ModelClass.schema)) {
5957
- if (propertyMetadata) {
5958
- propertiesMetadata.set(propertyName, propertyMetadata);
5959
- }
5960
- }
5961
- sendBack({ type: 'updatePropertiesMetadata', propertiesMetadata });
5962
- if (!versionUid) {
5963
- // In this case this is a local only item, so we don't need to fetch anything
5964
- return;
5965
- }
5966
- const _fetchDataFromEas = () => __awaiter(void 0, void 0, void 0, function* () {
5967
- // Fetch Properties by versionUid
5968
- const { itemProperties } = yield queryClient.fetchQuery({
5969
- queryKey: ['getProperties', versionUid],
5970
- queryFn: () => __awaiter(void 0, void 0, void 0, function* () {
5971
- return easClient.request(GET_PROPERTIES, {
5972
- where: {
5973
- refUID: {
5974
- in: [versionUid],
5975
- },
5976
- decodedDataJson: {
5977
- not: {
5978
- // The first of many filters to keep bad data out
5979
- contains: '"value":"0x0000000000000000000000000000000000000000000000000000000000000020"',
5980
- },
5981
- },
6080
+ this.publish = () => __awaiter(this, void 0, void 0, function* () {
6081
+ yield waitForEvent({
6082
+ req: {
6083
+ eventLabel: `item.publish.request`,
6084
+ data: {
6085
+ seedLocalId: this.seedLocalId,
5982
6086
  },
5983
- });
5984
- }),
5985
- });
5986
- // Filter properties by schemaId
5987
- const selectedPropertiesMap = {};
5988
- itemProperties.forEach((property) => {
5989
- const existingProperties = selectedPropertiesMap[property.schemaId] || [];
5990
- existingProperties.push(property);
5991
- selectedPropertiesMap[property.schemaId] = existingProperties;
5992
- });
5993
- // For each schemaId, sort property Attestations by timeCreated DESC
5994
- Object.keys(selectedPropertiesMap).forEach((schemaId) => {
5995
- const sorted = selectedPropertiesMap[schemaId].sort((a, b) => {
5996
- return a.timeCreated - b.timeCreated;
6087
+ },
6088
+ res: {
6089
+ eventLabel: `item.${this.seedLocalId}.publish.success`,
6090
+ },
5997
6091
  });
5998
- selectedPropertiesMap[schemaId] = sorted;
5999
6092
  });
6000
- Object.keys(selectedPropertiesMap).forEach((schemaId) => {
6001
- // TODO: Finish this logic
6002
- // console.log('[singleItemActors] [fetchDataFromEas] schemaId', schemaId)
6003
- // sendBack({ type: 'addPropertyAttestation', schemaId })
6093
+ const { modelName, seedUid, schemaUid, seedLocalId, latestVersionLocalId, latestVersionUid, } = initialValues;
6094
+ const ModelClass = getModel(modelName);
6095
+ if (ModelClass &&
6096
+ Object.keys(ModelClass === null || ModelClass === void 0 ? void 0 : ModelClass.schema).includes('storageTransactionId') &&
6097
+ initialValues.storageTransactionId) {
6098
+ this._storageTransactionId = initialValues.storageTransactionId;
6099
+ }
6100
+ this._service = createActor(itemMachineSingle, {
6101
+ input: {
6102
+ seedLocalId,
6103
+ seedUid,
6104
+ schemaUid,
6105
+ ModelClass,
6106
+ latestVersionLocalId,
6107
+ latestVersionUid,
6108
+ storageTransactionId: this._storageTransactionId,
6109
+ },
6004
6110
  });
6005
- // Attach processed properties to the itemService/itemMachine context
6006
- sendBack({
6007
- type: 'updatedPropertiesBySchemaUid',
6008
- propertiesBySchemaUid: selectedPropertiesMap,
6111
+ this._subscription = this._service.subscribe((snapshot) => {
6112
+ const { context } = snapshot;
6113
+ if (!context ||
6114
+ !context.propertyInstances ||
6115
+ context.propertyInstances.size === 0) {
6116
+ return;
6117
+ }
6118
+ const propertiesObj = {};
6119
+ for (const [key, propertyInstance] of context.propertyInstances) {
6120
+ if (typeof key !== 'string' || internalPropertyNames.includes(key)) {
6121
+ propertiesObj[key.toString()] = propertyInstance;
6122
+ continue;
6123
+ }
6124
+ let transformedKey = key;
6125
+ if (propertyInstance.alias) {
6126
+ transformedKey = propertyInstance.alias;
6127
+ }
6128
+ if (!propertyInstance.alias && key.endsWith('Ids')) {
6129
+ transformedKey = key.slice(0, -3); // Remove 'Ids'
6130
+ transformedKey = pluralize(transformedKey);
6131
+ }
6132
+ if (!propertyInstance.alias && key.endsWith('Id')) {
6133
+ transformedKey = key.slice(0, -2); // Remove 'Id'
6134
+ }
6135
+ propertiesObj[transformedKey] = propertyInstance;
6136
+ }
6137
+ this._propertiesSubject.next(propertiesObj);
6138
+ eventEmitter.emit(`item.${modelName}.${seedUid || seedLocalId}.update`);
6009
6139
  });
6010
- });
6011
- _fetchDataFromEas().then(() => {
6012
- sendBack({ type: 'fetchDataFromEasSuccess' });
6013
- });
6014
- });
6015
-
6016
- const itemMachineSingle = setup({
6017
- types: {
6018
- context: {},
6019
- input: {},
6020
- },
6021
- actors: {
6022
- waitForDb,
6023
- initialize: initialize$2,
6024
- hydrateExistingItem,
6025
- hydrateNewItem,
6026
- fetchDataFromEas,
6027
- },
6028
- }).createMachine({
6029
- id: MachineIds.ITEM,
6030
- initial: 'waitingForDb',
6031
- context: ({ input }) => input,
6032
- on: {
6033
- updatedPropertiesBySchemaUid: {
6034
- actions: assign({
6035
- propertiesBySchemaUid: ({ event }) => event.propertiesBySchemaUid,
6036
- }),
6037
- },
6038
- updatePropertiesMetadata: {
6039
- actions: assign({
6040
- propertiesMetadata: ({ event }) => event.propertiesMetadata,
6041
- }),
6042
- },
6043
- updateProperties: {
6044
- actions: assign({
6045
- propertiesUpdatedAt: Date.now(),
6046
- }),
6047
- },
6048
- updateValue: {
6049
- actions: assign(({ event, context }) => {
6050
- let { propertyInstances } = context;
6051
- if (!propertyInstances) {
6052
- propertyInstances = new Map();
6140
+ this._service.start();
6141
+ const definedKeys = ['ModelClass'];
6142
+ const itemPropertyBase = {
6143
+ seedLocalId,
6144
+ seedUid,
6145
+ versionLocalId: latestVersionLocalId,
6146
+ versionUid: latestVersionUid,
6147
+ itemModelName: modelName,
6148
+ schemaUid,
6149
+ };
6150
+ if (ModelClass && ModelClass.schema) {
6151
+ const schema = ModelClass.schema;
6152
+ for (const [propertyName, propertyRecordSchema] of Object.entries(schema)) {
6153
+ if (!propertyRecordSchema) {
6154
+ throw new Error(`Property ${propertyName} has no definition`);
6155
+ }
6156
+ this._createPropertyInstance(Object.assign(Object.assign({}, itemPropertyBase), { propertyName, propertyValue: initialValues[propertyName] }));
6157
+ definedKeys.push(propertyName);
6158
+ }
6159
+ }
6160
+ Object.keys(initialValues).forEach((key) => {
6161
+ // If we already defined it, that means it was in the schema
6162
+ if (definedKeys.includes(key)) {
6163
+ return;
6164
+ }
6165
+ this._createPropertyInstance(Object.assign(Object.assign({}, itemPropertyBase), { propertyName: key, propertyValue: initialValues[key] }));
6166
+ });
6167
+ }
6168
+ static create(props) {
6169
+ return __awaiter(this, void 0, void 0, function* () {
6170
+ if (!props.seedUid) {
6171
+ console.log('Creating new item without seedUid');
6172
+ }
6173
+ if (props.seedUid || props.seedLocalId) {
6174
+ const seedId = (props.seedUid || props.seedLocalId);
6175
+ if (Item.instanceCache.has(seedId)) {
6176
+ const { instance, refCount } = Item.instanceCache.get(seedId);
6177
+ Item.instanceCache.set(seedId, {
6178
+ instance,
6179
+ refCount: refCount + 1,
6180
+ });
6181
+ return instance;
6053
6182
  }
6054
- const { propertyName, propertyValue } = event;
6055
- if (!propertyInstances.has(propertyName)) {
6056
- return {
6057
- [propertyName]: propertyValue,
6058
- };
6183
+ if (!Item.instanceCache.has(seedId)) {
6184
+ const newInstance = new Item(props);
6185
+ Item.instanceCache.set(seedId, {
6186
+ instance: newInstance,
6187
+ refCount: 1,
6188
+ });
6189
+ return newInstance;
6059
6190
  }
6060
- const propertyInstance = propertyInstances.get(propertyName);
6061
- propertyInstance.value = propertyValue;
6062
- propertyInstances.set(propertyName, propertyInstance);
6063
- // TODO: use immer here
6064
- return {
6065
- propertyInstances,
6066
- };
6067
- }),
6068
- },
6069
- addPropertyInstance: {
6070
- actions: assign(({ context, event }) => {
6071
- const propertyInstances = context.propertyInstances || new Map();
6072
- propertyInstances.set(event.propertyName, event.propertyInstance);
6073
- return {
6074
- propertyInstances,
6075
- };
6076
- }),
6077
- },
6078
- // addPropertyAttestation: {
6079
- // actions: assign(({ context, event }) => {
6080
- // console.log('[singleItemMachine] [addPropertyAttestation] event', event)
6081
- // const propertyInstances =
6082
- // context.propertyInstances || new Map<string, typeof ItemProperty>()
6083
- // propertyInstances.set(event.propertyName, event.propertyInstances)
6084
- // return {
6085
- // propertyInstances,
6086
- // }
6087
- // }),
6088
- // },
6089
- },
6090
- states: {
6091
- idle: {},
6092
- waitingForDb: {
6093
- on: {
6094
- waitForDbSuccess: 'initializing',
6095
- },
6096
- invoke: {
6097
- src: 'waitForDb',
6098
- },
6099
- },
6100
- initializing: {
6101
- on: {
6102
- hasExistingItem: {
6103
- target: 'idle',
6104
- actions: assign({
6105
- modelTableName: ({ event }) => event.modelTableName,
6106
- modelNamePlural: ({ event }) => event.modelNamePlural,
6107
- modelName: ({ event }) => event.modelName,
6108
- existingItem: ({ event }) => event.existingItem,
6109
- }),
6191
+ }
6192
+ if (!props.modelName) {
6193
+ throw new Error('Model name is required to create an item');
6194
+ }
6195
+ const { seedLocalId } = yield createNewItem({
6196
+ modelName: props.modelName,
6197
+ });
6198
+ props.seedLocalId = seedLocalId;
6199
+ const newInstance = new Item(props);
6200
+ Item.instanceCache.set(newInstance.seedUid || newInstance.seedLocalId, {
6201
+ instance: newInstance,
6202
+ refCount: 1,
6203
+ });
6204
+ return newInstance;
6205
+ });
6206
+ }
6207
+ static find(_b) {
6208
+ return __awaiter(this, arguments, void 0, function* ({ modelName, seedLocalId, seedUid, }) {
6209
+ if (!seedLocalId && !seedUid) {
6210
+ return;
6211
+ }
6212
+ const itemData = yield getItemDataFromDb({
6213
+ modelName,
6214
+ seedLocalId,
6215
+ seedUid,
6216
+ });
6217
+ if (!itemData) {
6218
+ console.error('No item data found', { modelName, seedLocalId, seedUid });
6219
+ return;
6220
+ }
6221
+ return Item.create(Object.assign(Object.assign({}, itemData), { modelName }));
6222
+ });
6223
+ }
6224
+ static all(modelName, deleted) {
6225
+ return __awaiter(this, void 0, void 0, function* () {
6226
+ const itemsData = yield getItemsData({ modelName, deleted });
6227
+ const itemInstances = [];
6228
+ for (const itemData of itemsData) {
6229
+ itemInstances.push(yield Item.create(Object.assign(Object.assign({}, itemData), { modelName })));
6230
+ }
6231
+ return orderBy(itemInstances, ['createdAt'], ['desc']);
6232
+ });
6233
+ }
6234
+ static publish(item) {
6235
+ return __awaiter(this, void 0, void 0, function* () {
6236
+ yield waitForEvent({
6237
+ req: {
6238
+ eventLabel: `item.${item.seedLocalId}.publish.request`,
6239
+ data: {
6240
+ seedLocalId: item.seedLocalId,
6241
+ },
6110
6242
  },
6111
- isNewItem: {
6112
- target: 'idle',
6113
- actions: assign({
6114
- modelTableName: ({ event }) => event.modelTableName,
6115
- modelNamePlural: ({ event }) => event.modelNamePlural,
6116
- modelName: ({ event }) => event.modelName,
6117
- }),
6243
+ res: {
6244
+ eventLabel: `item.${item.seedLocalId}.publish.success`,
6118
6245
  },
6119
- },
6120
- invoke: {
6121
- src: 'initialize',
6122
- input: ({ context, event }) => ({ context, event }),
6123
- },
6124
- },
6125
- hydratingExistingItem: {
6126
- on: {
6127
- hydrateExistingItemSuccess: 'idle',
6128
- hydrateExistingItemFailure: 'destroying',
6129
- },
6130
- invoke: {
6131
- src: 'hydrateExistingItem',
6132
- input: ({ event, context }) => ({ event, context }),
6133
- },
6134
- },
6135
- hydratingNewItem: {
6136
- on: {
6137
- hydrateNewItemSuccess: 'idle',
6138
- },
6139
- invoke: {
6140
- src: 'hydrateNewItem',
6141
- input: ({ context }) => ({ context }),
6142
- },
6143
- },
6144
- fetchingRemoteData: {
6145
- on: {
6146
- fetchRemoteDataSuccess: 'idle',
6147
- },
6148
- invoke: {
6149
- src: 'fetchRemoteData',
6150
- input: ({ context }) => ({ context }),
6151
- },
6152
- },
6153
- // fetchingDataFromEas: {
6154
- // on: {
6155
- // fetchDataFromEasSuccess: 'savingDataToDb',
6156
- // },
6157
- // invoke: {
6158
- // src: 'fetchDataFromEas',
6159
- // input: ({ context }) => ({ context }),
6160
- // },
6161
- // },
6162
- // savingDataToDb: {
6163
- // on: {
6164
- // saveDataToDbSuccess: 'idle',
6165
- // },
6166
- // invoke: {
6167
- // src: 'saveDataToDb',
6168
- // input: ({ context }) => ({ context }),
6169
- // },
6170
- // },
6171
- destroying: {
6172
- type: 'final',
6173
- },
6174
- },
6175
- });
6246
+ });
6247
+ });
6248
+ }
6249
+ _createPropertyInstance(props) {
6250
+ if (this._storageTransactionId) {
6251
+ props.storageTransactionId = this._storageTransactionId;
6252
+ }
6253
+ const propertyInstance = ItemProperty.create(props);
6254
+ if (!propertyInstance) {
6255
+ return;
6256
+ }
6257
+ if (!propertyInstance.alias) {
6258
+ this._service.send({
6259
+ type: 'addPropertyInstance',
6260
+ propertyName: props.propertyName,
6261
+ propertyInstance,
6262
+ });
6263
+ }
6264
+ Object.defineProperty(this, props.propertyName, {
6265
+ get: () => propertyInstance.value,
6266
+ set: (value) => (propertyInstance.value = value),
6267
+ enumerable: true,
6268
+ });
6269
+ }
6270
+ get seedLocalId() {
6271
+ return this._service.getSnapshot().context.seedLocalId;
6272
+ }
6273
+ get seedUid() {
6274
+ return this._service.getSnapshot().context.seedUid;
6275
+ }
6276
+ get schemaUid() {
6277
+ return this.properties['schemaUid'].value;
6278
+ }
6279
+ get latestVersionUid() {
6280
+ return this.properties['latestVersionUid'].value;
6281
+ }
6282
+ get modelName() {
6283
+ return this._service.getSnapshot().context.modelName;
6284
+ }
6285
+ get properties() {
6286
+ return this._propertiesSubject.value;
6287
+ }
6288
+ unload() {
6289
+ var _b;
6290
+ (_b = this._subscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
6291
+ this._service.stop();
6292
+ }
6293
+ }
6294
+ _a$1 = immerable;
6295
+ Item.instanceCache = new Map();
6176
6296
 
6177
- const getItemProperties = (_a) => __awaiter(void 0, [_a], void 0, function* ({ seedLocalId, seedUid, edited, }) {
6178
- const appDb = getAppDb();
6179
- const whereClauses = [isNotNull(metadata.propertyName)];
6180
- const uidWhereClause = seedUid
6181
- ? eq(seeds.uid, seedUid)
6182
- : isNull(seeds.uid);
6183
- const localWhereClause = seedLocalId
6184
- ? eq(seeds.localId, seedLocalId)
6185
- : isNull(seeds.localId);
6186
- whereClauses.push(or(localWhereClause, uidWhereClause));
6187
- whereClauses.push(isNotNull(metadata.propertyName));
6188
- whereClauses.push(isNotNull(metadata.easDataType));
6189
- if (typeof edited !== 'undefined') {
6190
- if (edited) {
6191
- whereClauses.push(isNull(metadata.uid));
6297
+ const logger$3 = debug('app:react:services');
6298
+ const finalStrings = ['idle', 'ready', 'done', 'success'];
6299
+ const getServiceName = (service) => {
6300
+ let name = 'actor';
6301
+ if (service && service.uniqueKey) {
6302
+ name = service.uniqueKey;
6303
+ }
6304
+ if (service && !service.uniqueKey && service.logic && service.logic.config) {
6305
+ name = getServiceUniqueKey(service);
6306
+ }
6307
+ return name;
6308
+ };
6309
+ const getServiceValue = (service) => {
6310
+ let value;
6311
+ if (service && service.getSnapshot() && service.getSnapshot().value) {
6312
+ value = service.getSnapshot().value;
6313
+ }
6314
+ if (getServiceName(service) === 'global') {
6315
+ if (value &&
6316
+ typeof value === 'object' &&
6317
+ Object.keys(value).length > 0 &&
6318
+ Object.keys(value)[0] === 'initialized') {
6319
+ value = 'ready';
6192
6320
  }
6193
- if (!edited) {
6194
- whereClauses.push(isNotNull(metadata.uid));
6321
+ }
6322
+ if (value && typeof value === 'object') {
6323
+ value = JSON.stringify(value);
6324
+ }
6325
+ return value;
6326
+ };
6327
+ const getServiceUniqueKey = (service) => {
6328
+ if (!service || !service.logic || !service.logic.config) {
6329
+ return;
6330
+ }
6331
+ const config = service.logic.config;
6332
+ if (!config.id) {
6333
+ return;
6334
+ }
6335
+ let uniqueKey = config.id;
6336
+ if (config.id.includes('@seedSdk/')) {
6337
+ uniqueKey = config.id.match(/^.*@seedSdk\/(\w+)[\.\w]*/)[1];
6338
+ }
6339
+ let snapshot;
6340
+ try {
6341
+ snapshot = service.getSnapshot();
6342
+ }
6343
+ catch (error) {
6344
+ logger$3('Error:', error);
6345
+ return uniqueKey;
6346
+ }
6347
+ if (snapshot) {
6348
+ const context = snapshot.context;
6349
+ if (context && context.dbName) {
6350
+ uniqueKey = context.dbName;
6351
+ }
6352
+ if (context && context.modelNamePlural) {
6353
+ uniqueKey = context.modelNamePlural;
6354
+ }
6355
+ if (context && context.modelName) {
6356
+ uniqueKey = pluralize(context.modelName.toLowerCase());
6195
6357
  }
6196
6358
  }
6197
- // if (!seedLocalId || !seedUid) {
6198
- // const seedRows = await appDb
6199
- // .select({
6200
- // localId: seeds.localId,
6201
- // uid: seeds.uid,
6202
- // })
6203
- // .from(seeds)
6204
- // .where(or(localWhereClause, uidWhereClause))
6205
- //
6206
- // if (seedRows && seedRows.length > 0) {
6207
- // seedUid = seedRows[0].uid as string
6208
- // seedLocalId = seedRows[0].localId as string
6209
- // }
6210
- // }
6211
- const metadataColumns = getTableColumns(metadata);
6212
- const propertiesData = yield appDb
6213
- .select(Object.assign({}, metadataColumns))
6214
- .from(seeds)
6215
- .leftJoin(metadata, eq(metadata.seedLocalId, seeds.localId))
6216
- .leftJoin(versions, eq(versions.localId, seeds.localId))
6217
- .where(and(...whereClauses))
6218
- .groupBy(metadata.propertyName);
6219
- return propertiesData;
6220
- });
6221
- // const localIdWhere = seedLocalId
6222
- // ? `s.local_id = '${seedLocalId}'`
6223
- // : 's.local_id IS NULL'
6224
- // const uidWhere = seedUid ? `s.uid = '${seedUid}'` : 's.uid IS NULL'
6225
- //
6226
- // const queryStatement = `WITH LatestMetadata as (SELECT m.property_name,
6227
- // m.property_value,
6228
- // m.version_local_id,
6229
- // MAX(m.attestation_created_at),
6230
- // m.uid,
6231
- // m.seed_local_id,
6232
- // seed_uid
6233
- // FROM metadata m
6234
- // JOIN seeds s ON s.local_id = m.seed_local_id
6235
- // GROUP BY m.property_name),
6236
- //
6237
- // LatestVersion as (SELECT v.local_id,
6238
- // MAX(v.attestation_created_at) as attestation_created_at,
6239
- // v.uid,
6240
- // v.seed_local_id,
6241
- // v.seed_uid
6242
- // FROM versions v
6243
- // JOIN seeds s ON s.local_id = v.seed_local_id
6244
- // GROUP BY s.local_id)
6245
- //
6246
- //
6247
- // SELECT s.local_id,
6248
- // s.uid,
6249
- // s.schema_uid,
6250
- // m.property_name,
6251
- // m.property_value,
6252
- // COUNT(v.local_id) as versions_count,
6253
- // m.model_type,
6254
- // lv.attestation_created_at,
6255
- // m.local_id,
6256
- // m.uid,
6257
- // MAX(m.attestation_created_at),
6258
- // m.ref_seed_type,
6259
- // m.ref_value_type,
6260
- // m.seed_local_id,
6261
- // m.seed_uid,
6262
- // m.created_at,
6263
- // m.updated_at,
6264
- // m.version_uid
6265
- // FROM seeds s
6266
- // JOIN LatestMetadata lm ON s.local_id = m.seed_local_id
6267
- // JOIN LatestVersion lv ON lv.seed_local_id = m.seed_local_id
6268
- // JOIN metadata m ON m.property_name = lm.property_name OR lm.property_value = s.uid
6269
- // JOIN versions v ON s.local_id = v.seed_local_id
6270
- // WHERE ${localIdWhere}
6271
- // OR ${uidWhere}
6272
- // GROUP BY m.property_name;
6273
- // `
6274
- //
6275
- // const { rows } = await runQueryForStatement(queryStatement)
6276
- //
6277
- // const propertiesDataOld: PropertyData[] = []
6278
- //
6279
- // for (const row of rows) {
6280
- // propertiesDataOld.push({
6281
- // localId: row[0],
6282
- // uid: row[1],
6283
- // schemaUid: row[2],
6284
- // propertyName: row[3],
6285
- // propertyValue: row[4],
6286
- // versionsCount: row[5],
6287
- // itemModelName: row[6],
6288
- // attestationCreatedAt: row[7],
6289
- // metadataLocalId: row[8],
6290
- // metadataUid: row[9],
6291
- // metadataAttestationCreatedAt: row[10],
6292
- // refSeedType: row[11],
6293
- // refValueType: row[12],
6294
- // seedLocalId: row[13],
6295
- // seedUid: row[14],
6296
- // createdAt: row[15],
6297
- // updatedAt: row[16],
6298
- // versionUid: row[17],
6299
- // })
6300
- // }
6359
+ return uniqueKey;
6360
+ };
6361
+ const useIsDbReady = () => {
6362
+ const [isDbReady, setIsDbReady] = useState(false);
6363
+ const { internalStatus } = useGlobalServiceStatus();
6364
+ useEffect(() => {
6365
+ if (internalStatus === 'ready') {
6366
+ setIsDbReady(true);
6367
+ }
6368
+ }, [internalStatus]);
6369
+ return isDbReady;
6370
+ };
6371
+ const useServices = () => {
6372
+ const [actors, setActors] = useState([]);
6373
+ const [percentComplete, setPercentComplete] = useState(5);
6374
+ const actorsMap = new Map();
6375
+ useEffect(() => {
6376
+ const globalServiceListener = (event) => {
6377
+ if (event && event.type === 'init') {
6378
+ return;
6379
+ }
6380
+ if (event.actorRef &&
6381
+ event.actorRef.logic &&
6382
+ event.actorRef.logic.config) {
6383
+ const service = event.actorRef;
6384
+ const services = [service];
6385
+ if (service.logic.config.id === MachineIds.GLOBAL) {
6386
+ const context = service.getSnapshot().context;
6387
+ const keys = Object.keys(context);
6388
+ for (const key of keys) {
6389
+ if (!key.startsWith('internal') && key.endsWith('Service')) {
6390
+ const allItemsService = context[key];
6391
+ services.push(allItemsService);
6392
+ }
6393
+ }
6394
+ }
6395
+ services.forEach((innerService) => {
6396
+ const uniqueKey = getServiceUniqueKey(innerService);
6397
+ if (!uniqueKey) {
6398
+ return;
6399
+ }
6400
+ innerService.uniqueKey = uniqueKey;
6401
+ actorsMap.set(uniqueKey, innerService);
6402
+ });
6403
+ let actorsArray = Array.from(actorsMap.values());
6404
+ actorsArray = orderBy(actorsArray, (a) => a.logic.config.id, ['asc']);
6405
+ setActors(produce(actors, (draft) => {
6406
+ return actorsArray;
6407
+ }));
6408
+ }
6409
+ };
6410
+ eventEmitter.addListener('inspect.globalService', globalServiceListener);
6411
+ return () => {
6412
+ eventEmitter.removeListener('inspect.globalService', globalServiceListener);
6413
+ };
6414
+ }, []);
6415
+ useEffect(() => {
6416
+ const globalService = actors.find((actor) => getServiceName(actor) === 'global');
6417
+ const internalService = actors.find((actor) => getServiceName(actor) === 'internal');
6418
+ if (!globalService || !internalService) {
6419
+ return;
6420
+ }
6421
+ if (getServiceValue(globalService) === 'ready' &&
6422
+ getServiceValue(internalService) === 'ready') {
6423
+ const denominator = actors.length;
6424
+ const finishedActors = actors.filter((actor) => {
6425
+ const value = getServiceValue(actor);
6426
+ return finalStrings.includes(value);
6427
+ });
6428
+ const numerator = finishedActors.length;
6429
+ const percentComplete = (numerator / denominator) * 100;
6430
+ setPercentComplete(percentComplete);
6431
+ }
6432
+ }, [actors]);
6433
+ return {
6434
+ services: actors,
6435
+ percentComplete,
6436
+ };
6437
+ };
6438
+ const useGlobalServiceStatus = () => {
6439
+ const globalService = getGlobalService();
6440
+ const status = useSelector(globalService, (snapshot) => {
6441
+ return snapshot.value;
6442
+ });
6443
+ const internalStatus = useSelector(globalService.getSnapshot().context.internalService, (snapshot) => {
6444
+ if (!snapshot) {
6445
+ return;
6446
+ }
6447
+ return snapshot.value;
6448
+ });
6449
+ useSelector(globalService, (snapshot) => {
6450
+ return snapshot.context.internalService;
6451
+ });
6452
+ return {
6453
+ status,
6454
+ internalStatus,
6455
+ };
6456
+ };
6301
6457
 
6302
- var _a$1;
6303
- class Item {
6304
- constructor(initialValues) {
6305
- this[_a$1] = true;
6306
- this._propertiesSubject = new BehaviorSubject({});
6307
- this.subscribe = (callback) => {
6308
- return this._service.subscribe((snapshot) => {
6309
- callback(snapshot.context);
6310
- });
6311
- };
6312
- this.getService = () => {
6313
- return this._service;
6314
- };
6315
- this.getEditedProperties = () => __awaiter(this, void 0, void 0, function* () {
6316
- return yield getItemProperties({
6317
- seedLocalId: this.seedLocalId,
6318
- edited: true,
6319
- });
6320
- });
6321
- this.publish = () => __awaiter(this, void 0, void 0, function* () {
6322
- yield waitForEvent({
6323
- req: {
6324
- eventLabel: `item.publish.request`,
6325
- data: {
6326
- seedLocalId: this.seedLocalId,
6327
- },
6328
- },
6329
- res: {
6330
- eventLabel: `item.${this.seedLocalId}.publish.success`,
6331
- },
6458
+ const logger$2 = debug('app:react:item');
6459
+ const useItem = ({ modelName, seedLocalId, seedUid }) => {
6460
+ const [itemData, setItemData] = useImmer({});
6461
+ const [item, setItem] = useState();
6462
+ const [itemSubscription, setItemSubscription] = useState();
6463
+ const { status, internalStatus } = useGlobalServiceStatus();
6464
+ const isReadingDb = useRef(false);
6465
+ const itemStatus = useSelector(item === null || item === void 0 ? void 0 : item.getService(), (snapshot) => snapshot === null || snapshot === void 0 ? void 0 : snapshot.value);
6466
+ const updateItem = useCallback((newItem) => {
6467
+ setItemData((draft) => {
6468
+ Object.keys(newItem.properties).forEach((propertyName) => {
6469
+ const value = newItem[propertyName];
6470
+ draft[propertyName] = value;
6332
6471
  });
6333
6472
  });
6334
- const { modelName, seedUid, schemaUid, seedLocalId, latestVersionLocalId, latestVersionUid, } = initialValues;
6335
- const ModelClass = getModel(modelName);
6336
- if (ModelClass &&
6337
- Object.keys(ModelClass === null || ModelClass === void 0 ? void 0 : ModelClass.schema).includes('storageTransactionId') &&
6338
- initialValues.storageTransactionId) {
6339
- this._storageTransactionId = initialValues.storageTransactionId;
6473
+ }, []);
6474
+ const readFromDb = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
6475
+ if (isReadingDb.current ||
6476
+ internalStatus !== 'ready' ||
6477
+ (!seedUid && !seedLocalId)) {
6478
+ return;
6340
6479
  }
6341
- this._service = createActor(itemMachineSingle, {
6342
- input: {
6343
- seedLocalId,
6344
- seedUid,
6345
- schemaUid,
6346
- ModelClass,
6347
- latestVersionLocalId,
6348
- latestVersionUid,
6349
- storageTransactionId: this._storageTransactionId,
6350
- },
6480
+ isReadingDb.current = true;
6481
+ const foundItem = yield Item.find({
6482
+ modelName,
6483
+ seedLocalId,
6484
+ seedUid,
6351
6485
  });
6352
- this._subscription = this._service.subscribe((snapshot) => {
6353
- const { context } = snapshot;
6354
- if (!context ||
6355
- !context.propertyInstances ||
6356
- context.propertyInstances.size === 0) {
6357
- return;
6358
- }
6359
- const propertiesObj = {};
6360
- for (const [key, propertyInstance] of context.propertyInstances) {
6361
- if (typeof key !== 'string' || internalPropertyNames.includes(key)) {
6362
- propertiesObj[key.toString()] = propertyInstance;
6363
- continue;
6364
- }
6365
- let transformedKey = key;
6366
- if (propertyInstance.alias) {
6367
- transformedKey = propertyInstance.alias;
6368
- }
6369
- if (!propertyInstance.alias && key.endsWith('Ids')) {
6370
- transformedKey = key.slice(0, -3); // Remove 'Ids'
6371
- transformedKey = pluralize(transformedKey);
6372
- }
6373
- if (!propertyInstance.alias && key.endsWith('Id')) {
6374
- transformedKey = key.slice(0, -2); // Remove 'Id'
6486
+ if (!foundItem) {
6487
+ logger$2('[useItem] [getItemFromDb] no item found', modelName, seedLocalId);
6488
+ return;
6489
+ }
6490
+ setItem(foundItem);
6491
+ updateItem(foundItem);
6492
+ isReadingDb.current = false;
6493
+ }), [internalStatus]);
6494
+ const listenerRef = useRef(readFromDb);
6495
+ useEffect(() => {
6496
+ listenerRef.current = readFromDb;
6497
+ }, [readFromDb]);
6498
+ useEffect(() => {
6499
+ if (internalStatus === 'ready') {
6500
+ listenerRef.current();
6501
+ }
6502
+ }, [internalStatus, status]);
6503
+ useEffect(() => {
6504
+ if (item && !itemSubscription) {
6505
+ const subscription = item.subscribe((_) => __awaiter(void 0, void 0, void 0, function* () {
6506
+ const newItem = yield Item.find({ modelName, seedLocalId, seedUid });
6507
+ if (!newItem) {
6508
+ logger$2('[useItem] [itemSubscription] no item found', modelName, seedLocalId);
6509
+ return;
6375
6510
  }
6376
- propertiesObj[transformedKey] = propertyInstance;
6377
- }
6378
- this._propertiesSubject.next(propertiesObj);
6379
- eventEmitter.emit(`item.${modelName}.${seedUid || seedLocalId}.update`);
6511
+ updateItem(newItem);
6512
+ setItem(newItem);
6513
+ }));
6514
+ setItemSubscription(subscription);
6515
+ }
6516
+ return () => {
6517
+ itemSubscription === null || itemSubscription === void 0 ? void 0 : itemSubscription.unsubscribe();
6518
+ };
6519
+ }, [item, itemSubscription]);
6520
+ useEffect(() => {
6521
+ const seedId = seedUid || seedLocalId;
6522
+ eventEmitter.addListener(`item.${modelName}.${seedId}.update`, () => {
6523
+ listenerRef.current();
6380
6524
  });
6381
- this._service.start();
6382
- const definedKeys = ['ModelClass'];
6383
- const itemPropertyBase = {
6525
+ return () => {
6526
+ eventEmitter.removeListener(`item.${modelName}.${seedId}.update`, readFromDb);
6527
+ };
6528
+ }, []);
6529
+ return {
6530
+ item,
6531
+ itemData,
6532
+ itemStatus,
6533
+ };
6534
+ };
6535
+ const useItems = ({ modelName, deleted }) => {
6536
+ const [items, setItems] = useImmer([]);
6537
+ const [isReadingDb, setIsReadingDb] = useState(false);
6538
+ const [isInitialized, setIsInitialized] = useState(false);
6539
+ const isDbReady = useIsDbReady();
6540
+ const modelNameRef = useRef(modelName);
6541
+ const readFromDb = useCallback((event) => __awaiter(void 0, void 0, void 0, function* () {
6542
+ if (!event ||
6543
+ !event.modelName ||
6544
+ event.modelName !== modelNameRef.current ||
6545
+ isReadingDb) {
6546
+ return;
6547
+ }
6548
+ setIsReadingDb(true);
6549
+ const allItems = yield Item.all(modelNameRef.current, deleted);
6550
+ setItems(() => allItems);
6551
+ setIsReadingDb(false);
6552
+ }), [modelName, isReadingDb]);
6553
+ useEffect(() => {
6554
+ if (isDbReady && !isInitialized) {
6555
+ const _fetchItems = () => __awaiter(void 0, void 0, void 0, function* () {
6556
+ yield readFromDb({ modelName });
6557
+ setIsInitialized(true);
6558
+ });
6559
+ _fetchItems();
6560
+ }
6561
+ }, [isInitialized, isDbReady]);
6562
+ useEffect(() => {
6563
+ eventEmitter.addListener('item.requestAll', readFromDb);
6564
+ return () => {
6565
+ eventEmitter.removeListener('item.requestAll');
6566
+ };
6567
+ }, []);
6568
+ return {
6569
+ items: orderBy(items, [
6570
+ (item) => item.lastVersionPublishedAt ||
6571
+ item.attestationCreatedAt ||
6572
+ item.createdAt,
6573
+ ], ['desc']).slice(0, 10),
6574
+ isReadingDb,
6575
+ isInitialized,
6576
+ };
6577
+ };
6578
+ const useItemIsReady = () => {
6579
+ const [itemListenersReady, setItemListenersReady] = useState(false);
6580
+ const itemEventListenersHandler = useCallback((_) => {
6581
+ setItemListenersReady(true);
6582
+ }, []);
6583
+ useEffect(() => {
6584
+ const areReady = getAreItemEventHandlersReady();
6585
+ if (areReady) {
6586
+ itemEventListenersHandler(true);
6587
+ }
6588
+ eventEmitter.addListener('item.events.setupAllItemsEventHandlers', itemEventListenersHandler);
6589
+ return () => {
6590
+ eventEmitter.removeListener('item.events.setupAllItemsEventHandlers');
6591
+ };
6592
+ }, []);
6593
+ return {
6594
+ isReady: itemListenersReady,
6595
+ };
6596
+ };
6597
+ const useCreateItem = (modelName) => {
6598
+ const [isCreatingItem, setIsCreatingItem] = useState(false);
6599
+ const { isReady } = useItemIsReady();
6600
+ const createItem = useCallback((itemData) => __awaiter(void 0, void 0, void 0, function* () {
6601
+ if (!isReady) {
6602
+ console.error(`[useCreateItem] [createItem] called before listeners are ready`, itemData);
6603
+ return;
6604
+ }
6605
+ if (isCreatingItem) {
6606
+ // TODO: should we setup a queue for this?
6607
+ console.error(`[useCreateItem] [createItem] already creating item`, itemData);
6608
+ return;
6609
+ }
6610
+ setIsCreatingItem(true);
6611
+ const { seedLocalId } = yield createNewItem(Object.assign({ modelName }, itemData));
6612
+ yield Item.find({ modelName, seedLocalId });
6613
+ eventEmitter.emit('item.requestAll', { modelName });
6614
+ setIsCreatingItem(false);
6615
+ }), [isCreatingItem, isReady]);
6616
+ return {
6617
+ createItem,
6618
+ isCreatingItem,
6619
+ };
6620
+ };
6621
+
6622
+ const logger$1 = debug('app:react:property');
6623
+ const useItemProperty = ({ propertyName, seedLocalId, seedUid, }) => {
6624
+ const [property, setProperty] = useState();
6625
+ const [isReadingFromDb, setIsReadingFromDb] = useState(false);
6626
+ const [isInitialized, setIsInitialized] = useState(false);
6627
+ // const isDbReady = useMemo(() => useIsDbReady(), [])
6628
+ const { internalStatus } = useGlobalServiceStatus();
6629
+ const value = useSelector(property === null || property === void 0 ? void 0 : property.getService(), (snapshot) => {
6630
+ if (!snapshot || !snapshot.context) {
6631
+ return;
6632
+ }
6633
+ return snapshot.context.renderValue || snapshot.context.propertyValue;
6634
+ });
6635
+ const status = useSelector(property === null || property === void 0 ? void 0 : property.getService(), (snapshot) => snapshot === null || snapshot === void 0 ? void 0 : snapshot.value);
6636
+ // useEffect(() => {
6637
+ // if (property && property.value !== value) {
6638
+ // readFromDb()
6639
+ // }
6640
+ // }, [property, value])
6641
+ const readFromDb = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
6642
+ if (internalStatus !== 'ready' ||
6643
+ isReadingFromDb ||
6644
+ (!seedLocalId && !seedUid)) {
6645
+ return;
6646
+ }
6647
+ setIsReadingFromDb(true);
6648
+ const foundProperty = yield ItemProperty.find({
6649
+ propertyName,
6384
6650
  seedLocalId,
6385
6651
  seedUid,
6386
- versionLocalId: latestVersionLocalId,
6387
- versionUid: latestVersionUid,
6388
- itemModelName: modelName,
6389
- schemaUid,
6390
- };
6391
- if (ModelClass && ModelClass.schema) {
6392
- const schema = ModelClass.schema;
6393
- for (const [propertyName, propertyRecordSchema] of Object.entries(schema)) {
6394
- if (!propertyRecordSchema) {
6395
- throw new Error(`Property ${propertyName} has no definition`);
6396
- }
6397
- this._createPropertyInstance(Object.assign(Object.assign({}, itemPropertyBase), { propertyName, propertyValue: initialValues[propertyName] }));
6398
- definedKeys.push(propertyName);
6399
- }
6400
- }
6401
- Object.keys(initialValues).forEach((key) => {
6402
- // If we already defined it, that means it was in the schema
6403
- if (definedKeys.includes(key)) {
6404
- return;
6405
- }
6406
- this._createPropertyInstance(Object.assign(Object.assign({}, itemPropertyBase), { propertyName: key, propertyValue: initialValues[key] }));
6407
- });
6408
- }
6409
- static create(props) {
6410
- return __awaiter(this, void 0, void 0, function* () {
6411
- if (!props.seedUid) {
6412
- console.log('Creating new item without seedUid');
6413
- }
6414
- if (props.seedUid || props.seedLocalId) {
6415
- const seedId = (props.seedUid || props.seedLocalId);
6416
- if (Item.instanceCache.has(seedId)) {
6417
- const { instance, refCount } = Item.instanceCache.get(seedId);
6418
- Item.instanceCache.set(seedId, {
6419
- instance,
6420
- refCount: refCount + 1,
6421
- });
6422
- return instance;
6423
- }
6424
- if (!Item.instanceCache.has(seedId)) {
6425
- const newInstance = new Item(props);
6426
- Item.instanceCache.set(seedId, {
6427
- instance: newInstance,
6428
- refCount: 1,
6429
- });
6430
- return newInstance;
6431
- }
6432
- }
6433
- if (!props.modelName) {
6434
- throw new Error('Model name is required to create an item');
6435
- }
6436
- const { seedLocalId } = yield createNewItem({
6437
- modelName: props.modelName,
6438
- });
6439
- props.seedLocalId = seedLocalId;
6440
- const newInstance = new Item(props);
6441
- Item.instanceCache.set(newInstance.seedUid || newInstance.seedLocalId, {
6442
- instance: newInstance,
6443
- refCount: 1,
6444
- });
6445
- return newInstance;
6446
6652
  });
6447
- }
6448
- static find(_b) {
6449
- return __awaiter(this, arguments, void 0, function* ({ modelName, seedLocalId, seedUid, }) {
6450
- if (!seedLocalId && !seedUid) {
6451
- return;
6452
- }
6453
- const itemData = yield getItemDataFromDb({
6454
- modelName,
6455
- seedLocalId,
6456
- seedUid,
6457
- });
6458
- if (!itemData) {
6459
- console.error('No item data found', { modelName, seedLocalId, seedUid });
6460
- return;
6461
- }
6462
- if (!(itemData === null || itemData === void 0 ? void 0 : itemData.seedUid)) {
6463
- console.log('Item not found', { modelName, seedLocalId, seedUid });
6464
- }
6465
- return Item.create(Object.assign(Object.assign({}, itemData), { modelName }));
6466
- });
6467
- }
6468
- static all(modelName, deleted) {
6469
- return __awaiter(this, void 0, void 0, function* () {
6470
- const itemsData = yield getItemsData({ modelName, deleted });
6471
- const itemInstances = [];
6472
- for (const itemData of itemsData) {
6473
- itemInstances.push(yield Item.create(Object.assign(Object.assign({}, itemData), { modelName })));
6474
- }
6475
- return orderBy(itemInstances, ['createdAt'], ['desc']);
6476
- });
6477
- }
6478
- static publish(item) {
6479
- return __awaiter(this, void 0, void 0, function* () {
6480
- yield waitForEvent({
6481
- req: {
6482
- eventLabel: `item.${item.seedLocalId}.publish.request`,
6483
- data: {
6484
- seedLocalId: item.seedLocalId,
6485
- },
6486
- },
6487
- res: {
6488
- eventLabel: `item.${item.seedLocalId}.publish.success`,
6489
- },
6490
- });
6491
- });
6492
- }
6493
- _createPropertyInstance(props) {
6494
- if (this._storageTransactionId) {
6495
- props.storageTransactionId = this._storageTransactionId;
6653
+ setIsReadingFromDb(false);
6654
+ if (!foundProperty) {
6655
+ logger$1(`[useItemPropertyTest] [readFromDb] no property found for Item.${seedLocalId}.${propertyName}`);
6656
+ return;
6496
6657
  }
6497
- const propertyInstance = ItemProperty.create(props);
6498
- if (!propertyInstance) {
6658
+ if (foundProperty.status === 'waitingForDb') {
6659
+ foundProperty.getService().send({ type: 'waitForDbSuccess' });
6660
+ }
6661
+ setProperty(foundProperty);
6662
+ setIsInitialized(true);
6663
+ }), [internalStatus, isReadingFromDb]);
6664
+ // let count = 0
6665
+ //
6666
+ // const refresh = useCallback(() => {
6667
+ // count++
6668
+ // console.log('[useItemPropertyTest] [refresh] property', property)
6669
+ // }, [property])
6670
+ useEffect(() => {
6671
+ if (internalStatus === 'ready') {
6672
+ readFromDb();
6673
+ }
6674
+ }, [internalStatus]);
6675
+ // useEffect(() => {
6676
+ // eventEmitter.addListener(
6677
+ // `property.${seedUid || seedLocalId}.${propertyName}.update`,
6678
+ // (event) => {
6679
+ // refresh()
6680
+ // },
6681
+ // )
6682
+ //
6683
+ // return () => {
6684
+ // eventEmitter.removeListener(
6685
+ // `property.${seedUid || seedLocalId}.${propertyName}.update`,
6686
+ // )
6687
+ // }
6688
+ // }, [])
6689
+ return {
6690
+ property,
6691
+ isInitialized,
6692
+ isReadingFromDb,
6693
+ value,
6694
+ status,
6695
+ };
6696
+ };
6697
+ const useItemProperties = (item) => {
6698
+ const [propertyObj, setPropertyObj] = useImmer({});
6699
+ useState(false);
6700
+ const updatePropertyObj = useCallback((event) => {
6701
+ if (!item) {
6702
+ console.error('[XXXXXX] [updatePropertyObj] no item when expected');
6499
6703
  return;
6500
6704
  }
6501
- if (!propertyInstance.alias) {
6502
- this._service.send({
6503
- type: 'addPropertyInstance',
6504
- propertyName: props.propertyName,
6505
- propertyInstance,
6506
- });
6705
+ const { propertyName, propertyValue } = event;
6706
+ if (!propertyName) {
6707
+ return;
6507
6708
  }
6508
- Object.defineProperty(this, props.propertyName, {
6509
- get: () => propertyInstance.value,
6510
- set: (value) => (propertyInstance.value = value),
6511
- enumerable: true,
6709
+ setPropertyObj((draft) => {
6710
+ draft[propertyName] = propertyValue;
6512
6711
  });
6513
- }
6514
- get seedLocalId() {
6515
- return this._service.getSnapshot().context.seedLocalId;
6516
- }
6517
- get seedUid() {
6518
- return this._service.getSnapshot().context.seedUid;
6519
- }
6520
- get schemaUid() {
6521
- return this.properties['schemaUid'].value;
6522
- }
6523
- get latestVersionUid() {
6524
- return this.properties['latestVersionUid'].value;
6525
- }
6526
- get modelName() {
6527
- return this._service.getSnapshot().context.modelName;
6528
- }
6529
- get properties() {
6530
- return this._propertiesSubject.value;
6531
- }
6532
- unload() {
6533
- var _b;
6534
- (_b = this._subscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
6535
- this._service.stop();
6536
- }
6537
- }
6538
- _a$1 = immerable;
6539
- Item.instanceCache = new Map();
6712
+ }, [item]);
6713
+ useEffect(() => {
6714
+ if (!item) {
6715
+ return;
6716
+ }
6717
+ const eventKey = `item.${item.seedLocalId}.property.update`;
6718
+ eventEmitter.addListener(eventKey, updatePropertyObj);
6719
+ return () => {
6720
+ eventEmitter.removeListener(eventKey, updatePropertyObj);
6721
+ };
6722
+ }, [item]);
6723
+ return {
6724
+ properties: propertyObj,
6725
+ };
6726
+ };
6727
+
6728
+ debug('app:react:db');
6729
+
6730
+ const deleteItem = (_a) => __awaiter(void 0, [_a], void 0, function* ({ seedLocalId, seedUid }) {
6731
+ const appDb = getAppDb();
6732
+ yield appDb
6733
+ .update(seeds)
6734
+ .set({
6735
+ _markedForDeletion: 1,
6736
+ })
6737
+ .where(or(eq(seeds.localId, seedLocalId), eq(seeds.uid, seedUid)));
6738
+ });
6739
+
6740
+ const useDeleteItem = () => {
6741
+ const [isDeletingItem, setIsDeletingItem] = useState(false);
6742
+ const destroy = useCallback((item) => __awaiter(void 0, void 0, void 0, function* () {
6743
+ if (!item) {
6744
+ return;
6745
+ }
6746
+ setIsDeletingItem(true);
6747
+ const { modelName } = item.getService().getSnapshot().context;
6748
+ yield deleteItem({ seedLocalId: item.seedLocalId });
6749
+ eventEmitter.emit('item.requestAll', { modelName });
6750
+ setIsDeletingItem(false);
6751
+ }), [isDeletingItem]);
6752
+ useEffect(() => { }, []);
6753
+ return {
6754
+ deleteItem: destroy,
6755
+ isDeletingItem,
6756
+ };
6757
+ };
6758
+
6759
+ const logger = debug('app:services:events');
6760
+ const handleServiceSaveState = (event) => {
6761
+ const { state, serviceId } = event;
6762
+ logger(`[browser] [service.saveState.request] serviceId: ${serviceId}`);
6763
+ localStorage.setItem(`seed_sdk_service_${serviceId}`, JSON.stringify(state));
6764
+ };
6765
+ const setupServicesEventHandlers = () => {
6766
+ eventEmitter.addListener('service.saveState.request', handleServiceSaveState);
6767
+ };
6540
6768
 
6541
- const logger = debug('app:db:queries:getItem');
6542
- const getItemDataFromDb = (_a) => __awaiter(void 0, [_a], void 0, function* ({ modelName, seedLocalId, seedUid, }) {
6543
- if (!seedLocalId && !seedUid) {
6544
- throw new Error('[db/queries] [getItem] no seedLocalId or seedUid');
6545
- }
6546
- if (seedUid && !seedLocalId) {
6547
- const seedData = yield getSeedData({ seedUid });
6548
- if (!seedData) {
6549
- logger('[db/queries] [getItem] no seedData seedUid', seedUid);
6550
- return;
6551
- }
6552
- seedLocalId = seedData.localId;
6553
- }
6554
- const appDb = getAppDb();
6555
- const _b = getTableColumns(seeds), rest = __rest(_b, ["localId", "uid"]);
6556
- const whereClauses = [];
6557
- if (modelName) {
6558
- whereClauses.push(eq(seeds.type, modelName.toLowerCase()));
6559
- }
6560
- if (seedUid) {
6561
- whereClauses.push(eq(seeds.uid, seedUid));
6562
- }
6563
- if (seedLocalId && !seedUid) {
6564
- whereClauses.push(eq(seeds.localId, seedLocalId));
6565
- }
6566
- const versionData = getVersionData();
6567
- const itemDataRows = yield appDb
6568
- .with(versionData)
6569
- .select(Object.assign(Object.assign({}, rest), { seedLocalId: seeds.localId, seedUid: seeds.uid, versionsCount: versionData.versionsCount, lastVersionPublishedAt: versionData.lastVersionPublishedAt, latestVersionUid: versionData.latestVersionUid, latestVersionLocalId: versionData.latestVersionLocalId }))
6570
- .from(seeds)
6571
- .leftJoin(versionData, eq(seeds.localId, versionData.seedLocalId))
6572
- .where(and(...whereClauses, gt(versionData.versionsCount, 0)))
6573
- .orderBy(sql.raw('COALESCE(attestation_created_at, created_at) DESC'))
6574
- .groupBy(seeds.localId);
6575
- if (!itemDataRows || itemDataRows.length === 0) {
6576
- logger('[db/queries] [getItemDataFromDb] no itemDataRows');
6769
+ const saveServiceHandler = (event) => __awaiter(void 0, void 0, void 0, function* () {
6770
+ const globalService = getGlobalService();
6771
+ if (!globalService || !globalService.getSnapshot().context) {
6577
6772
  return;
6578
6773
  }
6579
- let itemData = itemDataRows[0];
6580
- const propertiesData = yield getItemProperties({ seedLocalId, seedUid });
6581
- // const initObj: ItemData = {
6582
- // seedLocalId,
6583
- // seedUid,
6584
- // modelName,
6585
- // }
6586
- if (!propertiesData || propertiesData.length === 0) {
6587
- return itemData;
6588
- }
6589
- propertiesData[0];
6590
- for (const propertyData of propertiesData) {
6591
- const propertyName = propertyData.propertyName;
6592
- const propertyValue = propertyData.propertyValue;
6593
- // TODO: Find a better place for the property data below
6594
- // Since initObj is used to initialize an Item, the following values
6595
- // just overwrite each other for each property since they are Property
6596
- // specific.
6597
- // const refSeedType = propertyDbValues[11]
6598
- // if (refSeedType) {
6599
- // initObj.refSeedType = refSeedType
6600
- // }
6601
- // const refValueType = propertyDbValues[12]
6602
- // if (refValueType) {
6603
- // initObj.refValueType = refValueType
6604
- // }
6605
- //
6606
- // if (
6607
- // refSeedType &&
6608
- // refValueType === 'list' &&
6609
- // propertyName.endsWith('Ids')
6610
- // ) {
6611
- // logger('[db/queries] [getItemDataFromDb] propertyName', propertyName)
6612
- // }
6613
- itemData[propertyName] = propertyValue;
6614
- }
6615
- return itemData;
6774
+ const { modelName } = event;
6775
+ const nameOfService = `${modelName}Service`;
6776
+ const service = globalService.getSnapshot().context[nameOfService];
6777
+ yield writeAppState(`snapshot__${modelName}`, JSON.stringify(service.getPersistedSnapshot()));
6616
6778
  });
6617
6779
 
6780
+ const setupServiceHandlers = () => {
6781
+ eventEmitter.addListener('service.save', saveServiceHandler);
6782
+ };
6783
+
6784
+ const client = {
6785
+ init: ({ config, addresses }) => {
6786
+ const { endpoints, models } = config;
6787
+ for (const [key, value] of Object.entries(models)) {
6788
+ setModel(key, value);
6789
+ }
6790
+ setupFsListeners();
6791
+ setupAllItemsEventHandlers();
6792
+ setupServicesEventHandlers();
6793
+ setupServiceHandlers();
6794
+ if (areFsListenersReady()) {
6795
+ eventEmitter.emit('fs.init');
6796
+ }
6797
+ if (!areFsListenersReady()) {
6798
+ console.error('fs listeners not ready during init');
6799
+ }
6800
+ globalService.send({ type: 'init', endpoints, models, addresses });
6801
+ import('./seed.schema.config-BHZSMMmL.js').then(({ models }) => {
6802
+ for (const [key, value] of Object.entries(models)) {
6803
+ setModel(key, value);
6804
+ }
6805
+ });
6806
+ },
6807
+ subscribe: (callback) => {
6808
+ callback({
6809
+ type: '@xstate.snapshot',
6810
+ actorRef: globalService,
6811
+ snapshot: globalService.getSnapshot(),
6812
+ });
6813
+ eventEmitter.addListener('globalService', callback);
6814
+ return {
6815
+ unsubscribe: () => {
6816
+ eventEmitter.removeListener('globalService', callback);
6817
+ },
6818
+ };
6819
+ },
6820
+ on: (outerEvent, callback) => {
6821
+ eventEmitter.addListener(outerEvent, callback);
6822
+ return {
6823
+ unsubscribe: () => {
6824
+ eventEmitter.removeListener(outerEvent, callback);
6825
+ },
6826
+ };
6827
+ },
6828
+ getSeedClass: () => __awaiter(void 0, void 0, void 0, function* () {
6829
+ return new Promise((resolve) => {
6830
+ const subscription = globalService.subscribe((snapshot) => {
6831
+ if (snapshot.status === 'done') {
6832
+ resolve(snapshot.output);
6833
+ }
6834
+ });
6835
+ globalService.send({ type: 'getSeed' });
6836
+ subscription.unsubscribe();
6837
+ });
6838
+ }),
6839
+ getModel: (modelName) => {
6840
+ return getModel(modelName);
6841
+ },
6842
+ getModels: () => {
6843
+ return getModels();
6844
+ },
6845
+ getModelNames: () => {
6846
+ return getModelNames();
6847
+ },
6848
+ };
6849
+
6618
6850
  const getItemPropertyData = (props) => __awaiter(void 0, void 0, void 0, function* () {
6619
6851
  const appDb = getAppDb();
6620
6852
  const whereClauses = [];
6621
6853
  const tableColumns = getTableColumns(metadata);
6622
6854
  for (const [propertyName, propertyValue] of Object.entries(props)) {
6623
6855
  if (Object.keys(tableColumns).includes(propertyName)) {
6624
- tableColumns[propertyName];
6625
6856
  whereClauses.push(eq(tableColumns[propertyName], propertyValue));
6626
6857
  }
6627
6858
  }
@@ -6635,142 +6866,141 @@ const getItemPropertyData = (props) => __awaiter(void 0, void 0, void 0, functio
6635
6866
  return queryRows[0];
6636
6867
  });
6637
6868
 
6638
- const createMetadata = (metadataValues, propertyRecordSchema) => __awaiter(void 0, void 0, void 0, function* () {
6639
- const appDb = getAppDb();
6640
- metadataValues.localId = generateId();
6641
- if (propertyRecordSchema &&
6642
- propertyRecordSchema.localStorageDir &&
6643
- propertyRecordSchema.storageType === 'ItemStorage') {
6644
- metadataValues.refResolvedValue = `${metadataValues.localId}${propertyRecordSchema.filenameSuffix}`;
6645
- metadataValues.refValueType = 'file';
6869
+ const saveItemStorage = fromCallback(({ sendBack, input: { context, event } }) => {
6870
+ const { localId, seedLocalId, seedUid, propertyName, propertyRecordSchema, itemModelName, propertyValue: existingValue, } = context;
6871
+ if (!propertyRecordSchema) {
6872
+ throw new Error('Missing propertyRecordSchema');
6646
6873
  }
6647
- return appDb
6648
- .insert(metadata)
6649
- .values(Object.assign(Object.assign({}, metadataValues), { createdAt: Date.now(), updatedAt: Date.now() }))
6650
- .returning();
6874
+ let newValue;
6875
+ if (event) {
6876
+ newValue = event.newValue;
6877
+ }
6878
+ if (existingValue === newValue) {
6879
+ sendBack({ type: 'saveValueToDbSuccess' });
6880
+ return;
6881
+ }
6882
+ const _saveItemStorage = () => __awaiter(void 0, void 0, void 0, function* () {
6883
+ // Save value to file
6884
+ const appDb = getAppDb();
6885
+ let propertyData;
6886
+ if (localId) {
6887
+ propertyData = yield getItemPropertyData({
6888
+ localId,
6889
+ });
6890
+ }
6891
+ if (!localId && seedLocalId) {
6892
+ const itemData = yield getItemDataFromDb({
6893
+ seedLocalId,
6894
+ });
6895
+ if (itemData) {
6896
+ const whereClauses = [
6897
+ eq(metadata.propertyName, propertyName),
6898
+ eq(metadata.seedLocalId, seedLocalId),
6899
+ ];
6900
+ if (itemData.latestVersionLocalId) {
6901
+ whereClauses.push(eq(metadata.versionLocalId, itemData.latestVersionLocalId));
6902
+ }
6903
+ const queryRows = yield appDb
6904
+ .select()
6905
+ .from(metadata)
6906
+ .where(and(...whereClauses));
6907
+ if (queryRows && queryRows.length) {
6908
+ propertyData = queryRows[0];
6909
+ }
6910
+ if (!propertyData) {
6911
+ const propertyDataRows = yield createMetadata({
6912
+ propertyName,
6913
+ modelType: itemModelName.toLowerCase(),
6914
+ seedLocalId,
6915
+ seedUid,
6916
+ versionLocalId: itemData.latestVersionLocalId,
6917
+ versionUid: itemData.latestVersionUid,
6918
+ localStorageDir: propertyRecordSchema.localStorageDir,
6919
+ refValueType: 'file',
6920
+ }, propertyRecordSchema);
6921
+ propertyData = propertyDataRows[0];
6922
+ }
6923
+ // propertyData = {
6924
+ // propertyName,
6925
+ // seedLocalId,
6926
+ // seedUid,
6927
+ // versionLocalId: itemData.latestVersionLocalId,
6928
+ // versionUid: itemData.latestVersionUid,
6929
+ // schemaUid: itemData.schemaUid,
6930
+ // }
6931
+ }
6932
+ }
6933
+ const localStorageDir = propertyRecordSchema.localStorageDir || propertyData.localStorageDir;
6934
+ const fileName = propertyData.refResolvedValue ||
6935
+ `${propertyData.seedLocalId}${propertyRecordSchema.filenameSuffix}`;
6936
+ if (!localStorageDir || !fileName) {
6937
+ throw new Error(`Missing localStorageDir: ${localStorageDir} or fileName: ${fileName}`);
6938
+ }
6939
+ const filePath = `/files/${localStorageDir}/${fileName}`;
6940
+ yield fs.promises.writeFile(filePath, newValue);
6941
+ yield appDb
6942
+ .update(metadata)
6943
+ .set({
6944
+ refResolvedValue: fileName,
6945
+ })
6946
+ .where(eq(metadata.localId, propertyData.localId));
6947
+ sendBack({
6948
+ type: 'updateContext',
6949
+ renderValue: newValue,
6950
+ });
6951
+ return true;
6952
+ });
6953
+ _saveItemStorage().then((success) => {
6954
+ if (success) {
6955
+ sendBack({ type: 'saveItemStorageSuccess' });
6956
+ }
6957
+ });
6651
6958
  });
6652
6959
 
6653
- const saveValueToDb = fromCallback(({ sendBack, input: { context, event } }) => {
6654
- const { localId, propertyName: propertyNameRaw, seedLocalId, seedUid, versionLocalId, versionUid, propertyValue: existingValue, propertyRecordSchema, itemModelName, schemaUid, } = context;
6655
- let { newValue } = event;
6960
+ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
6961
+ const { localId, propertyName: propertyNameRaw, seedLocalId, versionLocalId, propertyValue: existingValue, propertyRecordSchema, itemModelName, schemaUid, } = context;
6962
+ let newValue;
6963
+ if (event) {
6964
+ newValue = event.newValue;
6965
+ }
6656
6966
  if (existingValue === newValue) {
6657
6967
  sendBack({ type: 'saveValueToDbSuccess' });
6658
6968
  return;
6659
6969
  }
6660
- const _saveValueToDb = () => __awaiter(void 0, void 0, void 0, function* () {
6661
- let refResolvedValue;
6662
- let refResolvedDisplayValue;
6663
- let refSeedType;
6970
+ if (!propertyRecordSchema) {
6971
+ throw new Error('Missing propertyRecordSchema');
6972
+ }
6973
+ const _analyzeInput = () => __awaiter(void 0, void 0, void 0, function* () {
6664
6974
  let propertyName = propertyNameRaw;
6665
- if (propertyRecordSchema && propertyRecordSchema.dataType === 'Relation') {
6666
- refResolvedValue = newValue;
6667
- if (!propertyName.endsWith('Id')) {
6668
- propertyName = `${propertyName}Id`;
6669
- }
6670
- let fileType;
6671
- const dirs = yield fs.promises.readdir('/files');
6672
- for (const dir of dirs) {
6673
- const files = yield fs.promises.readdir(`/files/${dir}`);
6674
- if (files.includes(newValue)) {
6675
- fileType = dir;
6676
- break;
6677
- }
6678
- }
6679
- if (fileType === 'images') {
6680
- const filePath = `/files/images/${newValue}`;
6681
- refResolvedDisplayValue = yield getContentUrlFromPath(filePath);
6682
- refSeedType = 'image';
6683
- newValue = yield createSeed({
6684
- type: refSeedType,
6685
- });
6686
- yield createVersion({
6687
- seedLocalId,
6688
- seedUid,
6689
- seedType: refSeedType,
6690
- });
6691
- }
6975
+ if (propertyRecordSchema.refValueType !== 'ImageSrc' &&
6976
+ propertyRecordSchema.dataType === 'Relation') {
6977
+ sendBack({
6978
+ type: 'saveRelation',
6979
+ newValue,
6980
+ });
6981
+ return false;
6692
6982
  }
6693
- if (propertyRecordSchema &&
6694
- propertyRecordSchema.storageType &&
6983
+ if (propertyRecordSchema.refValueType === 'ImageSrc' ||
6984
+ propertyRecordSchema.dataType === 'ImageSrc') {
6985
+ sendBack({
6986
+ type: 'saveImageSrc',
6987
+ newValue,
6988
+ });
6989
+ return false;
6990
+ }
6991
+ if (propertyRecordSchema.storageType &&
6695
6992
  propertyRecordSchema.storageType === 'ItemStorage') {
6696
- // Save value to file
6697
- const appDb = getAppDb();
6698
- let propertyData;
6699
- if (localId) {
6700
- propertyData = yield getItemPropertyData({
6701
- localId,
6702
- });
6703
- }
6704
- if (!localId && seedLocalId) {
6705
- const itemData = yield getItemDataFromDb({
6706
- seedLocalId,
6707
- });
6708
- if (itemData) {
6709
- const whereClauses = [
6710
- eq(metadata.propertyName, propertyName),
6711
- eq(metadata.seedLocalId, seedLocalId),
6712
- ];
6713
- if (itemData.latestVersionLocalId) {
6714
- whereClauses.push(eq(metadata.versionLocalId, itemData.latestVersionLocalId));
6715
- }
6716
- const queryRows = yield appDb
6717
- .select()
6718
- .from(metadata)
6719
- .where(and(...whereClauses));
6720
- if (queryRows && queryRows.length) {
6721
- propertyData = queryRows[0];
6722
- }
6723
- if (!propertyData) {
6724
- const propertyDataRows = yield createMetadata({
6725
- propertyName,
6726
- modelType: itemModelName.toLowerCase(),
6727
- seedLocalId,
6728
- seedUid,
6729
- versionLocalId: itemData.latestVersionLocalId,
6730
- versionUid: itemData.latestVersionUid,
6731
- localStorageDir: propertyRecordSchema.localStorageDir,
6732
- refValueType: 'file',
6733
- }, propertyRecordSchema);
6734
- propertyData = propertyDataRows[0];
6735
- }
6736
- // propertyData = {
6737
- // propertyName,
6738
- // seedLocalId,
6739
- // seedUid,
6740
- // versionLocalId: itemData.latestVersionLocalId,
6741
- // versionUid: itemData.latestVersionUid,
6742
- // schemaUid: itemData.schemaUid,
6743
- // }
6744
- }
6745
- }
6746
- const localStorageDir = propertyRecordSchema.localStorageDir || propertyData.localStorageDir;
6747
- const fileName = propertyData.refResolvedValue ||
6748
- `${propertyData.localId}${propertyRecordSchema.filenameSuffix}`;
6749
- if (!localStorageDir || !fileName) {
6750
- throw new Error(`Missing localStorageDir: ${localStorageDir} or fileName: ${fileName}`);
6751
- }
6752
- const filePath = `/files/${localStorageDir}/${fileName}`;
6753
- yield fs.promises.writeFile(filePath, newValue);
6754
- yield appDb
6755
- .update(metadata)
6756
- .set({
6757
- refResolvedValue: fileName,
6758
- })
6759
- .where(eq(metadata.localId, propertyData.localId));
6760
6993
  sendBack({
6761
- type: 'updateContext',
6762
- renderValue: newValue,
6994
+ type: 'saveItemStorage',
6995
+ newValue,
6763
6996
  });
6764
- return;
6997
+ return false;
6765
6998
  }
6766
6999
  yield updateItemPropertyValue({
6767
7000
  propertyLocalId: localId,
6768
7001
  propertyName,
6769
7002
  newValue,
6770
7003
  seedLocalId,
6771
- refSeedType,
6772
- refResolvedValue,
6773
- refResolvedDisplayValue,
6774
7004
  versionLocalId,
6775
7005
  modelName: itemModelName,
6776
7006
  schemaUid,
@@ -6778,11 +7008,13 @@ const saveValueToDb = fromCallback(({ sendBack, input: { context, event } }) =>
6778
7008
  sendBack({
6779
7009
  type: 'updateContext',
6780
7010
  propertyValue: newValue,
6781
- renderValue: refResolvedDisplayValue,
6782
7011
  });
7012
+ return true;
6783
7013
  });
6784
- _saveValueToDb().then(() => {
6785
- sendBack({ type: 'saveValueToDbSuccess' });
7014
+ _analyzeInput().then((isDone) => {
7015
+ if (isDone) {
7016
+ sendBack({ type: 'saveValueToDbSuccess' });
7017
+ }
6786
7018
  });
6787
7019
  });
6788
7020
 
@@ -6790,6 +7022,7 @@ const saveValueToDb = fromCallback(({ sendBack, input: { context, event } }) =>
6790
7022
  const propertyMachine = setup({
6791
7023
  types: {
6792
7024
  context: {},
7025
+ input: {},
6793
7026
  },
6794
7027
  // actions: {
6795
7028
  // updateContext: updateMachineContext,
@@ -6800,7 +7033,10 @@ const propertyMachine = setup({
6800
7033
  initialize: initialize$3,
6801
7034
  resolveRelatedValue,
6802
7035
  resolveRemoteStorage,
6803
- saveValueToDb,
7036
+ analyzeInput,
7037
+ saveImageSrc,
7038
+ saveRelation,
7039
+ saveItemStorage,
6804
7040
  },
6805
7041
  }).createMachine({
6806
7042
  id: 'itemProperty',
@@ -6913,23 +7149,60 @@ const propertyMachine = setup({
6913
7149
  },
6914
7150
  },
6915
7151
  saving: {
6916
- on: {
6917
- saveValueToDbSuccess: {
6918
- target: 'idle',
6919
- actions: assign({
6920
- isSaving: false,
6921
- }),
7152
+ initial: 'analyzingInput',
7153
+ states: {
7154
+ analyzingInput: {
7155
+ on: {
7156
+ saveValueToDbSuccess: {
7157
+ target: 'doneSaving',
7158
+ },
7159
+ saveImageSrc: 'savingImageSrc',
7160
+ saveRelation: 'savingRelation',
7161
+ saveItemStorage: 'savingItemStorage',
7162
+ },
7163
+ invoke: {
7164
+ src: 'analyzeInput',
7165
+ input: ({ context, event }) => ({ context, event }),
7166
+ },
6922
7167
  },
6923
- saveValueToDbFailure: {
6924
- target: 'idle',
6925
- actions: assign({
6926
- isSaving: false,
6927
- }),
7168
+ savingImageSrc: {
7169
+ on: {
7170
+ saveImageSrcSuccess: 'doneSaving',
7171
+ },
7172
+ invoke: {
7173
+ src: 'saveImageSrc',
7174
+ input: ({ context, event }) => ({ context, event }),
7175
+ },
7176
+ },
7177
+ savingRelation: {
7178
+ on: {
7179
+ saveRelationSuccess: 'doneSaving',
7180
+ },
7181
+ invoke: {
7182
+ src: 'saveRelation',
7183
+ input: ({ context, event }) => ({ context, event }),
7184
+ },
7185
+ },
7186
+ savingItemStorage: {
7187
+ on: {
7188
+ saveItemStorageSuccess: 'doneSaving',
7189
+ },
7190
+ invoke: {
7191
+ src: 'saveItemStorage',
7192
+ input: ({ context, event }) => ({ context, event }),
7193
+ },
7194
+ },
7195
+ doneSaving: {
7196
+ type: 'final',
6928
7197
  },
6929
7198
  },
6930
- invoke: {
6931
- src: 'saveValueToDb',
6932
- input: ({ context, event }) => ({ context, event }),
7199
+ onDone: {
7200
+ target: 'idle',
7201
+ actions: assign(({ context }) => {
7202
+ return {
7203
+ isSaving: false,
7204
+ };
7205
+ }),
6933
7206
  },
6934
7207
  },
6935
7208
  },
@@ -7097,4 +7370,4 @@ if (isNode()) {
7097
7370
  }
7098
7371
 
7099
7372
  export { GET_SCHEMAS as G, Item as I, Json as J, List as L, Model as M, Property as P, Relation as R, Text as T, GET_SEEDS as a, GET_SEED_IDS as b, GET_STORAGE_TRANSACTION_ID as c, GET_VERSIONS as d, GET_PROPERTIES as e, GET_ALL_PROPERTIES_FOR_ALL_VERSIONS as f, itemMachineAll as g, ImageSrc as h, itemMachineSingle as i, ItemProperty as j, useItem as k, useItemProperties as l, useCreateItem as m, useItemProperty as n, useDeleteItem as o, useGlobalServiceStatus as p, useServices as q, getGlobalService as r, client as s, getCorrectId as t, useItems as u, withSeed as w };
7100
- //# sourceMappingURL=index-DQKd-s2Q.js.map
7373
+ //# sourceMappingURL=index-D4my8yy8.js.map