@underpostnet/cyberia 3.3.73 → 3.3.76

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 (228) hide show
  1. package/.env.example +17 -5
  2. package/.github/workflows/coverall.cyberia.ci.yml +5 -0
  3. package/.github/workflows/docker-image.cyberia-client.ci.yml +1 -1
  4. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +1 -1
  5. package/.github/workflows/docker-image.cyberia-server.ci.yml +1 -1
  6. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +1 -1
  7. package/.github/workflows/docker-image.engine-cyberia.ci.yml +1 -1
  8. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +1 -1
  9. package/.github/workflows/publish.cyberia.ci.yml +44 -0
  10. package/AGENTS.md +61 -12
  11. package/CHANGELOG.md +126 -41
  12. package/CLI-HELP.md +19 -12
  13. package/Dockerfile +1 -1
  14. package/Dockerfile.dev +1 -1
  15. package/Dockerfile.test +2 -2
  16. package/README.md +28 -28
  17. package/bin/build.js +37 -17
  18. package/bin/cyberia.js +1247 -1373
  19. package/bin/index.js +1247 -1373
  20. package/compose.env +17 -5
  21. package/conf.js +7 -3
  22. package/deploy/cyberia-client/deploy.sh +10 -11
  23. package/deploy/cyberia-client/package.sh +0 -1
  24. package/deploy/cyberia-client/state.sh +3 -2
  25. package/deploy/cyberia-server/deploy.sh +10 -11
  26. package/deploy/cyberia-server/package.sh +0 -1
  27. package/deploy/cyberia-server/state.sh +3 -2
  28. package/deploy/dd-cyberia/deploy.sh +5 -5
  29. package/deploy/dd-cyberia/init.sh +15 -14
  30. package/deploy/dd-cyberia/package.sh +0 -1
  31. package/deploy/dd-cyberia/state.sh +2 -2
  32. package/deploy/dd-cyberia/sync-deploy.sh +139 -75
  33. package/deploy/lib/config.sh +29 -0
  34. package/deploy/lib/github-actions-logging.sh +92 -76
  35. package/deploy/lib/host.sh +27 -18
  36. package/deploy/lib/state.sh +4 -1
  37. package/deploy/pwa-microservices-template/deploy.sh +10 -8
  38. package/deploy/release/deploy.sh +0 -2
  39. package/deployment.yaml +1 -1
  40. package/docker-compose.yml +23 -17
  41. package/hardhat/package-lock.json +2 -2
  42. package/hardhat/package.json +1 -1
  43. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  44. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +1 -1
  45. package/manifests/deployment/dd-cyberia-development/deployment.yaml +1 -1
  46. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  47. package/manifests/deployment/mongo-express/deployment.yaml +46 -27
  48. package/manifests/deployment/mongo-express/kustomization.yaml +9 -0
  49. package/manifests/deployment/mongo-express/mongo-express-nodeport.yaml +18 -0
  50. package/manifests/deployment/mongo-express/service.yaml +16 -0
  51. package/manifests/deployment/mongo-express-no-auth/disable-mongodb-auth.yaml +16 -0
  52. package/manifests/deployment/mongo-express-no-auth/kustomization.yaml +16 -0
  53. package/package.json +19 -17
  54. package/scripts/test-monitor.sh +3 -3
  55. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +14 -9
  56. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +36 -5
  57. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +5 -0
  58. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +88 -184
  59. package/src/api/cyberia-action/cyberia-action.router.js +2 -2
  60. package/src/api/cyberia-action/cyberia-action.service.js +3 -4
  61. package/src/api/cyberia-audio/cyberia-audio.controller.js +6 -0
  62. package/src/api/cyberia-audio/cyberia-audio.model.js +61 -0
  63. package/src/api/cyberia-audio/cyberia-audio.router.js +21 -0
  64. package/src/api/cyberia-audio/cyberia-audio.service.js +220 -0
  65. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +1 -3
  66. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +10 -19
  67. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +12 -34
  68. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +15 -32
  69. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +1 -1
  70. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +1 -1
  71. package/src/api/cyberia-entity/cyberia-entity.model.js +2 -0
  72. package/src/api/cyberia-entity/cyberia-entity.service.js +1 -1
  73. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +8 -2
  74. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +31 -20
  75. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +16 -1
  76. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +466 -3
  77. package/src/api/cyberia-instance/cyberia-fallback-capture.js +87 -51
  78. package/src/api/cyberia-instance/cyberia-fallback-world.js +21 -40
  79. package/src/api/cyberia-instance/cyberia-instance-boot.service.js +5 -5
  80. package/src/api/cyberia-instance/cyberia-instance-items.js +98 -0
  81. package/src/api/cyberia-instance/cyberia-instance-map.service.js +34 -141
  82. package/src/api/cyberia-instance/cyberia-instance.controller.js +1 -4
  83. package/src/api/cyberia-instance/cyberia-instance.model.js +0 -14
  84. package/src/api/cyberia-instance/cyberia-instance.router.js +3 -16
  85. package/src/api/cyberia-instance/cyberia-instance.service.js +3 -43
  86. package/src/api/cyberia-instance/cyberia-world-generator.js +8 -13
  87. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +49 -75
  88. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +74 -1
  89. package/src/api/cyberia-map/cyberia-map.service.js +6 -2
  90. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.controller.js +31 -0
  91. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.model.js +56 -0
  92. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.router.js +33 -0
  93. package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +189 -0
  94. package/src/api/cyberia-quest/cyberia-quest.router.js +3 -3
  95. package/src/api/cyberia-quest/cyberia-quest.service.js +3 -3
  96. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +1 -1
  97. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +403 -188
  98. package/src/api/cyberia-skill/cyberia-skill.model.js +6 -6
  99. package/src/api/file/file.ref.js +153 -0
  100. package/src/api/file/file.ref.json +11 -2
  101. package/src/api/object-layer/object-layer.model.js +47 -12
  102. package/src/api/object-layer/object-layer.router.js +10 -3
  103. package/src/api/object-layer/object-layer.service.js +113 -120
  104. package/src/cli/app.js +12 -1
  105. package/src/cli/client.js +2 -2
  106. package/src/cli/cluster.js +7 -0
  107. package/src/cli/deploy.js +4 -4
  108. package/src/cli/docker-compose.js +1 -1
  109. package/src/cli/fs-selection.js +115 -0
  110. package/src/cli/fs.js +158 -342
  111. package/src/cli/index.js +22 -10
  112. package/src/cli/repository.js +28 -0
  113. package/src/cli/run.js +71 -197
  114. package/src/cli/test.js +4 -0
  115. package/src/cli/wireguard.js +32 -31
  116. package/src/client/components/core/Docs.js +77 -100
  117. package/src/client/components/core/Modal.js +56 -1
  118. package/src/client/components/cyberia/ActionEngineCyberia.js +12 -36
  119. package/src/client/components/cyberia/EntityEngineCyberia.js +492 -121
  120. package/src/client/components/cyberia/InstanceEngineCyberia.js +129 -160
  121. package/src/client/components/cyberia/InstanceSelectionView.js +7 -1
  122. package/src/client/components/cyberia/MapEngineCyberia.js +175 -69
  123. package/src/client/components/cyberia/ObjectLayerEngine.js +1011 -97
  124. package/src/client/components/cyberia/ObjectLayerEngineModal.js +81 -155
  125. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +113 -98
  126. package/src/client/components/cyberia/SharedDefaultsCyberia.js +215 -56
  127. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +0 -34
  128. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +1 -1
  129. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +712 -76
  130. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +0 -4
  131. package/src/client/public/cyberia-docs/ARCHITECTURE.md +15 -15
  132. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +280 -24
  133. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +51 -29
  134. package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +52 -53
  135. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +16 -11
  136. package/src/client/public/cyberia-docs/CYBERIA.md +28 -28
  137. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +11 -5
  138. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  139. package/src/client/public/cyberia-docs/STATS-PROGRESSION.md +217 -0
  140. package/src/client/public/cyberia-docs/WHITE-PAPER.md +20 -12
  141. package/src/client/services/cyberia-audio/cyberia-audio.service.js +99 -0
  142. package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +38 -0
  143. package/src/client/services/cyberia-instance/cyberia-instance.management.js +5 -4
  144. package/src/client/services/cyberia-instance/cyberia-instance.service.js +0 -40
  145. package/src/client/services/cyberia-map/cyberia-map.management.js +5 -4
  146. package/src/client/services/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +138 -0
  147. package/src/client/services/object-layer/object-layer.management.js +6 -10
  148. package/src/client/services/object-layer/object-layer.service.js +3 -1
  149. package/src/client-builder/client-build-docs.js +52 -52
  150. package/src/client-builder/client-build.js +67 -44
  151. package/src/client-builder/client-bundle.js +347 -0
  152. package/src/db/mongo/MongoExpress.js +187 -0
  153. package/src/grpc/cyberia/grpc-server.js +5 -7
  154. package/src/index.js +1 -1
  155. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +143 -146
  156. package/src/projects/cyberia/atlas-sprite-sheet-store.js +391 -0
  157. package/src/projects/cyberia/besu-genesis-generator.js +5 -14
  158. package/src/projects/cyberia/boot-contract-fixtures.js +32 -0
  159. package/src/projects/cyberia/catalog-cyberia.js +3 -2
  160. package/src/projects/cyberia/gemini-client.js +3 -3
  161. package/src/projects/cyberia/generate-saga.js +4 -11
  162. package/src/projects/cyberia/hot-reload-trigger.js +17 -28
  163. package/src/projects/cyberia/instance-backup.js +210 -0
  164. package/src/projects/cyberia/instance-data.js +177 -257
  165. package/src/projects/cyberia/map-preview-generator.js +32 -68
  166. package/src/projects/cyberia/object-layer.js +152 -319
  167. package/src/projects/cyberia/seed-audio.js +139 -0
  168. package/src/projects/cyberia/semantic-layer-generator-skin.js +2 -8
  169. package/src/projects/cyberia/semantic-layer-generator.js +2 -18
  170. package/src/projects/cyberia/stat-balance.js +81 -0
  171. package/src/projects/cyberia/stat-commands.js +23 -0
  172. package/src/projects/cyberia/stat-contract-generator.js +101 -0
  173. package/src/runtime/cyberia-client/Dockerfile +8 -4
  174. package/src/runtime/cyberia-client/Dockerfile.dev +5 -2
  175. package/src/runtime/cyberia-server/Dockerfile +9 -2
  176. package/src/runtime/cyberia-server/Dockerfile.dev +8 -1
  177. package/src/runtime/engine-cyberia/Dockerfile +1 -1
  178. package/src/runtime/engine-cyberia/Dockerfile.dev +1 -1
  179. package/src/runtime/engine-cyberia/Dockerfile.test +2 -2
  180. package/src/runtime/engine-cyberia/compose.env +17 -5
  181. package/src/runtime/engine-cyberia/docker-compose.yml +23 -17
  182. package/src/server/build/coverage.js +113 -42
  183. package/src/server/build/package.js +55 -12
  184. package/src/server/build/testing.js +59 -9
  185. package/src/server/network/middlewares.js +8 -2
  186. package/src/server/ops/logger.js +70 -35
  187. package/src/server/runtime/conf.js +4 -2
  188. package/src/server/storage/data-query.js +16 -0
  189. package/src/server/storage/downloader.js +62 -14
  190. package/src/server/storage/zip.js +153 -0
  191. package/test/integration/app/cyberia/atlas-sprite-sheet-store.test.js +402 -0
  192. package/test/integration/app/cyberia/atlas-sprite-sheet.test.js +86 -0
  193. package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +34 -0
  194. package/test/integration/app/cyberia/cyberia-entity-type-default.test.js +842 -0
  195. package/test/integration/app/cyberia/cyberia-instance-conf-coerce.test.js +53 -0
  196. package/test/integration/app/cyberia/cyberia-instance-conf-defaults.test.js +16 -22
  197. package/test/integration/app/cyberia/cyberia-instance-items.test.js +90 -0
  198. package/test/integration/app/cyberia/cyberia-load.test.js +6 -7
  199. package/test/integration/app/cyberia/cyberia-map-audio-conf.test.js +256 -0
  200. package/test/integration/app/cyberia/cyberia-stats.test.js +150 -0
  201. package/test/integration/app/cyberia/fallback-world-capture.test.js +87 -2
  202. package/test/integration/app/cyberia/object-layer-item-selection.test.js +56 -0
  203. package/test/integration/app/cyberia/object-layer-natural-key.test.js +32 -0
  204. package/test/integration/app/cyberia/seed-audio.test.js +275 -0
  205. package/test/integration/infra/2-network/wireguard-cli.test.js +33 -9
  206. package/test/integration/infra/2-network/wireguard-edge.test.js +58 -18
  207. package/test/integration/infra/3-cluster/mongo-express-deploy.test.js +156 -0
  208. package/test/integration/infra/4-ingress/api-cross-origin.test.js +79 -0
  209. package/test/unit/client-build-docs.test.js +97 -70
  210. package/test/unit/client-bundle.test.js +313 -0
  211. package/test/unit/conf-resolution.test.js +17 -0
  212. package/test/unit/coverage-artifact.test.js +120 -29
  213. package/test/unit/cyberia/instance-backup.test.js +183 -0
  214. package/test/unit/cyberia/instance-object-layer-items.test.js +46 -0
  215. package/test/unit/cyberia/publish-workflow.test.js +22 -0
  216. package/test/unit/cyberia/stat-balance.test.js +69 -0
  217. package/test/unit/deploy-log-table.test.js +76 -5
  218. package/test/unit/downloader-integrity.test.js +98 -0
  219. package/test/unit/file-reference-registry.test.js +141 -0
  220. package/test/unit/fs-storage-paths.test.js +596 -0
  221. package/test/unit/logger-redaction.test.js +29 -0
  222. package/test/unit/package.test.js +70 -16
  223. package/test/unit/prepare-host.test.js +84 -1
  224. package/test/unit/test-tiers.test.js +27 -0
  225. package/test/unit/zip-archive.test.js +142 -0
  226. package/vitest.config.js +11 -3
  227. package/src/api/cyberia-instance/cyberia-fallback-default-items.js +0 -63
  228. package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +0 -368
@@ -0,0 +1,99 @@
1
+ import { Auth } from '../../components/core/Auth.js';
2
+ import { loggerFactory } from '../../components/core/Logger.js';
3
+ import { getApiBaseUrl, headersFactory, payloadFactory, buildQueryUrl } from '../core/core.service.js';
4
+ const logger = loggerFactory(import.meta);
5
+ logger.info('Load service');
6
+ const endpoint = 'cyberia-audio';
7
+ class CyberiaAudioService {
8
+ static post = (options = { id: '', body: {} }) =>
9
+ new Promise((resolve, reject) =>
10
+ fetch(getApiBaseUrl({ id: options.id, endpoint }), {
11
+ method: 'POST',
12
+ headers: headersFactory(),
13
+ credentials: 'include',
14
+ body: payloadFactory(options.body),
15
+ })
16
+ .then(async (res) => {
17
+ return await res.json();
18
+ })
19
+ .then((res) => {
20
+ logger.info(res);
21
+ return resolve(res);
22
+ })
23
+ .catch((error) => {
24
+ logger.error(error);
25
+ return reject(error);
26
+ }),
27
+ );
28
+ static put = (options = { id: '', body: {} }) =>
29
+ new Promise((resolve, reject) =>
30
+ fetch(getApiBaseUrl({ id: options.id, endpoint }), {
31
+ method: 'PUT',
32
+ headers: headersFactory(),
33
+ credentials: 'include',
34
+ body: payloadFactory(options.body),
35
+ })
36
+ .then(async (res) => {
37
+ return await res.json();
38
+ })
39
+ .then((res) => {
40
+ logger.info(res);
41
+ return resolve(res);
42
+ })
43
+ .catch((error) => {
44
+ logger.error(error);
45
+ return reject(error);
46
+ }),
47
+ );
48
+ static get = (options = {}) => {
49
+ const { id, page, limit, filterModel, sortModel, sort, asc, order } = options;
50
+ const url = buildQueryUrl(getApiBaseUrl({ id, endpoint }), {
51
+ page,
52
+ limit,
53
+ filterModel,
54
+ sortModel,
55
+ sort,
56
+ asc,
57
+ order,
58
+ });
59
+ return new Promise((resolve, reject) =>
60
+ fetch(url.toString(), {
61
+ method: 'GET',
62
+ headers: headersFactory(),
63
+ credentials: 'include',
64
+ })
65
+ .then(async (res) => {
66
+ return await res.json();
67
+ })
68
+ .then((res) => {
69
+ logger.info(res);
70
+ return resolve(res);
71
+ })
72
+ .catch((error) => {
73
+ logger.error(error);
74
+ return reject(error);
75
+ }),
76
+ );
77
+ };
78
+ static delete = (options = { id: '', body: {} }) =>
79
+ new Promise((resolve, reject) =>
80
+ fetch(getApiBaseUrl({ id: options.id, endpoint }), {
81
+ method: 'DELETE',
82
+ headers: headersFactory(),
83
+ credentials: 'include',
84
+ body: payloadFactory(options.body),
85
+ })
86
+ .then(async (res) => {
87
+ return await res.json();
88
+ })
89
+ .then((res) => {
90
+ logger.info(res);
91
+ return resolve(res);
92
+ })
93
+ .catch((error) => {
94
+ logger.error(error);
95
+ return reject(error);
96
+ }),
97
+ );
98
+ }
99
+ export { CyberiaAudioService };
@@ -95,5 +95,43 @@ class CyberiaEntityTypeDefaultService {
95
95
  return reject(error);
96
96
  }),
97
97
  );
98
+ /** Points one instance's conf at every default the given maps place. */
99
+ static syncInstance = (options = { instanceCode: '', body: {} }) =>
100
+ new Promise((resolve, reject) =>
101
+ fetch(getApiBaseUrl({ id: `sync-instance/${options.instanceCode}`, endpoint }), {
102
+ method: 'POST',
103
+ headers: headersFactory(),
104
+ credentials: 'include',
105
+ body: payloadFactory(options.body),
106
+ })
107
+ .then(async (res) => await res.json())
108
+ .then((res) => {
109
+ logger.info(res);
110
+ return resolve(res);
111
+ })
112
+ .catch((error) => {
113
+ logger.error(error);
114
+ return reject(error);
115
+ }),
116
+ );
117
+ /** States the complete set of instances that reference this default. */
118
+ static setInstances = (options = { id: '', body: {} }) =>
119
+ new Promise((resolve, reject) =>
120
+ fetch(getApiBaseUrl({ id: `${options.id}/instances`, endpoint }), {
121
+ method: 'POST',
122
+ headers: headersFactory(),
123
+ credentials: 'include',
124
+ body: payloadFactory(options.body),
125
+ })
126
+ .then(async (res) => await res.json())
127
+ .then((res) => {
128
+ logger.info(res);
129
+ return resolve(res);
130
+ })
131
+ .catch((error) => {
132
+ logger.error(error);
133
+ return reject(error);
134
+ }),
135
+ );
98
136
  }
99
137
  export { CyberiaEntityTypeDefaultService };
@@ -29,7 +29,7 @@ class CyberiaInstanceManagement {
29
29
  <i class="fa-solid fa-upload"></i>
30
30
  </div>`,
31
31
  class: `in fll section-mp management-table-btn-mini management-table-btn-load-instance-${idModal}-${cellRenderId} ${
32
- !params.data._id ? 'hide' : ''
32
+ !params.data.code ? 'hide' : ''
33
33
  }`,
34
34
  })}`;
35
35
 
@@ -37,12 +37,13 @@ class CyberiaInstanceManagement {
37
37
  EventsUI.onClick(
38
38
  `.management-table-btn-load-instance-${idModal}-${cellRenderId}`,
39
39
  async () => {
40
- if (!params.data._id) return;
41
- const result = await CyberiaInstanceService.get({ id: params.data._id });
40
+ // Instances are addressed by code, the key the engine URL carries.
41
+ if (!params.data.code) return;
42
+ const result = await CyberiaInstanceService.get({ id: params.data.code });
42
43
  if (result.status === 'success' && result.data) {
43
44
  if (loadInstanceCallback) await loadInstanceCallback(result.data);
44
45
  NotificationManager.Push({
45
- html: `Instance "${result.data.name || result.data.code || params.data._id}" loaded`,
46
+ html: `Instance "${result.data.name || result.data.code}" loaded`,
46
47
  status: 'success',
47
48
  });
48
49
  } else {
@@ -96,46 +96,6 @@ class CyberiaInstanceService {
96
96
  return reject(error);
97
97
  }),
98
98
  );
99
- /** Fallback-world default items currently staged on the engine process. */
100
- static getFallbackDefaultItems = () =>
101
- new Promise((resolve, reject) =>
102
- fetch(getApiBaseUrl({ id: 'fallback-world/default-items', endpoint }), {
103
- method: 'GET',
104
- headers: headersFactory(),
105
- credentials: 'include',
106
- })
107
- .then(async (res) => res.json())
108
- .then((res) => {
109
- logger.info(res);
110
- return resolve(res);
111
- })
112
- .catch((error) => {
113
- logger.error(error);
114
- return reject(error);
115
- }),
116
- );
117
- /**
118
- * Stage the fallback world's default items and reload a running cyberia-server
119
- * (moderator/admin). The items ride along with the trigger — nothing is persisted.
120
- */
121
- static fallbackHotReload = (options = { body: {} }) =>
122
- new Promise((resolve, reject) =>
123
- fetch(getApiBaseUrl({ id: 'fallback-world/hot-reload', endpoint }), {
124
- method: 'POST',
125
- headers: headersFactory(),
126
- credentials: 'include',
127
- body: JSON.stringify(options.body ?? {}),
128
- })
129
- .then(async (res) => res.json())
130
- .then((res) => {
131
- logger.info(res);
132
- return resolve(res);
133
- })
134
- .catch((error) => {
135
- logger.error(error);
136
- return reject(error);
137
- }),
138
- );
139
99
  static portalConnect = (options = { id: '' }) =>
140
100
  new Promise((resolve, reject) =>
141
101
  fetch(getApiBaseUrl({ id: `${options.id}/portal-connect`, endpoint }), {
@@ -29,7 +29,7 @@ class CyberiaMapManagement {
29
29
  <i class="fa-solid fa-upload"></i>
30
30
  </div>`,
31
31
  class: `in fll section-mp management-table-btn-mini management-table-btn-load-map-${idModal}-${cellRenderId} ${
32
- !params.data._id ? 'hide' : ''
32
+ !params.data.code ? 'hide' : ''
33
33
  }`,
34
34
  })}`;
35
35
 
@@ -37,12 +37,13 @@ class CyberiaMapManagement {
37
37
  EventsUI.onClick(
38
38
  `.management-table-btn-load-map-${idModal}-${cellRenderId}`,
39
39
  async () => {
40
- if (!params.data._id) return;
41
- const result = await CyberiaMapService.get({ id: params.data._id });
40
+ // Maps are addressed by code, the key the engine URL carries.
41
+ if (!params.data.code) return;
42
+ const result = await CyberiaMapService.get({ id: params.data.code });
42
43
  if (result.status === 'success' && result.data) {
43
44
  if (loadMapCallback) await loadMapCallback(result.data);
44
45
  NotificationManager.Push({
45
- html: `Map "${result.data.name || result.data.code || params.data._id}" loaded`,
46
+ html: `Map "${result.data.name || result.data.code}" loaded`,
46
47
  status: 'success',
47
48
  });
48
49
  } else {
@@ -0,0 +1,138 @@
1
+ import { Auth } from '../../components/core/Auth.js';
2
+ import { loggerFactory } from '../../components/core/Logger.js';
3
+ import { getApiBaseUrl, headersFactory, payloadFactory, buildQueryUrl } from '../core/core.service.js';
4
+ const logger = loggerFactory(import.meta);
5
+ logger.info('Load service');
6
+ const endpoint = 'cyberia-map-audio-conf';
7
+ class CyberiaMapAudioConfService {
8
+ static post = (options = { id: '', body: {} }) =>
9
+ new Promise((resolve, reject) =>
10
+ fetch(getApiBaseUrl({ id: options.id, endpoint }), {
11
+ method: 'POST',
12
+ headers: headersFactory(),
13
+ credentials: 'include',
14
+ body: payloadFactory(options.body),
15
+ })
16
+ .then(async (res) => {
17
+ return await res.json();
18
+ })
19
+ .then((res) => {
20
+ logger.info(res);
21
+ return resolve(res);
22
+ })
23
+ .catch((error) => {
24
+ logger.error(error);
25
+ return reject(error);
26
+ }),
27
+ );
28
+ static put = (options = { id: '', body: {} }) =>
29
+ new Promise((resolve, reject) =>
30
+ fetch(getApiBaseUrl({ id: options.id, endpoint }), {
31
+ method: 'PUT',
32
+ headers: headersFactory(),
33
+ credentials: 'include',
34
+ body: payloadFactory(options.body),
35
+ })
36
+ .then(async (res) => {
37
+ return await res.json();
38
+ })
39
+ .then((res) => {
40
+ logger.info(res);
41
+ return resolve(res);
42
+ })
43
+ .catch((error) => {
44
+ logger.error(error);
45
+ return reject(error);
46
+ }),
47
+ );
48
+ static get = (options = {}) => {
49
+ const { id, page, limit, filterModel, sortModel, sort, asc, order } = options;
50
+ const url = buildQueryUrl(getApiBaseUrl({ id, endpoint }), {
51
+ page,
52
+ limit,
53
+ filterModel,
54
+ sortModel,
55
+ sort,
56
+ asc,
57
+ order,
58
+ });
59
+ return new Promise((resolve, reject) =>
60
+ fetch(url.toString(), {
61
+ method: 'GET',
62
+ headers: headersFactory(),
63
+ credentials: 'include',
64
+ })
65
+ .then(async (res) => {
66
+ return await res.json();
67
+ })
68
+ .then((res) => {
69
+ logger.info(res);
70
+ return resolve(res);
71
+ })
72
+ .catch((error) => {
73
+ logger.error(error);
74
+ return reject(error);
75
+ }),
76
+ );
77
+ };
78
+ static delete = (options = { id: '', body: {} }) =>
79
+ new Promise((resolve, reject) =>
80
+ fetch(getApiBaseUrl({ id: options.id, endpoint }), {
81
+ method: 'DELETE',
82
+ headers: headersFactory(),
83
+ credentials: 'include',
84
+ body: payloadFactory(options.body),
85
+ })
86
+ .then(async (res) => {
87
+ return await res.json();
88
+ })
89
+ .then((res) => {
90
+ logger.info(res);
91
+ return resolve(res);
92
+ })
93
+ .catch((error) => {
94
+ logger.error(error);
95
+ return reject(error);
96
+ }),
97
+ );
98
+ static getByMapCode = (options = { mapCode: '' }) =>
99
+ new Promise((resolve, reject) =>
100
+ fetch(`${getApiBaseUrl({ endpoint })}/map-code/${options.mapCode}`, {
101
+ method: 'GET',
102
+ headers: headersFactory(),
103
+ credentials: 'include',
104
+ })
105
+ .then(async (res) => {
106
+ return await res.json();
107
+ })
108
+ .then((res) => {
109
+ logger.info(res);
110
+ return resolve(res);
111
+ })
112
+ .catch((error) => {
113
+ logger.error(error);
114
+ return reject(error);
115
+ }),
116
+ );
117
+ static assign = (options = { mapCode: '', body: {} }) =>
118
+ new Promise((resolve, reject) =>
119
+ fetch(`${getApiBaseUrl({ endpoint })}/map-code/${options.mapCode}`, {
120
+ method: 'POST',
121
+ headers: headersFactory(),
122
+ credentials: 'include',
123
+ body: payloadFactory(options.body),
124
+ })
125
+ .then(async (res) => {
126
+ return await res.json();
127
+ })
128
+ .then((res) => {
129
+ logger.info(res);
130
+ return resolve(res);
131
+ })
132
+ .catch((error) => {
133
+ logger.error(error);
134
+ return reject(error);
135
+ }),
136
+ );
137
+ }
138
+ export { CyberiaMapAudioConfService };
@@ -26,7 +26,7 @@ class ObjectLayerManagement {
26
26
  this.eGui = document.createElement('div');
27
27
  const { data } = params;
28
28
 
29
- if (!data || !data._id) {
29
+ if (!data?.data?.item?.id) {
30
30
  this.eGui.innerHTML = '';
31
31
  return;
32
32
  }
@@ -43,10 +43,8 @@ class ObjectLayerManagement {
43
43
  if (btn)
44
44
  btn.onclick = async () =>
45
45
  setTimeout(async () => {
46
- // Navigate to viewer route first
47
46
  setPath(`${getProxyPath()}object-layer-engine-viewer`);
48
- // Then add query param without replacing history
49
- setQueryParams({ id: data._id }, { replace: true });
47
+ setQueryParams({ id: null, itemId: data.data.item.id }, { replace: true });
50
48
  if (s(`.modal-object-layer-engine-viewer`)) {
51
49
  await ObjectLayerEngineViewer.Reload({ appStore, force: true });
52
50
  }
@@ -72,7 +70,7 @@ class ObjectLayerManagement {
72
70
  this.eGui = document.createElement('div');
73
71
  const { data } = params;
74
72
 
75
- if (!data || !data._id) {
73
+ if (!data?.data?.item?.id) {
76
74
  this.eGui.innerHTML = '';
77
75
  return;
78
76
  }
@@ -89,10 +87,8 @@ class ObjectLayerManagement {
89
87
  if (btn)
90
88
  btn.onclick = async () =>
91
89
  setTimeout(async () => {
92
- // Navigate to editor route first
93
90
  setPath(`${getProxyPath()}object-layer-engine`);
94
- // Then add query param without replacing history
95
- setQueryParams({ id: data._id }, { replace: true });
91
+ setQueryParams({ id: null, itemId: data.data.item.id }, { replace: true });
96
92
  if (s(`.modal-object-layer-engine`)) await ObjectLayerEngineModal.Reload();
97
93
  else s(`.main-btn-object-layer-engine`).click();
98
94
  });
@@ -121,8 +117,8 @@ class ObjectLayerManagement {
121
117
  return;
122
118
  }
123
119
 
124
- const { type, id } = data.data.item;
125
- const imagePath = `${getProxyPath()}assets/${type}/${id}/08/0.png`;
120
+ const { id } = data.data.item;
121
+ const imagePath = `${getProxyPath()}api/atlas-sprite-sheet/idle-preview/${id}`;
126
122
 
127
123
  // Container with both image and fallback
128
124
  this.eGui.innerHTML = html`
@@ -183,9 +183,11 @@ class ObjectLayerService {
183
183
  }),
184
184
  );
185
185
  };
186
- static searchItemIds = (options = { q: '' }) => {
186
+ /** Item identity ({ id, type }) by id prefix (`q`) or by an exact id list (`ids`). */
187
+ static searchItemIds = (options = { q: '', ids: [] }) => {
187
188
  const url = new URL(getApiBaseUrl({ id: `search-item-ids`, endpoint }));
188
189
  if (options.q) url.searchParams.set('q', options.q);
190
+ if (options.ids?.length) url.searchParams.set('ids', options.ids.join(','));
189
191
  return new Promise((resolve, reject) =>
190
192
  fetch(url.toString(), {
191
193
  method: 'GET',
@@ -11,6 +11,7 @@ import { shellExec } from '../server/runtime/process.js';
11
11
  import { loggerFactory } from '../server/ops/logger.js';
12
12
  import {
13
13
  coverageReportCandidates,
14
+ coverageReportsFactory,
14
15
  coverageUnavailablePage,
15
16
  resolveCoverageReportPath,
16
17
  } from '../server/build/coverage.js';
@@ -296,43 +297,41 @@ const buildApiDocs = async ({
296
297
  ),
297
298
  'utf8',
298
299
  );
299
- setTimeout(async () => {
300
- const { default: swaggerAutoGen } = await import('swagger-autogen');
301
- const outputFile = `./public/${host}${path === '/' ? path : `${path}/`}swagger-output.json`;
302
- const routes = [];
303
- for (const api of apis) {
304
- if (['user', 'object-layer'].includes(api)) routes.push(`./src/api/${api}/${api}.router.js`);
305
- }
300
+ // Imported after the patch above, and awaited: the spec is part of the client build
301
+ // output, so a bundle zipped before it landed shipped without one and the pod that
302
+ // restored that bundle served no `api-docs`.
303
+ const { default: swaggerAutoGen } = await import('swagger-autogen');
304
+ const outputFile = `./public/${host}${path === '/' ? path : `${path}/`}swagger-output.json`;
305
+ const routes = [];
306
+ for (const api of apis) {
307
+ if (['user', 'object-layer'].includes(api)) routes.push(`./src/api/${api}/${api}.router.js`);
308
+ }
306
309
 
307
- await swaggerAutoGen({ openapi: '3.0.0' })(outputFile, routes, doc);
310
+ await swaggerAutoGen({ openapi: '3.0.0' })(outputFile, routes, doc);
308
311
 
309
- // Post-process: inject requestBody into operations — swagger-autogen silently
310
- // ignores #swagger.requestBody annotations and has no internal OAS-3 body support.
311
- if (fs.existsSync(outputFile)) {
312
- const swaggerJson = JSON.parse(fs.readFileSync(outputFile, 'utf8'));
313
- let patched = false;
312
+ // Post-process: inject requestBody into operations — swagger-autogen silently
313
+ // ignores #swagger.requestBody annotations and has no internal OAS-3 body support.
314
+ if (fs.existsSync(outputFile)) {
315
+ const swaggerJson = JSON.parse(fs.readFileSync(outputFile, 'utf8'));
316
+ let patched = false;
314
317
 
315
- for (const [key, requestBody] of Object.entries(requestBodies)) {
316
- const [method, ...pathParts] = key.split(' ');
317
- const opPath = pathParts.join(' ');
318
- if (swaggerJson.paths?.[opPath]?.[method]) {
319
- swaggerJson.paths[opPath][method].requestBody = requestBody;
320
- // Remove any stale in:body entry from parameters (OAS 3.0 doesn't allow it)
321
- if (Array.isArray(swaggerJson.paths[opPath][method].parameters)) {
322
- swaggerJson.paths[opPath][method].parameters = swaggerJson.paths[opPath][method].parameters.filter(
323
- (p) => p.in !== 'body',
324
- );
325
- }
326
- patched = true;
318
+ for (const [key, requestBody] of Object.entries(requestBodies)) {
319
+ const [method, ...pathParts] = key.split(' ');
320
+ const opPath = pathParts.join(' ');
321
+ if (swaggerJson.paths?.[opPath]?.[method]) {
322
+ swaggerJson.paths[opPath][method].requestBody = requestBody;
323
+ // Remove any stale in:body entry from parameters (OAS 3.0 doesn't allow it)
324
+ if (Array.isArray(swaggerJson.paths[opPath][method].parameters)) {
325
+ swaggerJson.paths[opPath][method].parameters = swaggerJson.paths[opPath][method].parameters.filter(
326
+ (p) => p.in !== 'body',
327
+ );
327
328
  }
328
- }
329
-
330
- if (patched) {
331
- fs.writeFileSync(outputFile, JSON.stringify(swaggerJson, null, 2), 'utf8');
332
- // logger.warn('swagger post-process: requestBody injected', Object.keys(requestBodies));
329
+ patched = true;
333
330
  }
334
331
  }
335
- });
332
+
333
+ if (patched) fs.writeFileSync(outputFile, JSON.stringify(swaggerJson, null, 2), 'utf8');
334
+ }
336
335
  };
337
336
 
338
337
  /**
@@ -401,9 +400,9 @@ const buildJsDocs = async ({ host, path, metadata = {}, publicClientId, docs, do
401
400
  };
402
401
 
403
402
  /**
404
- * Publishes the coverage HTML report a build carried into the docs route.
403
+ * Publishes every coverage HTML report the deploy declares, each at `docs/coverage/<id>`.
405
404
  *
406
- * Never generates it: the report belongs to the test stage, which bundles it into the
405
+ * Never generates one: a report belongs to the test stage, which bundles it into the
407
406
  * deploy artifact (see {@link module:src/server/build/coverage.js}). A client build that
408
407
  * shelled out to `npm test` here spent minutes of a pod's build phase on a runner the
409
408
  * workload has no business holding, and every expected non-zero exit of that suite latched
@@ -412,31 +411,32 @@ const buildJsDocs = async ({ host, path, metadata = {}, publicClientId, docs, do
412
411
  * @memberof clientBuildDocs
413
412
  * @param {Object} options - Coverage build options
414
413
  * @param {Object} options.docs - Documentation config from server conf
415
- * @param {string} options.docs.coveragePath - Source tree root the report was bundled into
416
- * @param {string} [options.docs.coverageOutputDir] - Route directory under the docs path
414
+ * @param {Array<{id: string, label?: string, suite?: string, path?: string}>} [options.docs.coverage] - Declared reports
417
415
  * @param {string} options.docsDestination - Resolved output path where docs were built
418
416
  */
419
417
  const buildCoverage = async ({ docs, docsDestination }) => {
420
418
  const logger = loggerFactory(import.meta);
421
- const { coveragePath, coverageOutputDir = 'coverage' } = docs;
422
- // No configured source tree is a deploy that never declared coverage — not a missing report.
423
- if (!coveragePath) return;
419
+ const reports = coverageReportsFactory(docs);
420
+ if (reports.length === 0) return;
421
+ // The route holds exactly the declared reports: one dropped from the conf leaves with it.
422
+ fs.emptyDirSync(`${docsDestination}coverage`);
423
+ for (const report of reports) {
424
+ const coverageBuildPath = `${docsDestination}coverage/${report.id}`;
425
+ const reportPath = resolveCoverageReportPath(report);
424
426
 
425
- const coverageBuildPath = `${docsDestination}${coverageOutputDir}`;
426
- const reportPath = resolveCoverageReportPath(coveragePath);
427
+ if (!reportPath) {
428
+ fs.outputFileSync(`${coverageBuildPath}/index.html`, coverageUnavailablePage(report), 'utf8');
429
+ logger.warn('no coverage report bundled, publishing the unavailable page', {
430
+ id: report.id,
431
+ searched: coverageReportCandidates(report),
432
+ published: coverageBuildPath,
433
+ });
434
+ continue;
435
+ }
427
436
 
428
- if (!reportPath) {
429
- fs.outputFileSync(`${coverageBuildPath}/index.html`, coverageUnavailablePage(), 'utf8');
430
- logger.warn('no coverage report bundled, publishing the unavailable page', {
431
- searched: coverageReportCandidates(coveragePath),
432
- published: coverageBuildPath,
433
- });
434
- return;
437
+ fs.copySync(reportPath, coverageBuildPath);
438
+ logger.warn('build coverage', coverageBuildPath);
435
439
  }
436
-
437
- fs.emptyDirSync(coverageBuildPath);
438
- fs.copySync(reportPath, coverageBuildPath);
439
- logger.warn('build coverage', coverageBuildPath);
440
440
  };
441
441
 
442
442
  /**
@@ -473,7 +473,7 @@ const buildDocs = async ({
473
473
  // TypeDoc output is versioned: served at /docs/engine/{version}/
474
474
  const version = (packageData?.version || '').replace(/^v/, '');
475
475
  const jsDocsDestination = `./public/${host}${pathPrefix}docs/engine/${version}/`;
476
- // Coverage output at /docs/coverage/ (or /docs/{coverageOutputDir}/)
476
+ // Coverage reports at /docs/coverage/<id>/
477
477
  const coverageBaseDestination = `./public/${host}${pathPrefix}docs/`;
478
478
  await buildJsDocs({ host, path, metadata, publicClientId, docs, docsDestination: jsDocsDestination });
479
479
  await buildCoverage({ docs, docsDestination: coverageBaseDestination });