@seedprotocol/sdk 0.1.54 → 0.1.56

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