@xyo-network/os-runtime 3.0.0

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 (132) hide show
  1. package/LICENSE +165 -0
  2. package/README.md +13 -0
  3. package/dist/neutral/index.d.ts +1656 -0
  4. package/dist/neutral/index.mjs +3432 -0
  5. package/dist/neutral/index.mjs.map +1 -0
  6. package/package.json +78 -0
  7. package/src/Caller.ts +221 -0
  8. package/src/DappCallerBase.ts +52 -0
  9. package/src/DefaultsQueries.ts +27 -0
  10. package/src/OsCallerBase.ts +55 -0
  11. package/src/PubSubBridgeCaller.ts +30 -0
  12. package/src/XyOs.ts +125 -0
  13. package/src/XyOsBase.ts +119 -0
  14. package/src/XyOsDapp.ts +90 -0
  15. package/src/access-interfaces/ValidDappAccessInterfaces.ts +8 -0
  16. package/src/access-interfaces/index.ts +2 -0
  17. package/src/access-interfaces/registered-names/helpers/AccessNodeQueries.ts +59 -0
  18. package/src/access-interfaces/registered-names/helpers/index.ts +2 -0
  19. package/src/access-interfaces/registered-names/helpers/resource/AbstractXnsCaller.ts +38 -0
  20. package/src/access-interfaces/registered-names/helpers/resource/RegistrationsResource.ts +54 -0
  21. package/src/access-interfaces/registered-names/helpers/resource/RegistrationsResourceQueries.ts +22 -0
  22. package/src/access-interfaces/registered-names/helpers/resource/index.ts +3 -0
  23. package/src/access-interfaces/registered-names/index.ts +1 -0
  24. package/src/adapter/Base.ts +96 -0
  25. package/src/adapter/Network.ts +31 -0
  26. package/src/adapter/Settings.ts +30 -0
  27. package/src/adapter/index.ts +2 -0
  28. package/src/adapters/OsPubSubBridgeNetwork.ts +10 -0
  29. package/src/adapters/OsSettings.ts +7 -0
  30. package/src/adapters/OsXyoPublicNetwork.ts +9 -0
  31. package/src/adapters/index.ts +3 -0
  32. package/src/classes/cache/RunningAccessDappCache.ts +21 -0
  33. package/src/classes/cache/RunningDappCache.ts +50 -0
  34. package/src/classes/cache/index.ts +2 -0
  35. package/src/classes/dapp/DefaultsResource.ts +65 -0
  36. package/src/classes/dapp/access/Caller.ts +73 -0
  37. package/src/classes/dapp/access/Queries.ts +38 -0
  38. package/src/classes/dapp/access/Resource.ts +63 -0
  39. package/src/classes/dapp/access/index.ts +3 -0
  40. package/src/classes/dapp/index.ts +2 -0
  41. package/src/classes/index.ts +8 -0
  42. package/src/classes/lib/DappCreatorParams.ts +16 -0
  43. package/src/classes/lib/Insertable.ts +14 -0
  44. package/src/classes/lib/index.ts +2 -0
  45. package/src/classes/menu/Caller.ts +76 -0
  46. package/src/classes/menu/Queries.ts +59 -0
  47. package/src/classes/menu/Resource.ts +103 -0
  48. package/src/classes/menu/index.ts +2 -0
  49. package/src/classes/node/Creator.ts +96 -0
  50. package/src/classes/node/DefaultPayloads/DappAccessPayloads.ts +17 -0
  51. package/src/classes/node/DefaultPayloads/DefaultPayloads.ts +33 -0
  52. package/src/classes/node/DefaultPayloads/NodeInfoPayload.ts +27 -0
  53. package/src/classes/node/DefaultPayloads/SigningKeyPayloads.ts +85 -0
  54. package/src/classes/node/DefaultPayloads/index.ts +1 -0
  55. package/src/classes/node/ExternalModulePermissions/ExternalModulePermissions.ts +47 -0
  56. package/src/classes/node/ExternalModulePermissions/index.ts +1 -0
  57. package/src/classes/node/createDappContext.ts +52 -0
  58. package/src/classes/node/index.ts +3 -0
  59. package/src/classes/registration/DappRegistrationService.ts +146 -0
  60. package/src/classes/registration/DappRegistry.ts +121 -0
  61. package/src/classes/registration/ValidateDappAccessDiviner/Config.ts +19 -0
  62. package/src/classes/registration/ValidateDappAccessDiviner/Diviner.ts +132 -0
  63. package/src/classes/registration/ValidateDappAccessDiviner/index.ts +2 -0
  64. package/src/classes/registration/index.ts +2 -0
  65. package/src/classes/settings/Caller.ts +76 -0
  66. package/src/classes/settings/CallerBase.ts +24 -0
  67. package/src/classes/settings/Resource.ts +79 -0
  68. package/src/classes/settings/SettingsQueries.ts +38 -0
  69. package/src/classes/settings/badge/Caller.ts +30 -0
  70. package/src/classes/settings/badge/Queries.ts +18 -0
  71. package/src/classes/settings/badge/Resource.ts +54 -0
  72. package/src/classes/settings/badge/index.ts +2 -0
  73. package/src/classes/settings/index.ts +5 -0
  74. package/src/classes/system/ManageSystemDapps.ts +131 -0
  75. package/src/classes/system/Queries.ts +69 -0
  76. package/src/classes/system/index.ts +1 -0
  77. package/src/event/bus/Connection.ts +31 -0
  78. package/src/event/bus/EventBus.ts +145 -0
  79. package/src/event/bus/PubSubConnection.ts +28 -0
  80. package/src/event/bus/index.ts +3 -0
  81. package/src/event/connections/DappAccessRequest.ts +11 -0
  82. package/src/event/connections/DappsReady.ts +9 -0
  83. package/src/event/connections/ExposeDappRequest.ts +11 -0
  84. package/src/event/connections/OsPubSubNetworkReady.ts +12 -0
  85. package/src/event/connections/OsSettingsReady.ts +12 -0
  86. package/src/event/connections/OsXyoPublicReady.ts +12 -0
  87. package/src/event/connections/index.ts +6 -0
  88. package/src/event/index.ts +2 -0
  89. package/src/helpers/index.ts +1 -0
  90. package/src/helpers/monitor/XyOsMonitor.ts +52 -0
  91. package/src/helpers/monitor/index.ts +2 -0
  92. package/src/helpers/monitor/types.ts +5 -0
  93. package/src/index.ts +22 -0
  94. package/src/intent/Caller.ts +72 -0
  95. package/src/intent/Resource.ts +66 -0
  96. package/src/intent/index.ts +2 -0
  97. package/src/lib/ExternalStore.ts +7 -0
  98. package/src/lib/Listener.ts +1 -0
  99. package/src/lib/ModuleAccountPaths.ts +29 -0
  100. package/src/lib/ModuleNames.ts +3 -0
  101. package/src/lib/NameTransforms.ts +31 -0
  102. package/src/lib/PayloadStore.ts +98 -0
  103. package/src/lib/ResourceStores.ts +7 -0
  104. package/src/lib/index.ts +10 -0
  105. package/src/lib/initializeXns.ts +16 -0
  106. package/src/lib/isPayload.ts +24 -0
  107. package/src/lib/tokenPlacesSplit.ts +17 -0
  108. package/src/loadOsNode.ts +43 -0
  109. package/src/manifest/ManifestReplaceableTokens.ts +17 -0
  110. package/src/manifest/index.ts +2 -0
  111. package/src/manifest/os-node.manifest.json +132 -0
  112. package/src/manifests/dapp-window.manifest.json +36 -0
  113. package/src/manifests/index.ts +1 -0
  114. package/src/profileModuleEvents.ts +43 -0
  115. package/src/stack/Base.ts +153 -0
  116. package/src/stack/Manager.ts +48 -0
  117. package/src/stack/Map.ts +20 -0
  118. package/src/stack/OsPubSubNetworkStack.ts +70 -0
  119. package/src/stack/OsSettingsStack.ts +24 -0
  120. package/src/stack/XyoPublicNetworkStack.ts +32 -0
  121. package/src/stack/index.ts +6 -0
  122. package/src/types/global.d.ts +9 -0
  123. package/src/types/images.d.ts +5 -0
  124. package/src/utils/buildWalletSeedPhrasePayload.ts +41 -0
  125. package/src/utils/getApiDomain.ts +14 -0
  126. package/src/utils/index.ts +3 -0
  127. package/src/utils/renameObjKey.ts +22 -0
  128. package/src/wallet/DappSeedPhraseRepository.ts +95 -0
  129. package/src/wallet/SeedPhraseRepository.ts +32 -0
  130. package/src/wallet/index.ts +2 -0
  131. package/typedoc.json +5 -0
  132. package/xy.config.ts +10 -0
@@ -0,0 +1,50 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import type { DappId, RegisteredDapp, WindowDappNodeSet, XyOsContext } from '@xyo-network/os-model'
3
+ import { Mutex } from 'async-mutex'
4
+
5
+ import { XyOs } from '../../XyOs.ts'
6
+ import { createDappContext, DappContextCreator } from '../node/index.ts'
7
+
8
+ const findOrCreateMutex = new Mutex()
9
+
10
+ /**
11
+ * A cache for running node instances
12
+ */
13
+ export class RunningDappCache {
14
+ private static _cache: { [key: DappId]: WindowDappNodeSet } = {}
15
+
16
+ static async findOrCreate(dapp: RegisteredDapp, xyOs: XyOsContext, allowedNames: string[], xnsNodeUrl: string | undefined, xnsNetwork: string | undefined): Promise<WindowDappNodeSet> {
17
+ const dappId = dapp.config.name
18
+
19
+ return await XyOs.monitor<WindowDappNodeSet>(
20
+ async () =>
21
+ await findOrCreateMutex.runExclusive(async () => {
22
+ const existingWindowDappSet = RunningDappCache.get(dappId)
23
+ if (existingWindowDappSet) {
24
+ console.debug('[DEBUG]', `RunningDappCache, using existing node for ${dappId}`)
25
+ const existingDappContext = assertEx(existingWindowDappSet.context, () => 'No context found in existing dapp node')
26
+ await DappContextCreator.primeDappArchivist(existingDappContext, xyOs, dappId)
27
+ return existingWindowDappSet
28
+ }
29
+ console.debug('[DEBUG]', 'RunningDappCache:creating', dappId)
30
+ const windowDappSet = await createDappContext(dapp, xyOs, allowedNames, xnsNodeUrl, xnsNetwork)
31
+ RunningDappCache.set(dappId, windowDappSet)
32
+
33
+ return windowDappSet
34
+ }),
35
+ { additionalProperties: { dappId }, name: 'Loading dApp' },
36
+ )
37
+ }
38
+
39
+ static get(key: DappId): WindowDappNodeSet | undefined {
40
+ return this._cache[key]
41
+ }
42
+
43
+ static has(key?: DappId) {
44
+ return key ? !!this._cache[key] : false
45
+ }
46
+
47
+ static set(key: DappId, value: WindowDappNodeSet) {
48
+ this._cache[key] = value
49
+ }
50
+ }
@@ -0,0 +1,2 @@
1
+ export * from './RunningAccessDappCache.ts'
2
+ export * from './RunningDappCache.ts'
@@ -0,0 +1,65 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import type { DappInjectableParams, NodeOsInfo, XyOsContext } from '@xyo-network/os-model'
3
+ import { isDappInjectableParams, isNodeOsInfo } from '@xyo-network/os-model'
4
+
5
+ import { DappCallerBase } from '../../DappCallerBase.ts'
6
+ import { DappDefaultsResourceQueries } from '../../DefaultsQueries.ts'
7
+ import type { Listener, ResourceStore } from '../../lib/index.ts'
8
+ import { PayloadStore } from '../../lib/index.ts'
9
+
10
+ export type DappDefaultsResourceViews = 'nodeOsInfo' | 'dappInjectableParamsFromRoute'
11
+
12
+ /**
13
+ * A resource for interacting with Dapp Defaults
14
+ */
15
+ export class DappDefaultsResource extends DappCallerBase implements ResourceStore<DappDefaultsResourceViews> {
16
+ private _dappInjectableParamsFromRouteListener: PayloadStore<DappInjectableParams> | undefined
17
+ private _nodeOsInfoListener: PayloadStore<NodeOsInfo> | undefined
18
+
19
+ constructor(context: XyOsContext) {
20
+ super(context)
21
+ }
22
+
23
+ get dappInjectableParamsFromRouteListener() {
24
+ return assertEx(this._dappInjectableParamsFromRouteListener, () => 'DappInjectableParams not found')
25
+ }
26
+
27
+ get nodeOsInfoListener() {
28
+ return assertEx(this._nodeOsInfoListener, () => 'NodeOsInfo not found')
29
+ }
30
+
31
+ get subscriptions() {
32
+ return {
33
+ dappInjectableParamsFromRoute: (cb: Listener) => this.dappInjectableParamsFromRouteListener.subscribe(cb),
34
+ nodeOsInfo: (cb: Listener) => this.nodeOsInfoListener.subscribe(cb),
35
+ }
36
+ }
37
+
38
+ get views() {
39
+ return {
40
+ dappInjectableParamsFromRoute: () => this.dappInjectableParamsFromRouteListener.getSnapshot(),
41
+ nodeOsInfo: () => this.nodeOsInfoListener.getSnapshot(),
42
+ }
43
+ }
44
+
45
+ cleanupListeners() {
46
+ this.nodeOsInfoListener.cleanupListeners()
47
+ }
48
+
49
+ async start() {
50
+ const archivist = await this.getDappArchivist()
51
+ const diviner = await this.getDappArchivistPayloadDiviner()
52
+
53
+ this._nodeOsInfoListener = await PayloadStore.create<NodeOsInfo>({
54
+ archivist,
55
+ getLatest: async () => await DappDefaultsResourceQueries.getNodeOsInfo(diviner),
56
+ idFunction: isNodeOsInfo,
57
+ })
58
+
59
+ this._dappInjectableParamsFromRouteListener = await PayloadStore.create<DappInjectableParams>({
60
+ archivist,
61
+ getLatest: async () => await DappDefaultsResourceQueries.getDappInjectableParamsFromRoute(diviner),
62
+ idFunction: isDappInjectableParams,
63
+ })
64
+ }
65
+ }
@@ -0,0 +1,73 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
3
+ import { asNodeInstance } from '@xyo-network/node-model'
4
+ import type {
5
+ PostRegistrationHandler,
6
+ RegisteredDappAccess,
7
+ RegisteredDappSet,
8
+ RegisteredDappSetResult,
9
+ XyOsContext } from '@xyo-network/os-model'
10
+ import {
11
+ isRegisteredDappAccessDappSet,
12
+ } from '@xyo-network/os-model'
13
+ import { PayloadBuilder } from '@xyo-network/payload-builder'
14
+
15
+ import { OsCallerBase } from '../../../OsCallerBase.ts'
16
+ import { RunningDappAccessCache, RunningDappCache } from '../../cache/index.ts'
17
+
18
+ /**
19
+ * Caller for managing Dapp Access Nodes
20
+ * Start nodes that have been registered as accessible
21
+ * Grab their Access Node(s)
22
+ * Put RegisteredDappAccess payloads in RegisteredDappInterfacesArchivist
23
+ * Keep Service running that can service requests for Access Nodes
24
+ **/
25
+ export class DappAccessCaller extends OsCallerBase implements PostRegistrationHandler {
26
+ constructor(
27
+ context: XyOsContext,
28
+ private registeredDapps: RegisteredDappSetResult[],
29
+ private allowedNames: string[],
30
+ private xnsNodeUrl: string | undefined,
31
+ private xnsNetwork: string | undefined,
32
+ private platformLocator = new ModuleFactoryLocator(),
33
+ ) {
34
+ super(context)
35
+ }
36
+
37
+ async start() {
38
+ const registeredDappAccessDappSets = this.registeredDapps.filter(isRegisteredDappAccessDappSet)
39
+ for (const registeredDappSet of registeredDappAccessDappSets) {
40
+ const context = await this.buildRunningDappCache(registeredDappSet, this.allowedNames)
41
+
42
+ for (const dappAccessor of registeredDappSet.dapp.accessors) {
43
+ await this.cacheAccessNode(dappAccessor, context)
44
+ await this.saveRegisteredDappInterfaces(dappAccessor)
45
+ }
46
+ }
47
+ }
48
+
49
+ private async buildRunningDappCache(registeredDappSet: RegisteredDappSet, allowedNames: string[]) {
50
+ const { context } = await RunningDappCache.findOrCreate(registeredDappSet.dapp, this.context, allowedNames, this.xnsNodeUrl, this.xnsNetwork)
51
+ if (!context) throw new Error('Dapp context not found')
52
+ return context
53
+ }
54
+
55
+ private async cacheAccessNode(dappAccessor: RegisteredDappAccess, context: XyOsContext) {
56
+ const accessNodeId = dappAccessor.rootModuleId
57
+ const accessNodeModule = assertEx(await context.root.resolve(accessNodeId), () => 'Access Node Module not found')
58
+ const accessNode = asNodeInstance(accessNodeModule, () => 'Access Node Module is not a NodeInstance')
59
+
60
+ RunningDappAccessCache.set(dappAccessor.registeringDappId, accessNode)
61
+ }
62
+
63
+ private async saveRegisteredDappInterfaces(registeredDappAccess: RegisteredDappAccess) {
64
+ const archivist = await this.getRegisteredDappInterfacesArchivist()
65
+
66
+ const hash = await PayloadBuilder.dataHash(registeredDappAccess)
67
+ const [existing] = await archivist.get([hash])
68
+ if (existing) return
69
+
70
+ await archivist.insert([registeredDappAccess])
71
+ console.debug('[DEBUG] -', `Registered ${registeredDappAccess.registeringDappId} with ${registeredDappAccess.name} interface`)
72
+ }
73
+ }
@@ -0,0 +1,38 @@
1
+ import type { DivinerInstance } from '@xyo-network/diviner-model'
2
+ import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
3
+ import type { DappAccessRequest, RegisteredDappAccess } from '@xyo-network/os-model'
4
+ import { DappAccessRequestSchema, RegisteredDappAccessSchema } from '@xyo-network/os-model'
5
+ import type { WithMeta } from '@xyo-network/payload-model'
6
+
7
+ const noResults: unknown[] = []
8
+
9
+ export const DappAccessRequestQueries = {
10
+ async getAccessRequests(diviner: DivinerInstance) {
11
+ const query = {
12
+ limit: 1,
13
+ schema: PayloadDivinerQuerySchema,
14
+ schemas: [DappAccessRequestSchema],
15
+ }
16
+
17
+ const results = (await diviner.divine([query])) as WithMeta<DappAccessRequest>[]
18
+
19
+ if (results.length === 0) {
20
+ return noResults as WithMeta<DappAccessRequest>[]
21
+ }
22
+ return results
23
+ },
24
+ async getRegisteredInterfaces(diviner: DivinerInstance) {
25
+ const query = {
26
+ limit: 1,
27
+ schema: PayloadDivinerQuerySchema,
28
+ schemas: [RegisteredDappAccessSchema],
29
+ }
30
+
31
+ const results = (await diviner.divine([query])) as WithMeta<RegisteredDappAccess>[]
32
+
33
+ if (results.length === 0) {
34
+ return noResults as WithMeta<RegisteredDappAccess>[]
35
+ }
36
+ return results
37
+ },
38
+ }
@@ -0,0 +1,63 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import type { DappAccessRequest, RegisteredDappAccess, XyOsContext } from '@xyo-network/os-model'
3
+ import { isDappAccessRequestWithMeta, isRegisteredDappAccess } from '@xyo-network/os-model'
4
+
5
+ import { DappCallerBase } from '../../../DappCallerBase.ts'
6
+ import type { Listener, ResourceStore } from '../../../lib/index.ts'
7
+ import { PayloadStore } from '../../../lib/index.ts'
8
+ import { DappAccessRequestQueries } from './Queries.ts'
9
+
10
+ export type DappAccessRequestViews = 'accessRequests' | 'registeredInterfaces'
11
+
12
+ export class DappAccessRequestResource extends DappCallerBase implements ResourceStore<DappAccessRequestViews> {
13
+ private _accessRequestListener: PayloadStore<DappAccessRequest> | undefined
14
+ private _registeredInterfacesListener: PayloadStore<RegisteredDappAccess> | undefined
15
+
16
+ constructor(context: XyOsContext) {
17
+ super(context)
18
+ }
19
+
20
+ get accessRequestListener() {
21
+ return assertEx(this._accessRequestListener, () => 'accessRequests note found')
22
+ }
23
+
24
+ get registeredInterfacesListener() {
25
+ return assertEx(this._registeredInterfacesListener, () => 'registeredInterfaces note found')
26
+ }
27
+
28
+ get subscriptions() {
29
+ return {
30
+ accessRequests: (cb: Listener) => this.accessRequestListener.subscribe(cb),
31
+ registeredInterfaces: (cb: Listener) => this.registeredInterfacesListener.subscribe(cb),
32
+ }
33
+ }
34
+
35
+ get views() {
36
+ return {
37
+ accessRequests: () => this.accessRequestListener.getSnapshot(),
38
+ registeredInterfaces: () => this.registeredInterfacesListener.getSnapshot(),
39
+ }
40
+ }
41
+
42
+ cleanupListeners(): void {
43
+ this.accessRequestListener.cleanupListeners()
44
+ }
45
+
46
+ // Start the resource
47
+ async start() {
48
+ const archivist = await this.getDappArchivist()
49
+ const diviner = await this.getDappArchivistPayloadDiviner()
50
+
51
+ this._accessRequestListener = await PayloadStore.create<DappAccessRequest>({
52
+ archivist,
53
+ getLatest: async () => await DappAccessRequestQueries.getAccessRequests(diviner),
54
+ idFunction: isDappAccessRequestWithMeta,
55
+ })
56
+
57
+ this._registeredInterfacesListener = await PayloadStore.create<RegisteredDappAccess>({
58
+ archivist,
59
+ getLatest: async () => await DappAccessRequestQueries.getRegisteredInterfaces(diviner),
60
+ idFunction: isRegisteredDappAccess,
61
+ })
62
+ }
63
+ }
@@ -0,0 +1,3 @@
1
+ export * from './Caller.ts'
2
+ export * from './Queries.ts'
3
+ export * from './Resource.ts'
@@ -0,0 +1,2 @@
1
+ export * from './access/index.ts'
2
+ export * from './DefaultsResource.ts'
@@ -0,0 +1,8 @@
1
+ export * from './cache/index.ts'
2
+ export * from './dapp/index.ts'
3
+ export * from './lib/index.ts'
4
+ export * from './menu/index.ts'
5
+ export * from './node/index.ts'
6
+ export * from './registration/index.ts'
7
+ export * from './settings/index.ts'
8
+ export * from './system/index.ts'
@@ -0,0 +1,16 @@
1
+ import type { ModuleManifest } from '@xyo-network/manifest'
2
+ import type { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
3
+ import type { DappName, DappPackageManifestPayload, XyOsContext } from '@xyo-network/os-model'
4
+ import type { WalletInstance } from '@xyo-network/wallet-model'
5
+
6
+ export type DappNodesCreatorParams = {
7
+ config: {
8
+ dappName: DappName
9
+ payload: DappPackageManifestPayload
10
+ privateChildren?: ModuleManifest[]
11
+ publicChildren?: ModuleManifest[]
12
+ }
13
+ context: XyOsContext
14
+ locator?: ModuleFactoryLocator
15
+ wallet: WalletInstance
16
+ }
@@ -0,0 +1,14 @@
1
+ import type { DappName, XyOsContext } from '@xyo-network/os-model'
2
+ import type { Payload } from '@xyo-network/payload-model'
3
+
4
+ export interface InsertableConstructor {
5
+ new (_xyOs: XyOsContext, dappName: DappName): DefaultPayloadsInsertable
6
+ }
7
+
8
+ type InsertableConstructorParams = ConstructorParameters<InsertableConstructor>
9
+
10
+ export interface DefaultPayloadsInsertable {
11
+ payloads(): Promise<Payload[]>
12
+ }
13
+
14
+ export const createInsertable = (insertable: InsertableConstructor, ...params: InsertableConstructorParams) => new insertable(...params)
@@ -0,0 +1,2 @@
1
+ export * from './DappCreatorParams.ts'
2
+ export * from './Insertable.ts'
@@ -0,0 +1,76 @@
1
+ import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
2
+ import type {
3
+ DappInjectableParams,
4
+ DappNavItemSelection,
5
+ XyOsContext } from '@xyo-network/os-model'
6
+ import {
7
+ DappInjectableParamsSchema,
8
+ DappNavItemSelectionSchema,
9
+ } from '@xyo-network/os-model'
10
+ import { PayloadBuilder } from '@xyo-network/payload-builder'
11
+ import type { Payload, WithMeta } from '@xyo-network/payload-model'
12
+
13
+ import { DappCaller } from '../../Caller.ts'
14
+
15
+ export class DappMenuCaller extends DappCaller {
16
+ constructor(context: XyOsContext) {
17
+ super(context)
18
+ }
19
+
20
+ /**
21
+ * Add new Payloads to the dappArchivist if they haven't already
22
+ *
23
+ * @param {Payload[]} payloads
24
+ */
25
+ async add(payloads: Payload[], force = false) {
26
+ const dappArchivist = await this.getDappArchivist()
27
+
28
+ for (const payload of payloads) {
29
+ const hash = await PayloadBuilder.dataHash(payload)
30
+ const [existing] = await dappArchivist.get([hash])
31
+ if (!existing || force) {
32
+ await dappArchivist.insert(payloads)
33
+ }
34
+ }
35
+ }
36
+
37
+ async currentNavSelection(): Promise<DappNavItemSelection[] | undefined> {
38
+ const diviner = await this.getDappArchivistPayloadDiviner()
39
+ const query = {
40
+ limit: 1,
41
+ order: 'desc',
42
+ schema: PayloadDivinerQuerySchema,
43
+ schemas: [DappNavItemSelectionSchema],
44
+ }
45
+
46
+ return (await diviner.divine([query])) as WithMeta<DappNavItemSelection>[]
47
+ }
48
+
49
+ /*
50
+ * Indicate to the system that a nav item was selected
51
+ *
52
+ * @param {string} path
53
+ * @params {string} injectableParamsPath
54
+ * @returns Promise
55
+ */
56
+ async makeNavItemSelection(path: string, injectableParamsPath?: string): Promise<void> {
57
+ const dappArchivist = await this.getDappArchivist()
58
+ const payload: DappNavItemSelection = {
59
+ path,
60
+ schema: DappNavItemSelectionSchema,
61
+ timestamp: Date.now(),
62
+ }
63
+ await dappArchivist.insert([payload])
64
+
65
+ if (injectableParamsPath) {
66
+ const injectableParams: DappInjectableParams = {
67
+ params: {},
68
+ path: injectableParamsPath,
69
+ schema: DappInjectableParamsSchema,
70
+ source: 'route',
71
+ timestamp: Date.now(),
72
+ }
73
+ await dappArchivist.insert([injectableParams])
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,59 @@
1
+ import type { DivinerInstance } from '@xyo-network/diviner-model'
2
+ import type { PayloadDivinerQueryPayload } from '@xyo-network/diviner-payload-model'
3
+ import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
4
+ import type {
5
+ DappNavItem,
6
+ DappNavItemSelection,
7
+ DappNavMenuConfig } from '@xyo-network/os-model'
8
+ import {
9
+ DappNavItemSchema,
10
+ DappNavItemSelectionSchema,
11
+ DappNavMenuConfigSchema,
12
+ } from '@xyo-network/os-model'
13
+ import type { WithMeta, WithSources } from '@xyo-network/payload-model'
14
+
15
+ const NO_ITEMS: unknown[] = []
16
+
17
+ export const DappMenuQueries = {
18
+ async getMenuConfigs(diviner: DivinerInstance): Promise<WithSources<WithMeta<DappNavMenuConfig>>[]> {
19
+ const query: PayloadDivinerQueryPayload = {
20
+ limit: 1,
21
+ order: 'desc',
22
+ schema: PayloadDivinerQuerySchema,
23
+ schemas: [DappNavMenuConfigSchema],
24
+ }
25
+ return (await diviner.divine([query])) as WithMeta<WithSources<DappNavMenuConfig>>[]
26
+ },
27
+
28
+ async getMenuItems(diviner: DivinerInstance) {
29
+ const query: PayloadDivinerQueryPayload = {
30
+ order: 'desc',
31
+ schema: PayloadDivinerQuerySchema,
32
+ schemas: [DappNavItemSchema],
33
+ }
34
+
35
+ const results = (await diviner.divine([query])) as WithMeta<WithSources<DappNavItem>>[]
36
+ return results.length > 0 ? results : (NO_ITEMS as WithMeta<WithSources<DappNavItem>>[])
37
+ },
38
+
39
+ async getNavItemSelections(diviner: DivinerInstance) {
40
+ const query: PayloadDivinerQueryPayload = {
41
+ limit: 1,
42
+ order: 'desc',
43
+ schema: PayloadDivinerQuerySchema,
44
+ schemas: [DappNavItemSelectionSchema],
45
+ }
46
+ const results = (await diviner.divine([query])) as WithMeta<WithSources<DappNavItemSelection>>[]
47
+ return results.length > 0 ? results : (NO_ITEMS as WithMeta<WithSources<DappNavItemSelection>>[])
48
+ },
49
+
50
+ async getVisibleMenuItems(diviner: DivinerInstance) {
51
+ const query: PayloadDivinerQueryPayload = {
52
+ order: 'desc',
53
+ schema: PayloadDivinerQuerySchema,
54
+ schemas: [DappNavItemSchema],
55
+ }
56
+ const results = (await diviner.divine([query])) as WithMeta<WithSources<DappNavItem>>[]
57
+ return results.filter(menuItem => menuItem.hidden !== true).sort((a, b) => ((a.weight ?? 0) > (b.weight ?? 0) ? 1 : -1))
58
+ },
59
+ }
@@ -0,0 +1,103 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import type { DappNavItem, DappNavItemSelection, DappNavMenuConfig, XyOsContext } from '@xyo-network/os-model'
3
+ import { isDappNavItemSelection, isDappNavMenuConfig } from '@xyo-network/os-model'
4
+ import type { Payload, WithMeta, WithSources } from '@xyo-network/payload-model'
5
+
6
+ import { DappCaller } from '../../Caller.ts'
7
+ import type { Listener, ResourceStore } from '../../lib/index.ts'
8
+ import { PayloadStore } from '../../lib/index.ts'
9
+ import { DappMenuQueries } from './Queries.ts'
10
+
11
+ export type DappMenuResourceViews = 'menuConfigs' | 'menuItems' | 'menuItemsVisible' | 'menuItemSelections'
12
+
13
+ export type NavPayloadType<T extends Payload = Payload> = WithMeta<WithSources<T>>[]
14
+
15
+ /**
16
+ * A Repository for interacting with dapp menu items and config
17
+ */
18
+ export class DappMenuResource extends DappCaller implements ResourceStore<DappMenuResourceViews> {
19
+ private _menuConfigListener: PayloadStore<DappNavMenuConfig> | undefined
20
+ private _menuItemListener: PayloadStore<DappNavItem> | undefined
21
+ private _menuItemSelectionListener: PayloadStore<DappNavItemSelection> | undefined
22
+ private _menuItemVisibleListener: PayloadStore<DappNavItem> | undefined
23
+
24
+ constructor(xyOsContext: XyOsContext) {
25
+ super(xyOsContext)
26
+ }
27
+
28
+ get menuConfigListener() {
29
+ return assertEx(this._menuConfigListener, () => 'menuConfigListener note found')
30
+ }
31
+
32
+ get menuItemListener() {
33
+ return assertEx(this._menuItemListener, () => 'menuItemListener note found')
34
+ }
35
+
36
+ get menuItemSelectionListener() {
37
+ return assertEx(this._menuItemSelectionListener, () => 'menuItemSelectionListener note found')
38
+ }
39
+
40
+ get menuItemVisibleListener() {
41
+ return assertEx(this._menuItemVisibleListener, () => 'menuItemVisibleListener note found')
42
+ }
43
+
44
+ /** subscribe to latest set of payloads */
45
+ get subscriptions() {
46
+ return {
47
+ menuConfigs: (cb: Listener) => this.menuConfigListener.subscribe(cb),
48
+ menuItemSelections: (cb: Listener) => this.menuItemSelectionListener.subscribe(cb),
49
+ menuItems: (cb: Listener) => this.menuItemListener.subscribe(cb),
50
+ menuItemsVisible: (cb: Listener) => this.menuItemVisibleListener.subscribe(cb),
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Return the latest menu payloads from the repository
56
+ */
57
+ get views() {
58
+ return {
59
+ menuConfigs: () => this.menuConfigListener.getSnapshot(),
60
+ menuItemSelections: () => this.menuItemSelectionListener.getSnapshot(),
61
+ menuItems: () => this.menuItemListener.getSnapshot(),
62
+ menuItemsVisible: () => this.menuItemVisibleListener.getSnapshot(),
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Remove all listeners and reset their class members
68
+ */
69
+ cleanupListeners() {
70
+ this.menuConfigListener.cleanupListeners()
71
+ this.menuItemListener.cleanupListeners()
72
+ this.menuItemSelectionListener.cleanupListeners()
73
+ }
74
+
75
+ /**
76
+ * Start the resource
77
+ */
78
+ async start(): Promise<void> {
79
+ const dappArchivist = await this.getDappArchivist()
80
+ const dappArchivistPayloadDiviner = await this.getDappArchivistPayloadDiviner()
81
+
82
+ this._menuConfigListener = await PayloadStore.create<DappNavMenuConfig>({
83
+ archivist: dappArchivist,
84
+ getLatest: async () => await DappMenuQueries.getMenuConfigs(dappArchivistPayloadDiviner),
85
+ idFunction: isDappNavMenuConfig,
86
+ })
87
+ this._menuItemListener = await PayloadStore.create<DappNavItem>({
88
+ archivist: dappArchivist,
89
+ getLatest: async () => await DappMenuQueries.getMenuItems(dappArchivistPayloadDiviner),
90
+ idFunction: isDappNavMenuConfig,
91
+ })
92
+ this._menuItemVisibleListener = await PayloadStore.create<DappNavItem>({
93
+ archivist: dappArchivist,
94
+ getLatest: async () => await DappMenuQueries.getVisibleMenuItems(dappArchivistPayloadDiviner),
95
+ idFunction: isDappNavMenuConfig,
96
+ })
97
+ this._menuItemSelectionListener = await PayloadStore.create<DappNavItemSelection>({
98
+ archivist: dappArchivist,
99
+ getLatest: async () => await DappMenuQueries.getNavItemSelections(dappArchivistPayloadDiviner),
100
+ idFunction: isDappNavItemSelection,
101
+ })
102
+ }
103
+ }
@@ -0,0 +1,2 @@
1
+ export * from './Caller.ts'
2
+ export * from './Resource.ts'