cyberia 3.2.12 → 3.2.22

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 (55) hide show
  1. package/.github/workflows/engine-cyberia.cd.yml +1 -0
  2. package/.github/workflows/engine-cyberia.ci.yml +14 -2
  3. package/.github/workflows/ghpkg.ci.yml +1 -0
  4. package/.github/workflows/npmpkg.ci.yml +9 -5
  5. package/CHANGELOG.md +151 -1
  6. package/CLI-HELP.md +975 -1130
  7. package/bin/build.js +97 -136
  8. package/bin/build.template.js +25 -179
  9. package/bin/cyberia.js +11 -6
  10. package/bin/deploy.js +4 -1
  11. package/bin/index.js +11 -6
  12. package/conf.js +1 -0
  13. package/deployment.yaml +74 -2
  14. package/hardhat/package-lock.json +4 -4
  15. package/hardhat/package.json +1 -1
  16. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +2 -2
  17. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  18. package/manifests/deployment/dd-cyberia-development/deployment.yaml +74 -2
  19. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  20. package/package.json +7 -7
  21. package/scripts/link-local-underpost-cli.sh +6 -0
  22. package/scripts/test-monitor.sh +250 -0
  23. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +7 -0
  24. package/src/cli/deploy.js +200 -282
  25. package/src/cli/env.js +1 -4
  26. package/src/cli/image.js +58 -4
  27. package/src/cli/index.js +47 -0
  28. package/src/cli/monitor.js +387 -6
  29. package/src/cli/release.js +26 -11
  30. package/src/cli/repository.js +101 -7
  31. package/src/cli/run.js +159 -73
  32. package/src/client/components/core/PanelForm.js +44 -44
  33. package/src/client/components/cyberia/SharedDefaultsCyberia.js +1 -1
  34. package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +55 -1
  35. package/src/client/public/cyberia-docs/ARCHITECTURE.md +272 -50
  36. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +20 -11
  37. package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +23 -1
  38. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  39. package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
  40. package/src/db/mongo/MongooseDB.js +2 -1
  41. package/src/index.js +1 -1
  42. package/src/runtime/cyberia-client/Dockerfile +4 -22
  43. package/src/runtime/cyberia-client/Dockerfile.dev +3 -18
  44. package/src/runtime/cyberia-server/Dockerfile +3 -23
  45. package/src/runtime/cyberia-server/Dockerfile.dev +3 -27
  46. package/src/runtime/wp/Dockerfile +3 -3
  47. package/src/server/catalog-underpost.js +61 -0
  48. package/src/server/catalog.js +77 -0
  49. package/src/server/conf.js +414 -56
  50. package/src/server/ipfs-client.js +5 -3
  51. package/src/server/runtime-status.js +235 -0
  52. package/src/server/start.js +32 -11
  53. package/test/deploy-monitor.test.js +251 -0
  54. package/manifests/deployment/dd-test-development/deployment.yaml +0 -256
  55. package/manifests/deployment/dd-test-development/proxy.yaml +0 -102
package/bin/build.js CHANGED
@@ -1,105 +1,65 @@
1
+ #! /usr/bin/env node
2
+
3
+ import { Command } from 'commander';
1
4
  import fs from 'fs-extra';
2
- import { loggerFactory } from '../src/server/logger.js';
3
- import { shellExec } from '../src/server/process.js';
4
5
  import dotenv from 'dotenv';
6
+ import { loggerFactory } from '../src/server/logger.js';
5
7
  import { getCapVariableName } from '../src/client/components/core/CommonJs.js';
6
- import { getPathsSSR } from '../src/server/conf.js';
8
+ import {
9
+ getPathsSSR,
10
+ resolveDeployList,
11
+ syncPrivateConf,
12
+ syncDeployIdSources,
13
+ buildTemplate,
14
+ updatePrivateEngineTestRepo,
15
+ } from '../src/server/conf.js';
16
+ import { loadDeployCatalog } from '../src/server/catalog.js';
17
+ import UnderpostRepository from '../src/cli/repository.js';
7
18
 
8
19
  const baseConfPath = './engine-private/conf/dd-cron/.env.production';
9
20
  if (fs.existsSync(baseConfPath)) dotenv.config({ path: baseConfPath, override: true });
10
21
 
11
22
  const logger = loggerFactory(import.meta);
12
23
 
13
- const confName = process.argv[2];
14
24
  const basePath = '../pwa-microservices-template';
15
- const repoName = `engine-${confName.split('dd-')[1]}`;
16
- const deployList = (confName === 'dd' ? fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8') : confName).split(
17
- ',',
18
- );
19
-
20
- logger.info('Build repository', {
21
- confName,
22
- repoName,
23
- basePath,
24
- deployList,
25
- });
26
-
27
- if (process.argv.includes('conf')) {
28
- for (const _confName of deployList) {
29
- const _repoName = `engine-${_confName.split('dd-')[1]}`;
30
- const privateRepoName = `${_repoName}-private`;
31
- const privateGitUri = `${process.env.GITHUB_USERNAME}/${privateRepoName}`;
32
-
33
- if (!fs.existsSync(`../${privateRepoName}`)) {
34
- shellExec(`cd .. && underpost clone ${privateGitUri}`, { silent: true });
35
- } else {
36
- shellExec(`cd ../${privateRepoName} && git checkout . && git clean -f -d && underpost pull . ${privateGitUri}`, {
37
- silent: true,
38
- });
39
- }
40
- const toPath = `../${privateRepoName}/conf/${_confName}`;
41
- fs.removeSync(toPath);
42
- fs.mkdirSync(toPath, { recursive: true });
43
- fs.copySync(`./engine-private/conf/${_confName}`, toPath);
44
- fs.removeSync(`../${privateRepoName}/replica`);
45
- if (fs.existsSync(`./engine-private/replica`)) {
46
- const replicas = await fs.readdir(`./engine-private/replica`);
47
- for (const replica of replicas)
48
- if (replica.match(_confName))
49
- fs.copySync(`./engine-private/replica/${replica}`, `../${privateRepoName}/replica/${replica}`);
50
- }
51
-
52
- if (fs.existsSync(`./engine-private/itc-scripts`)) {
53
- const itcScripts = await fs.readdir(`./engine-private/itc-scripts`);
54
- for (const itcScript of itcScripts)
55
- if (itcScript.match(_confName))
56
- fs.copySync(`./engine-private/itc-scripts/${itcScript}`, `../${privateRepoName}/itc-scripts/${itcScript}`);
57
- }
58
- switch (_confName) {
59
- case 'dd-cyberia':
60
- fs.copySync(`./engine-private/cyberia-instances/FOREST`, `../${privateRepoName}/cyberia-instances/FOREST`);
61
- break;
62
- default:
63
- break;
64
- }
65
- shellExec(
66
- `cd ../${privateRepoName}` +
67
- ` && git add .` +
68
- ` && underpost cmt . ci engine-core-conf 'Update ${_confName} conf'` +
69
- ` && underpost push . ${privateGitUri}`,
70
- {
71
- silent: true,
72
- silentOnError: true,
73
- },
74
- );
75
- }
76
- process.exit(0);
77
- }
78
25
 
79
- if (confName === 'dd') {
80
- for (const _confName of deployList) {
81
- shellExec(`node bin/build ${_confName}`);
26
+ /**
27
+ * Assembles a single deploy id's public template under {@link basePath}: pulls in
28
+ * its deploy-id-specific public sources, then mirrors the APIs, client components,
29
+ * SSR assets, manifests, and packaging declared by its conf into the template repo.
30
+ * @param {string} confName - A concrete deploy id (e.g. `dd-prototype`).
31
+ */
32
+ const buildDeployTemplate = async (confName) => {
33
+ const repoName = `engine-${confName.split('dd-')[1]}`;
34
+ const catalog = await loadDeployCatalog(confName);
35
+
36
+ if (catalog.sourceMoves.length) {
37
+ UnderpostRepository.API.sparseCheckoutDirectory(`conf/${confName}`);
38
+ if (catalog.sourceMoves.some(([src]) => !fs.existsSync(src))) UnderpostRepository.API.pullSourceRepo(repoName);
82
39
  }
83
- process.exit(0);
84
- }
40
+ syncDeployIdSources(catalog.sourceMoves);
85
41
 
86
- const { DefaultConf } = await import(`../conf.${confName}.js`);
42
+ const confDir = `./engine-private/conf/${confName}`;
43
+ const DefaultConf = {
44
+ server: JSON.parse(fs.readFileSync(`${confDir}/conf.server.json`, 'utf8')),
45
+ client: JSON.parse(fs.readFileSync(`${confDir}/conf.client.json`, 'utf8')),
46
+ ssr: JSON.parse(fs.readFileSync(`${confDir}/conf.ssr.json`, 'utf8')),
47
+ };
87
48
 
88
- {
89
49
  for (const host of Object.keys(DefaultConf.server)) {
90
50
  for (const path of Object.keys(DefaultConf.server[host])) {
91
51
  const { apis, ws } = DefaultConf.server[host][path];
92
52
  if (apis)
93
53
  for (const api of apis) {
94
- {
95
- const originPath = `./src/api/${api}`;
96
- logger.info(`Build`, originPath);
97
- fs.copySync(originPath, `${basePath}/src/api/${api}`);
54
+ const apiSrc = `./src/api/${api}`;
55
+ if (fs.existsSync(apiSrc)) {
56
+ logger.info(`Build`, apiSrc);
57
+ fs.copySync(apiSrc, `${basePath}/src/api/${api}`);
98
58
  }
99
- {
100
- const originPath = `./src/client/services/${api}`;
101
- logger.info(`Build`, originPath);
102
- fs.copySync(originPath, `${basePath}/src/client/services/${api}`);
59
+ const serviceSrc = `./src/client/services/${api}`;
60
+ if (fs.existsSync(serviceSrc)) {
61
+ logger.info(`Build`, serviceSrc);
62
+ fs.copySync(serviceSrc, `${basePath}/src/client/services/${api}`);
103
63
  }
104
64
  }
105
65
 
@@ -108,9 +68,7 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
108
68
  }
109
69
  }
110
70
  }
111
- }
112
71
 
113
- {
114
72
  for (const client of Object.keys(DefaultConf.client)) {
115
73
  const capName = getCapVariableName(client);
116
74
  for (const component of Object.keys(DefaultConf.client[client].components)) {
@@ -135,9 +93,7 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
135
93
  }
136
94
  }
137
95
  }
138
- }
139
96
 
140
- {
141
97
  for (const client of Object.keys(DefaultConf.ssr)) {
142
98
  const ssrPaths = getPathsSSR(DefaultConf.ssr[client]);
143
99
  for (const originPath of ssrPaths) {
@@ -149,16 +105,14 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
149
105
  }
150
106
 
151
107
  if (!fs.existsSync(`${basePath}/.github/workflows`))
152
- fs.mkdirSync(`${basePath}/.github/workflows`, {
153
- recursive: true,
154
- });
108
+ fs.mkdirSync(`${basePath}/.github/workflows`, { recursive: true });
155
109
 
156
110
  const originPackageJson = JSON.parse(fs.readFileSync(`./package.json`, 'utf8'));
157
111
  const packageJson = JSON.parse(fs.readFileSync(`${basePath}/package.json`, 'utf8'));
158
112
  packageJson.name = repoName.replace('engine-', '');
159
113
 
160
114
  switch (confName) {
161
- case 'dd-cyberia':
115
+ case 'dd-cyberia': {
162
116
  fs.copyFileSync(`./bin/cyberia.js`, `${basePath}/bin/cyberia.js`);
163
117
  fs.copyFileSync(
164
118
  `./.github/workflows/publish.cyberia.ci.yml`,
@@ -167,27 +121,8 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
167
121
  if (packageJson.bin) delete packageJson.bin.underpost;
168
122
  if (!packageJson.bin) packageJson.bin = {};
169
123
  packageJson.bin.cyberia = 'bin/index.js';
170
- packageJson.keywords = [
171
- 'cyberia',
172
- 'cyberia-cli',
173
- 'engine-cyberia',
174
- 'sidecar',
175
- 'data-layer',
176
- 'engine-cyberia',
177
- 'object-layer',
178
- 'atlas-sprite-sheet',
179
- 'ipfs',
180
- 'erc-1155',
181
- 'object-layer-token',
182
- 'hardhat',
183
- 'hyperledger-besu',
184
- 'blockchain',
185
- 'web3',
186
- 'underpost-platform',
187
- 'mmorpg',
188
- ];
189
- packageJson.description =
190
- 'Cyberia CLI — toolchain for the Cyberia MMO data layer, content pipeline, persistence, gRPC services, and ERC-1155 lifecycle on Hyperledger Besu.';
124
+ packageJson.keywords = catalog.keywords;
125
+ packageJson.description = catalog.description;
191
126
  const { CyberiaDependencies } = await import(`../src/api/cyberia-server-defaults/cyberia-server-defaults.js`);
192
127
  packageJson.dependencies = {
193
128
  ...originPackageJson.dependencies,
@@ -201,26 +136,9 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
201
136
  'utf8',
202
137
  );
203
138
  fs.copySync(`./hardhat`, `${basePath}/hardhat`);
204
- for (const path of [
205
- '/src/grpc/cyberia',
206
- '/src/client/ssr/views/CyberiaServerMetrics.js',
207
- '/src/server/object-layer.js',
208
- '/src/server/atlas-sprite-sheet-generator.js',
209
- '/src/server/shape-generator.js',
210
- '/src/server/semantic-layer-generator.js',
211
- '/src/server/semantic-layer-generator-floor.js',
212
- '/src/server/semantic-layer-generator-skin.js',
213
- '/src/server/semantic-layer-generator-resource.js',
214
- '/test/shape-generator.test.js',
215
- '/src/server/besu-genesis-generator.js',
216
- '/src/runtime/cyberia-server',
217
- '/src/runtime/cyberia-client',
218
- '/.github/workflows/hardhat.ci.yml',
219
- '/src/client/public/cyberia-docs',
220
- '/src/api/cyberia-server-defaults',
221
- ])
222
- fs.copySync(`.${path}`, `${basePath}${path}`);
223
-
139
+ for (const path of catalog.templatePaths) fs.copySync(`.${path}`, `${basePath}${path}`);
140
+ break;
141
+ }
224
142
  default:
225
143
  break;
226
144
  }
@@ -248,8 +166,6 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
248
166
  `${basePath}/manifests/deployment/${confName}-development`,
249
167
  );
250
168
 
251
- // Copy conf.<deploy-id>.js to conf.js for the respective deployment
252
- fs.copyFileSync(`./conf.${confName}.js`, `${basePath}/conf.js`);
253
169
  fs.copyFileSync(`./manifests/deployment/${confName}-development/proxy.yaml`, `${basePath}/proxy.yaml`);
254
170
  fs.copyFileSync(`./manifests/deployment/${confName}-development/deployment.yaml`, `${basePath}/deployment.yaml`);
255
171
  const pvPvcPath = `./manifests/deployment/${confName}-development/pv-pvc.yaml`;
@@ -258,6 +174,51 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
258
174
  if (fs.existsSync(`./src/ws/${confName.split('-')[1]}`)) {
259
175
  fs.copySync(`./src/ws/${confName.split('-')[1]}`, `${basePath}/src/ws/${confName.split('-')[1]}`);
260
176
  }
261
- fs.copyFileSync(`.gitignore`, `${basePath}/.gitignore`);
262
- shellExec(`cd ${basePath} && npm install --ignore-scripts`);
263
- }
177
+ fs.writeFileSync(
178
+ `${basePath}/.gitignore`,
179
+ fs.readFileSync(`.gitignore`, 'utf8').split('# Ignore ERP / CRM custom prototypes src')[0],
180
+ );
181
+ };
182
+
183
+ const program = new Command();
184
+
185
+ program
186
+ .name('build')
187
+ .description('Assemble deploy id public templates and sync their private configuration repos.')
188
+ .argument('<conf-name>', 'Deploy id, comma-separated list, or the "dd" meta id (fans out via dd.router).')
189
+ .argument('[env]', 'Environment label (informational; kept for CI invocation compatibility).')
190
+ .option('--conf', 'Sync each deploy id private configuration repo and exit (no template assembly).')
191
+ .option(
192
+ '--no-template-rebuild',
193
+ 'Skip the from-scratch base template reconstruction before assembly (assemble onto the existing template).',
194
+ )
195
+ .option(
196
+ '--update-private',
197
+ 'After assembling each deploy id, publish it to its private test source repo (underpostnet/engine-test-<id>) for isolated test deploys.',
198
+ false,
199
+ )
200
+ .action(async (confName, env, options) => {
201
+ const deployList = resolveDeployList(confName);
202
+ logger.info('Build repository', { confName, basePath, deployList, conf: !!options.conf });
203
+
204
+ if (options.conf) {
205
+ for (const deployId of deployList) {
206
+ const { privateConfPaths } = await loadDeployCatalog(deployId);
207
+ syncPrivateConf(deployId, privateConfPaths);
208
+ }
209
+ return;
210
+ }
211
+
212
+ // Reconstruct the base template from 0 before assembly so no src from a previous
213
+ // build run leaks into this one. Opt out with --no-template-rebuild.
214
+ if (options.templateRebuild) await buildTemplate({ toPath: basePath });
215
+
216
+ for (const deployId of deployList) {
217
+ await buildDeployTemplate(deployId);
218
+ // Publish the just-assembled tree to the deploy id's private test repo so a
219
+ // pod started with `--private-test-repo` clones this work-in-progress source.
220
+ if (options.updatePrivate) await updatePrivateEngineTestRepo(deployId);
221
+ }
222
+ });
223
+
224
+ await program.parseAsync();
@@ -1,187 +1,33 @@
1
- import fs from 'fs-extra';
1
+ #! /usr/bin/env node
2
2
 
3
- import { loggerFactory } from '../src/server/logger.js';
4
- import { getDirname, newInstance, uniqueArray } from '../src/client/components/core/CommonJs.js';
5
- import { shellExec } from '../src/server/process.js';
6
- import walk from 'ignore-walk';
7
- import { validateTemplatePath } from '../src/server/conf.js';
3
+ import { Command } from 'commander';
4
+ import fs from 'fs-extra';
8
5
  import dotenv from 'dotenv';
9
-
10
- const logger = loggerFactory(import.meta);
6
+ import { loggerFactory } from '../src/server/logger.js';
7
+ import { buildTemplate, updatePrivateTemplateRepo } from '../src/server/conf.js';
11
8
 
12
9
  if (fs.existsSync('./engine-private/conf/dd-cron/.env.production'))
13
- dotenv.config({
14
- path: `./engine-private/conf/dd-cron/.env.production`,
15
- override: true,
16
- });
10
+ dotenv.config({ path: `./engine-private/conf/dd-cron/.env.production`, override: true });
17
11
  else dotenv.config();
18
12
 
19
- // Engine-only paths stripped from the template after the source sync.
20
- const TEMPLATE_DELETE_PATHS = [
21
- './.github',
22
- './manifests/deployment/dd-lampp-development',
23
- './manifests/deployment/dd-cyberia-development',
24
- './manifests/deployment/dd-core-development',
25
- './manifests/deployment/dd-template-development',
26
- './src/server/object-layer.js',
27
- './src/server/atlas-sprite-sheet-generator.js',
28
- './src/server/shape-generator.js',
29
- './src/server/semantic-layer-generator.js',
30
- './src/server/semantic-layer-generator-floor.js',
31
- './src/server/semantic-layer-generator-skin.js',
32
- './src/server/semantic-layer-generator-resource.js',
33
- './src/server/besu-genesis-generator.js',
34
- './src/grpc/cyberia',
35
- './src/runtime/cyberia-server',
36
- './src/runtime/cyberia-client',
37
- './test/shape-generator.test.js',
38
- './src/client/public/cyberia-docs',
39
- 'bin/cyberia.js',
40
- './hardhat',
41
- ];
42
-
43
- // Workflow + service files re-added to the template after the engine-only strip above.
44
- const TEMPLATE_RESTORE_PATHS = [
45
- `./.github/workflows/pwa-microservices-template-page.cd.yml`,
46
- `./.github/workflows/pwa-microservices-template-test.ci.yml`,
47
- `./.github/workflows/npmpkg.ci.yml`,
48
- `./.github/workflows/ghpkg.ci.yml`,
49
- `./.github/workflows/gitlab.ci.yml`,
50
- `./.github/workflows/publish.ci.yml`,
51
- `./.github/workflows/release.cd.yml`,
52
- `./src/client/services/user/guest.service.js`,
53
- './src/api/user/guest.service.js',
54
- './src/ws/IoInterface.js',
55
- './src/ws/IoServer.js',
56
- ];
57
-
58
- const TEMPLATE_KEYWORDS = [
59
- 'underpost',
60
- 'underpost-platform',
61
- 'cli',
62
- 'toolchain',
63
- 'ci-cd',
64
- 'devops',
65
- 'kubernetes',
66
- 'k3s',
67
- 'kubeadm',
68
- 'lxd',
69
- 'bare-metal',
70
- 'container-orchestration',
71
- 'image-management',
72
- 'pwa',
73
- 'workbox',
74
- 'microservices',
75
- ];
76
-
77
- const TEMPLATE_DESCRIPTION =
78
- 'Underpost Platform — end-to-end CI/CD and application-delivery toolchain CLI. Covers bare metal, Kubernetes, K3s, kubeadm, LXD, container/image orchestration, secrets, databases, cron jobs, monitoring, SSH, runners, PWA + Workbox delivery, and release orchestration. Extensible via downstream CLIs.';
79
-
80
- /**
81
- * Builds the pwa-microservices-template from scratch out of the current engine source tree.
82
- *
83
- * Clones (or resets) the template repo next to the engine, syncs every engine-tracked file the
84
- * template is allowed to carry (validateTemplatePath), strips engine-only modules, restores the
85
- * template's own CI workflows + guest services, and rewrites package.json / package-lock.json /
86
- * README so the template is a standalone, installable project.
87
- *
88
- * Usage: node bin/build.template [srcPath=./] [toPath=../pwa-microservices-template]
89
- */
90
- const srcPath = (process.argv[2] ?? './').replaceAll(`'`, '');
91
- const toPath = (process.argv[3] ?? '../pwa-microservices-template').replaceAll(`'`, '');
92
- const githubUsername = process.env.GITHUB_USERNAME;
93
-
94
- logger.info('Build template', { srcPath, toPath });
95
-
96
- try {
97
- const sourceFiles = (
98
- await new Promise((resolve) =>
99
- walk(
100
- {
101
- path: srcPath,
102
- ignoreFiles: [`.gitignore`],
103
- includeEmpty: false,
104
- follow: false,
105
- },
106
- (...args) => resolve(args[1]),
107
- ),
108
- )
109
- ).filter((p) => !p.startsWith('.git'));
110
-
111
- // Clone the template from 0 if missing; otherwise reset it to a clean pristine checkout.
112
- if (!fs.existsSync(toPath)) {
113
- shellExec(`cd .. && node engine/bin clone ${githubUsername}/pwa-microservices-template`);
114
- } else {
115
- shellExec(`cd ${toPath} && git reset && git checkout . && git clean -f -d`);
116
- shellExec(`node bin pull ${toPath} ${githubUsername}/pwa-microservices-template`);
117
- shellExec(`sudo rm -rf ${toPath}/engine-private`);
118
- shellExec(`sudo rm -rf ${toPath}/logs`);
119
- }
120
- shellExec(`cd ${toPath} && git config core.filemode false`);
121
-
122
- for (const copyPath of sourceFiles) {
123
- if (copyPath === 'NaN') continue;
124
- const absolutePath = `${srcPath}/${copyPath}`;
125
- if (!validateTemplatePath(absolutePath)) continue;
126
-
127
- const folder = getDirname(`${toPath}/${copyPath}`);
128
- if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
129
-
130
- logger.info('build', `${toPath}/${copyPath}`);
131
- fs.copyFileSync(absolutePath, `${toPath}/${copyPath}`);
132
- }
133
-
134
- fs.copySync(`./.vscode`, `${toPath}/.vscode`);
135
- fs.copySync(`./src/client/public/default`, `${toPath}/src/client/public/default`);
136
-
137
- // Preserve the template's own README + package.json identity before merging engine metadata.
138
- for (const checkoutPath of ['README.md', 'package.json']) shellExec(`cd ${toPath} && git checkout ${checkoutPath}`);
139
-
140
- for (const deletePath of TEMPLATE_DELETE_PATHS) {
141
- const target = `${toPath}/${deletePath}`;
142
- if (fs.existsSync(target)) fs.removeSync(target);
143
- }
144
-
145
- fs.mkdirSync(`${toPath}/.github/workflows`, { recursive: true });
146
- for (const restorePath of TEMPLATE_RESTORE_PATHS) fs.copyFileSync(restorePath, `${toPath}/${restorePath}`);
147
-
148
- // ── package.json: take engine deps/scripts/version, keep template identity. ──
149
- const originPackageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
150
- const templatePackageJson = JSON.parse(fs.readFileSync(`${toPath}/package.json`, 'utf8'));
151
- const templateName = templatePackageJson.name;
152
-
153
- templatePackageJson.dependencies = originPackageJson.dependencies;
154
- templatePackageJson.devDependencies = originPackageJson.devDependencies;
155
- templatePackageJson.version = originPackageJson.version;
156
- templatePackageJson.scripts = originPackageJson.scripts;
157
- templatePackageJson.overrides = originPackageJson.overrides;
158
- templatePackageJson.name = templateName;
159
- templatePackageJson.description = TEMPLATE_DESCRIPTION;
160
- templatePackageJson.keywords = uniqueArray(TEMPLATE_KEYWORDS.concat(templatePackageJson.keywords || []));
161
- delete templatePackageJson.scripts['update:template'];
162
- fs.writeFileSync(`${toPath}/package.json`, JSON.stringify(templatePackageJson, null, 4), 'utf8');
13
+ const logger = loggerFactory(import.meta);
163
14
 
164
- // ── package-lock.json: mirror engine packages, keep template name/version on the root entry. ──
165
- const originPackageLockJson = JSON.parse(fs.readFileSync('./package-lock.json', 'utf8'));
166
- const templatePackageLockJson = JSON.parse(fs.readFileSync(`${toPath}/package-lock.json`, 'utf8'));
167
- const originBasePackageLock = newInstance(templatePackageLockJson.packages['']);
168
- templatePackageLockJson.name = templateName;
169
- templatePackageLockJson.version = originPackageLockJson.version;
170
- templatePackageLockJson.packages = originPackageLockJson.packages;
171
- templatePackageLockJson.packages[''].name = templateName;
172
- templatePackageLockJson.packages[''].version = originPackageLockJson.version;
173
- templatePackageLockJson.packages[''].hasInstallScript = originBasePackageLock.hasInstallScript;
174
- templatePackageLockJson.packages[''].license = originBasePackageLock.license;
175
- fs.writeFileSync(`${toPath}/package-lock.json`, JSON.stringify(templatePackageLockJson, null, 4), 'utf8');
15
+ const program = new Command();
16
+
17
+ program
18
+ .name('build.template')
19
+ .description('Rebuild the standalone pwa-microservices-template from scratch out of the engine source tree.')
20
+ .argument('[src-path]', 'Engine source root to sync from.', './')
21
+ .argument('[to-path]', 'Template output path.', '../pwa-microservices-template')
22
+ .option('--update-private', 'Update private template repository', false)
23
+ .action(async (srcPath, toPath, options) => {
24
+ try {
25
+ if (options.updatePrivate) return await updatePrivateTemplateRepo();
26
+ await buildTemplate({ srcPath: srcPath.replaceAll(`'`, ''), toPath: toPath.replaceAll(`'`, '') });
27
+ } catch (error) {
28
+ logger.error(error, error.stack);
29
+ process.exit(1);
30
+ }
31
+ });
176
32
 
177
- fs.writeFileSync(
178
- `${toPath}/README.md`,
179
- fs
180
- .readFileSync('./README.md', 'utf8')
181
- .replace('<!-- template-title -->', '#### Base template for pwa/api-rest projects.'),
182
- 'utf8',
183
- );
184
- } catch (error) {
185
- logger.error(error, error.stack);
186
- process.exit(1);
187
- }
33
+ await program.parseAsync();
package/bin/cyberia.js CHANGED
@@ -4131,6 +4131,10 @@ try {
4131
4131
  runner
4132
4132
  .command('import-default-items')
4133
4133
  .option('--dev', 'Force development environment (loads .env.development for IPFS localhost, etc.)')
4134
+ .option(
4135
+ '--mongo-host <mongo-host>',
4136
+ 'Mongo host override (forwarded to ol, seed-skill-config, seed-dialogues, client-hints)',
4137
+ )
4134
4138
  .description('Import default Object Layer items, skill config, dialogues, and client-hints into MongoDB')
4135
4139
  .action(async (options) => {
4136
4140
  // Pre-flight: every item id referenced by the fallback world must
@@ -4148,11 +4152,12 @@ try {
4148
4152
  }
4149
4153
 
4150
4154
  const devFlag = options.dev ? ' --dev' : '';
4155
+ const mongoHostFlag = options.mongoHost ? ` --mongo-host ${options.mongoHost}` : '';
4151
4156
  const instanceCode = process.env.INSTANCE_CODE || 'cyberia-main';
4152
- shellExec(`node bin/cyberia ol ${DefaultCyberiaItems.map((e) => e.item.id)} --import${devFlag}`);
4153
- shellExec(`node bin/cyberia run-workflow seed-skill-config${devFlag}`);
4154
- shellExec(`node bin/cyberia run-workflow seed-dialogues${devFlag}`);
4155
- shellExec(`node bin/cyberia client-hints ${instanceCode} --seed-defaults${devFlag}`);
4157
+ shellExec(`node bin/cyberia ol ${DefaultCyberiaItems.map((e) => e.item.id)} --import${devFlag}${mongoHostFlag}`);
4158
+ shellExec(`node bin/cyberia run-workflow seed-skill-config${devFlag}${mongoHostFlag}`);
4159
+ shellExec(`node bin/cyberia run-workflow seed-dialogues${devFlag}${mongoHostFlag}`);
4160
+ shellExec(`node bin/cyberia client-hints ${instanceCode} --seed-defaults${devFlag}${mongoHostFlag}`);
4156
4161
  });
4157
4162
 
4158
4163
  runner
@@ -4407,7 +4412,7 @@ try {
4407
4412
  throw new Error('Trigger underpost passthrough');
4408
4413
  }
4409
4414
 
4410
- program.parse();
4415
+ await program.parseAsync();
4411
4416
  } catch (error) {
4412
4417
  // ONLY reroute on the explicit passthrough sentinel. Any other thrown
4413
4418
  // error (subprocess non-zero from shellExec's fail-fast default, CLI
@@ -4420,7 +4425,7 @@ try {
4420
4425
  process.argv = process.argv.filter((c) => c !== 'underpost');
4421
4426
  logger.warn('Rerouting to underpost cli...');
4422
4427
  try {
4423
- underpostProgram.parse();
4428
+ await underpostProgram.parseAsync();
4424
4429
  } catch (err) {
4425
4430
  logger.error(err);
4426
4431
  process.exit(1);
package/bin/deploy.js CHANGED
@@ -283,7 +283,10 @@ ${shellExec(`git log | grep Author: | sort -u`, { stdout: true }).split(`\n`).jo
283
283
  }
284
284
 
285
285
  case 'cli-docs': {
286
- buildCliDoc(program, process.argv[3], process.argv[4]);
286
+ const version = Underpost.version;
287
+ const newVersion =
288
+ process.argv[4] && !process.argv[4].startsWith('v') ? `v${process.argv[4]}` : process.argv[4] || version;
289
+ buildCliDoc(program, process.argv[3] || version, newVersion);
287
290
  break;
288
291
  }
289
292
 
package/bin/index.js CHANGED
@@ -4131,6 +4131,10 @@ try {
4131
4131
  runner
4132
4132
  .command('import-default-items')
4133
4133
  .option('--dev', 'Force development environment (loads .env.development for IPFS localhost, etc.)')
4134
+ .option(
4135
+ '--mongo-host <mongo-host>',
4136
+ 'Mongo host override (forwarded to ol, seed-skill-config, seed-dialogues, client-hints)',
4137
+ )
4134
4138
  .description('Import default Object Layer items, skill config, dialogues, and client-hints into MongoDB')
4135
4139
  .action(async (options) => {
4136
4140
  // Pre-flight: every item id referenced by the fallback world must
@@ -4148,11 +4152,12 @@ try {
4148
4152
  }
4149
4153
 
4150
4154
  const devFlag = options.dev ? ' --dev' : '';
4155
+ const mongoHostFlag = options.mongoHost ? ` --mongo-host ${options.mongoHost}` : '';
4151
4156
  const instanceCode = process.env.INSTANCE_CODE || 'cyberia-main';
4152
- shellExec(`node bin/cyberia ol ${DefaultCyberiaItems.map((e) => e.item.id)} --import${devFlag}`);
4153
- shellExec(`node bin/cyberia run-workflow seed-skill-config${devFlag}`);
4154
- shellExec(`node bin/cyberia run-workflow seed-dialogues${devFlag}`);
4155
- shellExec(`node bin/cyberia client-hints ${instanceCode} --seed-defaults${devFlag}`);
4157
+ shellExec(`node bin/cyberia ol ${DefaultCyberiaItems.map((e) => e.item.id)} --import${devFlag}${mongoHostFlag}`);
4158
+ shellExec(`node bin/cyberia run-workflow seed-skill-config${devFlag}${mongoHostFlag}`);
4159
+ shellExec(`node bin/cyberia run-workflow seed-dialogues${devFlag}${mongoHostFlag}`);
4160
+ shellExec(`node bin/cyberia client-hints ${instanceCode} --seed-defaults${devFlag}${mongoHostFlag}`);
4156
4161
  });
4157
4162
 
4158
4163
  runner
@@ -4407,7 +4412,7 @@ try {
4407
4412
  throw new Error('Trigger underpost passthrough');
4408
4413
  }
4409
4414
 
4410
- program.parse();
4415
+ await program.parseAsync();
4411
4416
  } catch (error) {
4412
4417
  // ONLY reroute on the explicit passthrough sentinel. Any other thrown
4413
4418
  // error (subprocess non-zero from shellExec's fail-fast default, CLI
@@ -4420,7 +4425,7 @@ try {
4420
4425
  process.argv = process.argv.filter((c) => c !== 'underpost');
4421
4426
  logger.warn('Rerouting to underpost cli...');
4422
4427
  try {
4423
- underpostProgram.parse();
4428
+ await underpostProgram.parseAsync();
4424
4429
  } catch (err) {
4425
4430
  logger.error(err);
4426
4431
  process.exit(1);
package/conf.js CHANGED
@@ -750,6 +750,7 @@ const DefaultConf = /**/ {
750
750
  jsJsonPath: './typedoc.dd-cyberia.json',
751
751
  coverageOutputDir: 'hardhat-coverage',
752
752
  references: [
753
+ './src/client/public/cyberia-docs/CYBERIA.md',
753
754
  './src/client/public/cyberia-docs/WHITE-PAPER.md',
754
755
  './src/client/public/cyberia-docs/ARCHITECTURE.md',
755
756
  './src/client/public/cyberia-docs/QUEST-SYSTEM.md',