@nocobase/app-installer 0.1.0-beta.3 → 0.1.0-beta.5
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.
- package/README.md +96 -99
- package/dist/cli.js +8 -9
- package/dist/cli.js.map +1 -1
- package/dist/commands/install.js +41 -91
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/rollback.js +8 -11
- package/dist/commands/rollback.js.map +1 -1
- package/dist/commands/status.js +6 -27
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/upgrade.js +82 -213
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/lib/app-source.js +163 -0
- package/dist/lib/app-source.js.map +1 -0
- package/dist/lib/ecosystem.js +1 -5
- package/dist/lib/ecosystem.js.map +1 -1
- package/dist/lib/layout.js +0 -13
- package/dist/lib/layout.js.map +1 -1
- package/dist/lib/prechecks.js +1 -38
- package/dist/lib/prechecks.js.map +1 -1
- package/dist/lib/registry.js +0 -50
- package/dist/lib/registry.js.map +1 -1
- package/dist/lib/release.js +6 -161
- package/dist/lib/release.js.map +1 -1
- package/dist/lib/source.js +5 -51
- package/dist/lib/source.js.map +1 -1
- package/dist/lib/state.js +15 -1
- package/dist/lib/state.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { extract } from 'tar';
|
|
5
|
+
import { parse, stringify } from 'yaml';
|
|
6
|
+
import { EXIT_INVALID, InstallerError, isInstallerError } from "./errors.js";
|
|
7
|
+
import { unpackRelease } from "./release.js";
|
|
8
|
+
import { CommandFailedError, tail } from "./run-command.js";
|
|
9
|
+
/** Bare names are official applications; other publishers use their full scoped package name. */
|
|
10
|
+
export function parseAppSpec(value) {
|
|
11
|
+
const match = /^(?:(@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*)|([a-z0-9][a-z0-9._-]*))(?:@([a-zA-Z0-9][a-zA-Z0-9.+_-]*))?$/u.exec(value);
|
|
12
|
+
if (!match) {
|
|
13
|
+
throw new InstallerError('INVALID_USAGE', '--app expects an application name, optionally followed by @<version or tag>, e.g. studio or @nocobase/studio@beta.', { exitCode: EXIT_INVALID });
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
package: match[1] ?? `@nocobase/${match[2]}`,
|
|
17
|
+
selector: match[3] ?? 'latest',
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** Explicit application scope prevents a user's scoped registry from overriding --registry. */
|
|
21
|
+
function registryArgs(packageName, registry) {
|
|
22
|
+
return [
|
|
23
|
+
`--registry=${registry}`,
|
|
24
|
+
`--${packageName.split('/')[0]}:registry=${registry}`,
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
/** npm handles the user's registry authentication; resolve once, then pack that exact version. */
|
|
28
|
+
export async function resolveApp(spec, registry, run) {
|
|
29
|
+
// Validate selectors read from state or --to as well as those supplied to install.
|
|
30
|
+
parseAppSpec(`${spec.package}@${spec.selector}`);
|
|
31
|
+
try {
|
|
32
|
+
const result = await run('npm', [
|
|
33
|
+
'view',
|
|
34
|
+
`${spec.package}@${spec.selector}`,
|
|
35
|
+
'name',
|
|
36
|
+
'version',
|
|
37
|
+
'--json',
|
|
38
|
+
...registryArgs(spec.package, registry),
|
|
39
|
+
], { timeoutMs: 120_000 });
|
|
40
|
+
const metadata = JSON.parse(result.stdout);
|
|
41
|
+
if (metadata.name !== spec.package ||
|
|
42
|
+
!metadata.version ||
|
|
43
|
+
!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/u.test(metadata.version)) {
|
|
44
|
+
throw new InstallerError('APP_INVALID', `The registry did not resolve ${spec.package}@${spec.selector} to one application version.`);
|
|
45
|
+
}
|
|
46
|
+
return { package: spec.package, selector: metadata.version };
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (isInstallerError(error))
|
|
50
|
+
throw error;
|
|
51
|
+
throw new InstallerError('APP_RESOLVE_FAILED', `Could not resolve ${spec.package}@${spec.selector} from ${registry}.`, {
|
|
52
|
+
cause: error,
|
|
53
|
+
...(error instanceof CommandFailedError
|
|
54
|
+
? { details: { output: tail(`${error.stdout}\n${error.stderr}`) } }
|
|
55
|
+
: {}),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Build the published application itself, without scaffolding or rewriting its identity. */
|
|
60
|
+
export async function buildApp(options) {
|
|
61
|
+
const { app, registry, layout, run, reporter } = options;
|
|
62
|
+
const temporary = await mkdtemp(path.join(os.tmpdir(), 'nocobase-app-build-'));
|
|
63
|
+
const env = {
|
|
64
|
+
...process.env,
|
|
65
|
+
npm_config_registry: registry,
|
|
66
|
+
NPM_CONFIG_REGISTRY: registry,
|
|
67
|
+
PNPM_CONFIG_REGISTRY: registry,
|
|
68
|
+
PNPM_CONFIG_MINIMUM_RELEASE_AGE: '0',
|
|
69
|
+
CI: 'true',
|
|
70
|
+
};
|
|
71
|
+
try {
|
|
72
|
+
const pnpm = await run('pnpm', ['--version'], { cwd: temporary, env });
|
|
73
|
+
if (Number.parseInt(pnpm.stdout, 10) < 11 ||
|
|
74
|
+
!/^\d+\./u.test(pnpm.stdout.trim())) {
|
|
75
|
+
throw new InstallerError('PNPM_REQUIRED', 'Installing an npm application requires pnpm 11 or later.', { exitCode: EXIT_INVALID });
|
|
76
|
+
}
|
|
77
|
+
reporter.progress(`Downloading ${app.package}@${app.selector}`);
|
|
78
|
+
const packed = await run('npm', [
|
|
79
|
+
'pack',
|
|
80
|
+
`${app.package}@${app.selector}`,
|
|
81
|
+
'--ignore-scripts',
|
|
82
|
+
'--json',
|
|
83
|
+
...registryArgs(app.package, registry),
|
|
84
|
+
], { cwd: temporary, env, timeoutMs: 120_000 });
|
|
85
|
+
const entries = JSON.parse(packed.stdout);
|
|
86
|
+
const filename = entries[0]?.filename;
|
|
87
|
+
if (!filename || filename !== path.basename(filename))
|
|
88
|
+
throw new InstallerError('APP_INVALID', 'npm pack returned no application tarball.');
|
|
89
|
+
extract({
|
|
90
|
+
file: path.join(temporary, filename),
|
|
91
|
+
cwd: temporary,
|
|
92
|
+
strip: 1,
|
|
93
|
+
strict: true,
|
|
94
|
+
sync: true,
|
|
95
|
+
});
|
|
96
|
+
const manifest = JSON.parse(await readFile(path.join(temporary, 'package.json'), 'utf8'));
|
|
97
|
+
if (manifest.name !== app.package ||
|
|
98
|
+
manifest.version !== app.selector ||
|
|
99
|
+
manifest.nocobase?.templateKind !== 'app' ||
|
|
100
|
+
!manifest.scripts?.build) {
|
|
101
|
+
throw new InstallerError('APP_INVALID', `${app.package}@${app.selector} is not a buildable NocoBase application package.`, { exitCode: EXIT_INVALID });
|
|
102
|
+
}
|
|
103
|
+
const workspaceFile = path.join(temporary, 'pnpm-workspace.yaml');
|
|
104
|
+
const existing = await readFile(workspaceFile, 'utf8').catch((error) => {
|
|
105
|
+
if (error.code === 'ENOENT')
|
|
106
|
+
return '';
|
|
107
|
+
throw error;
|
|
108
|
+
});
|
|
109
|
+
const workspace = (parse(existing) ?? {});
|
|
110
|
+
await writeFile(workspaceFile, stringify({
|
|
111
|
+
verifyDepsBeforeRun: false,
|
|
112
|
+
strictDepBuilds: false,
|
|
113
|
+
...workspace,
|
|
114
|
+
allowBuilds: {
|
|
115
|
+
esbuild: true,
|
|
116
|
+
oracledb: true,
|
|
117
|
+
'better-sqlite3': false,
|
|
118
|
+
'tesseract.js': false,
|
|
119
|
+
...workspace.allowBuilds,
|
|
120
|
+
},
|
|
121
|
+
}));
|
|
122
|
+
const npmrc = path.join(temporary, '.npmrc');
|
|
123
|
+
await writeFile(npmrc, `\nregistry=${registry}\n@nocobase:registry=${registry}\n${app.package.split('/')[0]}:registry=${registry}\n`, { flag: 'a' });
|
|
124
|
+
reporter.progress(`Installing build dependencies for ${app.package}@${app.selector}`);
|
|
125
|
+
await run('pnpm', [
|
|
126
|
+
'install',
|
|
127
|
+
'--no-frozen-lockfile',
|
|
128
|
+
'--prod=false',
|
|
129
|
+
'--config.strict-peer-dependencies=false',
|
|
130
|
+
`--registry=${registry}`,
|
|
131
|
+
], { cwd: temporary, env, timeoutMs: 20 * 60_000 });
|
|
132
|
+
reporter.progress(`Building ${app.package}@${app.selector} for this server`);
|
|
133
|
+
await run('pnpm', ['build', '--tar'], {
|
|
134
|
+
cwd: temporary,
|
|
135
|
+
env,
|
|
136
|
+
timeoutMs: 30 * 60_000,
|
|
137
|
+
});
|
|
138
|
+
const prepared = await unpackRelease({
|
|
139
|
+
layout,
|
|
140
|
+
archive: path.join(temporary, 'storage/exports/dist.tar.gz'),
|
|
141
|
+
});
|
|
142
|
+
if (prepared.appName !== app.package || prepared.version !== app.selector) {
|
|
143
|
+
if (!prepared.reused)
|
|
144
|
+
await rm(path.dirname(prepared.dir), { recursive: true, force: true });
|
|
145
|
+
throw new InstallerError('APP_INVALID', 'The build changed the published application name or version.');
|
|
146
|
+
}
|
|
147
|
+
return prepared;
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
if (isInstallerError(error))
|
|
151
|
+
throw error;
|
|
152
|
+
throw new InstallerError('APP_BUILD_FAILED', `Building ${app.package}@${app.selector} failed: ${error instanceof Error ? error.message : String(error)}`, {
|
|
153
|
+
cause: error,
|
|
154
|
+
...(error instanceof CommandFailedError
|
|
155
|
+
? { details: { output: tail(`${error.stdout}\n${error.stderr}`) } }
|
|
156
|
+
: {}),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
await rm(temporary, { recursive: true, force: true });
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=app-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-source.js","sourceRoot":"","sources":["../../src/lib/app-source.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/ecosystem.js
CHANGED
|
@@ -30,11 +30,7 @@ module.exports = {
|
|
|
30
30
|
max_restarts: 10,
|
|
31
31
|
exp_backoff_restart_delay: 1000,
|
|
32
32
|
// pm2 sends SIGKILL 1.6s after SIGINT by default; the application finishes what it is doing first.
|
|
33
|
-
kill_timeout: 60000
|
|
34
|
-
? `
|
|
35
|
-
// The Hub stops its App Host child itself, and the child exits on its own if the Hub is killed.
|
|
36
|
-
treekill: false,`
|
|
37
|
-
: ''}
|
|
33
|
+
kill_timeout: 60000,
|
|
38
34
|
out_file: path.join(root, 'logs/app.out.log'),
|
|
39
35
|
error_file: path.join(root, 'logs/app.err.log'),
|
|
40
36
|
time: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ecosystem.js","sourceRoot":"","sources":["../../src/lib/ecosystem.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ecosystem.js","sourceRoot":"","sources":["../../src/lib/ecosystem.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAyB;IAC5D,OAAO;;;;;;;;cAQK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;;gBAE1B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC;;;;;;;;;;;;;;;;;CAiB/C,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO;;;;;;;;;;;;;;;;;;;;CAoBR,CAAC;AACF,CAAC"}
|
package/dist/lib/layout.js
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
/** The directory inside `releases/<id>/` holding a release's deployment root: `dist/` and `config.example.yml`. */
|
|
3
3
|
export const RELEASE_APP_DIR = 'app';
|
|
4
|
-
export const HUB_TEMPLATE = {
|
|
5
|
-
name: 'hub',
|
|
6
|
-
title: 'Hub',
|
|
7
|
-
package: '@nocobase/app-template-hub',
|
|
8
|
-
projectName: 'hub',
|
|
9
|
-
basePath: '/hub',
|
|
10
|
-
};
|
|
11
|
-
export const TEMPLATES = [HUB_TEMPLATE];
|
|
12
4
|
export function layoutOf(root) {
|
|
13
5
|
return {
|
|
14
6
|
root,
|
|
@@ -19,7 +11,6 @@ export function layoutOf(root) {
|
|
|
19
11
|
outLog: path.join(root, 'logs/app.out.log'),
|
|
20
12
|
errorLog: path.join(root, 'logs/app.err.log'),
|
|
21
13
|
releasesDir: path.join(root, 'releases'),
|
|
22
|
-
buildDir: path.join(root, '.build'),
|
|
23
14
|
backupsDir: path.join(root, 'backups'),
|
|
24
15
|
current: path.join(root, 'current'),
|
|
25
16
|
stateFile: path.join(root, 'installer.json'),
|
|
@@ -50,10 +41,6 @@ export function releaseDir(layout, id) {
|
|
|
50
41
|
export function releaseLinkTarget(id) {
|
|
51
42
|
return path.join('releases', id, RELEASE_APP_DIR);
|
|
52
43
|
}
|
|
53
|
-
/** Where a template build runs, one directory per version. */
|
|
54
|
-
export function buildRoot(layout, version) {
|
|
55
|
-
return path.join(layout.buildDir, version);
|
|
56
|
-
}
|
|
57
44
|
/** Where an archive is unpacked before its manifest names the release it is. */
|
|
58
45
|
export function stagingDir(layout) {
|
|
59
46
|
return path.join(layout.releasesDir, `.staging-${process.pid}`);
|
package/dist/lib/layout.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/lib/layout.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,mHAAmH;AACnH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/lib/layout.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,mHAAmH;AACnH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAuBrC,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO;QACL,IAAI;QACJ,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QAClC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;QACzC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QACtC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;QAChC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC;QAC3C,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC;QAC7C,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC;QACxC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QACtC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QACnC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC;QAC5C,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC;QAC5C,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC;QACtD,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC;KAC9C,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,OAAe;IACxD,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC;SAC9B,WAAW,EAAE;SACb,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC;SACnB,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACvB,OAAO,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;AACjC,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,EAAU;IACnD,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,EAAE,eAAe,CAAC,CAAC;AAC5D,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,eAAe,CAAC,CAAC;AACpD,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AAClE,CAAC"}
|
package/dist/lib/prechecks.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { readdir } from 'node:fs/promises';
|
|
2
2
|
import { createServer } from 'node:net';
|
|
3
|
-
import { EXIT_INVALID, InstallerError
|
|
4
|
-
import { runCommand } from "./run-command.js";
|
|
3
|
+
import { EXIT_INVALID, InstallerError } from "./errors.js";
|
|
5
4
|
import { compareVersions } from "./version.js";
|
|
6
5
|
export const MINIMUM_NODE_MAJOR = 24;
|
|
7
|
-
export const MINIMUM_PNPM_MAJOR = 11;
|
|
8
6
|
/**
|
|
9
7
|
* pm2 recognises `ecosystem.config.cjs` as a configuration from 4.3 on; an older one runs the file as the application
|
|
10
8
|
* instead, which exits at once and looks like an application that cannot start.
|
|
@@ -25,41 +23,6 @@ export function checkPlatform(platform = process.platform) {
|
|
|
25
23
|
});
|
|
26
24
|
}
|
|
27
25
|
}
|
|
28
|
-
export async function checkPnpm(run = runCommand) {
|
|
29
|
-
let version;
|
|
30
|
-
try {
|
|
31
|
-
version = (await run('pnpm', ['--version'])).stdout.trim();
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
throw new InstallerError('PNPM_MISSING', 'pnpm was not found on PATH.', {
|
|
35
|
-
exitCode: EXIT_INVALID,
|
|
36
|
-
suggestions: installPnpmAdvice(),
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
if (!(majorOf(version) >= MINIMUM_PNPM_MAJOR)) {
|
|
40
|
-
throw new InstallerError('PNPM_UNSUPPORTED', `pnpm ${MINIMUM_PNPM_MAJOR} or later is required; found ${version}.`, {
|
|
41
|
-
exitCode: EXIT_INVALID,
|
|
42
|
-
suggestions: installPnpmAdvice(),
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return version;
|
|
46
|
-
}
|
|
47
|
-
/** Two steps, since a suggestion runs one command: corepack is enabled, then pnpm is activated through it. */
|
|
48
|
-
function installPnpmAdvice() {
|
|
49
|
-
return [
|
|
50
|
-
{
|
|
51
|
-
message: `Enable corepack, which provides pnpm ${MINIMUM_PNPM_MAJOR}:`,
|
|
52
|
-
run: { command: 'corepack', args: ['enable'] },
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
message: `Then activate pnpm ${MINIMUM_PNPM_MAJOR}, and open a new shell:`,
|
|
56
|
-
run: {
|
|
57
|
-
command: 'corepack',
|
|
58
|
-
args: ['prepare', `pnpm@${MINIMUM_PNPM_MAJOR}`, '--activate'],
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
];
|
|
62
|
-
}
|
|
63
26
|
/** The C library Node runs on, which a Linux build's native modules are compiled against. */
|
|
64
27
|
export function currentLibc() {
|
|
65
28
|
if (process.platform !== 'linux')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prechecks.js","sourceRoot":"","sources":["../../src/lib/prechecks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,
|
|
1
|
+
{"version":3,"file":"prechecks.js","sourceRoot":"","sources":["../../src/lib/prechecks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAoB,MAAM,aAAa,CAAC;AAE7E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AACrC;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC;AAE3C,MAAM,UAAU,OAAO,CAAC,OAAe;IACrC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAChD,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,WAA4B,OAAO,CAAC,QAAQ;IAE5C,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,IAAI,cAAc,CACtB,sBAAsB,EACtB,wGAAwG,EACxG;YACE,QAAQ,EAAE,YAAY;YACtB,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC;SACzD,CACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,WAAW;IACzB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IACnD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,EAEtC,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,GAAG,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACzF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,OAAO,EAAE,MAAM;QACf,IAAI,EAAE;YACJ,OAAO;YACP,UAAU;YACV,kBAAkB,EAAE;YACpB,gBAAgB;YAChB,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAC1B,OAAO;SACR;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAQ;IACrC,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,cAAc,CAAC,aAAa,EAAE,4BAA4B,EAAE;YACpE,QAAQ,EAAE,YAAY;YACtB,WAAW,EAAE;gBACX;oBACE,OAAO,EAAE,uBAAuB;oBAChC,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE;iBACxD;gBACD;oBACE,OAAO,EACL,+DAA+D;iBAClE;aACF;SACF,CAAC,CAAC;IACL,CAAC;IACD,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IACjE,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,cAAc,CACtB,iBAAiB,EACjB,UAAU,KAAK,SAAS;YACtB,CAAC,CAAC,OAAO,mBAAmB,yDAAyD,OAAO,4BAA4B;YACxH,CAAC,CAAC,OAAO,mBAAmB,gCAAgC,OAAO,GAAG,EACxE;YACE,QAAQ,EAAE,YAAY;YACtB,WAAW,EAAE;gBACX;oBACE,OAAO,EAAE,sBAAsB;oBAC/B,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,YAAY,CAAC,EAAE;iBAC/D;gBACD;oBACE,OAAO,EAAE,mDAAmD;oBAC5D,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE;iBAC1C;aACF;SACF,CACF,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAQ,EAAE,IAAY;IAC3D,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,IAAI,cAAc,CACtB,iBAAiB,EACjB,oCAAoC,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EACzF;YACE,QAAQ,EAAE,YAAY;YACtB,WAAW,EAAE;gBACX;oBACE,OAAO,EAAE,2EAA2E,IAAI,KAAK;iBAC9F;aACF;SACF,CACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAChB,IAAY,EACZ,IAAY;IAEZ,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAA4B,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACvE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACL,CAAC;AAED,qHAAqH;AACrH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAY,EACZ,KAAa,EACb,WAAmB,EAAE;IAErB,KACE,IAAI,IAAI,GAAG,KAAK,GAAG,CAAC,EACpB,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,QAAQ,EAAE,KAAK,CAAC,EACzC,IAAI,IAAI,CAAC,EACT,CAAC;QACD,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IAClD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,IAAY,EACZ,UAAqC,EAAE;IAEvC,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,MAAM,IAAI,GACR,OAAO,CAAC,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;QAChD,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC;QAChC,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,IAAI,cAAc,CACtB,aAAa,EACb,KAAK,CAAC,IAAI,KAAK,YAAY;QACzB,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,qBAAqB;QACtC,CAAC,CAAC,oBAAoB,IAAI,IAAI,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,EACxD;QACE,QAAQ,EAAE,YAAY;QACtB,OAAO,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC5D,WAAW,EAAE;YACX,OAAO,CAAC,WAAW;gBACjB,CAAC,CAAC;oBACE,OAAO,EACL,IAAI,KAAK,SAAS;wBAChB,CAAC,CAAC,kCAAkC;wBACpC,CAAC,CAAC,QAAQ,IAAI,yBAAyB,IAAI,sCAAsC;iBACtF;gBACH,CAAC,CAAC,EAAE,OAAO,EAAE,gDAAgD,EAAE;SAClE;KACF,CACF,CAAC;AACJ,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,iBAAiB,CAC/B,SAA4B,EAC5B,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC;IACpE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,cAAc,CACtB,aAAa,EACb,wBAAwB,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,oBAAoB,aAAa,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAC5H,EAAE,QAAQ,EAAE,YAAY,EAAE,CAC3B,CAAC;IACJ,CAAC;AACH,CAAC;AAED,8FAA8F;AAC9F,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY;IACjD,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;QACnD,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACpC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,IAAI,cAAc,CAAC,kBAAkB,EAAE,GAAG,IAAI,aAAa,EAAE;gBACjE,QAAQ,EAAE,YAAY;gBACtB,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,wCAAwC,EAAE,CAAC;aACrE,CAAC,CAAC;QACL,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,cAAc,CAAC,kBAAkB,EAAE,GAAG,IAAI,gBAAgB,EAAE;YACpE,QAAQ,EAAE,YAAY;YACtB,WAAW,EAAE;gBACX,EAAE,OAAO,EAAE,wCAAwC,EAAE;gBACrD;oBACE,OAAO,EACL,wGAAwG;iBAC3G;aACF;SACF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/lib/registry.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { EXIT_INVALID, InstallerError } from "./errors.js";
|
|
2
1
|
/** The public npm registry is the default; `--registry` and `NOCOBASE_REGISTRY` may select a private registry. */
|
|
3
2
|
export const FALLBACK_REGISTRY = 'https://registry.npmjs.org';
|
|
4
3
|
export function defaultRegistry(env = process.env) {
|
|
@@ -7,53 +6,4 @@ export function defaultRegistry(env = process.env) {
|
|
|
7
6
|
export function normalizeRegistry(registry) {
|
|
8
7
|
return registry.replace(/\/+$/u, '');
|
|
9
8
|
}
|
|
10
|
-
/**
|
|
11
|
-
* Resolves a dist-tag such as `latest`, or checks an exact version, against the registry. Every later step uses the
|
|
12
|
-
* exact version, so `latest` moving halfway through an install cannot mix two releases.
|
|
13
|
-
*/
|
|
14
|
-
export async function resolveTemplateVersion(registry, packageName, requested, fetchImpl = fetch) {
|
|
15
|
-
const url = `${normalizeRegistry(registry)}/${packageName.replace('/', '%2f')}`;
|
|
16
|
-
let packument;
|
|
17
|
-
try {
|
|
18
|
-
const response = await fetchImpl(url, {
|
|
19
|
-
headers: { accept: 'application/vnd.npm.install-v1+json' },
|
|
20
|
-
signal: AbortSignal.timeout(30_000),
|
|
21
|
-
});
|
|
22
|
-
if (!response.ok) {
|
|
23
|
-
throw new Error(`HTTP ${response.status}`);
|
|
24
|
-
}
|
|
25
|
-
packument = (await response.json());
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
throw new InstallerError('REGISTRY_UNREACHABLE', `Could not read ${packageName} from ${normalizeRegistry(registry)}: ${error instanceof Error ? error.message : String(error)}.`, {
|
|
29
|
-
exitCode: EXIT_INVALID,
|
|
30
|
-
cause: error,
|
|
31
|
-
suggestions: [
|
|
32
|
-
{
|
|
33
|
-
message: 'Check the network, or name another registry with --registry.',
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
// `hasOwn`, not a plain lookup: `constructor` and friends are on every parsed object's prototype.
|
|
39
|
-
const tags = packument['dist-tags'] ?? {};
|
|
40
|
-
if (Object.hasOwn(tags, requested))
|
|
41
|
-
return tags[requested];
|
|
42
|
-
if (packument.versions && Object.hasOwn(packument.versions, requested)) {
|
|
43
|
-
return requested;
|
|
44
|
-
}
|
|
45
|
-
const recent = Object.keys(packument.versions ?? {}).slice(-5);
|
|
46
|
-
throw new InstallerError('VERSION_NOT_FOUND', `${packageName} has no version or tag "${requested}".`, {
|
|
47
|
-
exitCode: EXIT_INVALID,
|
|
48
|
-
details: {
|
|
49
|
-
distTags: packument['dist-tags'] ?? {},
|
|
50
|
-
recentVersions: recent,
|
|
51
|
-
},
|
|
52
|
-
suggestions: [
|
|
53
|
-
{
|
|
54
|
-
message: `Use a tag (${Object.keys(packument['dist-tags'] ?? {}).join(', ') || 'none'}) or one of the recent versions: ${recent.join(', ') || 'none'}.`,
|
|
55
|
-
},
|
|
56
|
-
],
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
9
|
//# sourceMappingURL=registry.js.map
|
package/dist/lib/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/lib/registry.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/lib/registry.ts"],"names":[],"mappings":"AAAA,kHAAkH;AAClH,MAAM,CAAC,MAAM,iBAAiB,GAAG,4BAA4B,CAAC;AAE9D,MAAM,UAAU,eAAe,CAAC,MAAyB,OAAO,CAAC,GAAG;IAClE,OAAO,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,IAAI,iBAAiB,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,OAAO,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC"}
|
package/dist/lib/release.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
-
import { mkdir, readFile, rename, rm
|
|
2
|
+
import { mkdir, readFile, rename, rm } from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { extract } from 'tar';
|
|
5
5
|
import { EXIT_INVALID, InstallerError, isInstallerError } from "./errors.js";
|
|
6
|
-
import { RELEASE_APP_DIR,
|
|
6
|
+
import { RELEASE_APP_DIR, releaseDir, releaseId, stagingDir, } from "./layout.js";
|
|
7
7
|
import { currentNodeMajor, rebuildCommandLine } from "./prechecks.js";
|
|
8
|
-
import {
|
|
9
|
-
import { CommandFailedError, runCommand, tail, } from "./run-command.js";
|
|
8
|
+
import { CommandFailedError, tail } from "./run-command.js";
|
|
10
9
|
/** Every official database dialect; each has its driver in `@nocobase/db-<dialect>`. */
|
|
11
10
|
export const DIALECTS = [
|
|
12
11
|
'sqlite',
|
|
@@ -18,60 +17,6 @@ export const DIALECTS = [
|
|
|
18
17
|
'kingbase',
|
|
19
18
|
'oceanbase',
|
|
20
19
|
];
|
|
21
|
-
/** SQLite ships with every template; any other dialect's driver has to be added before the build. */
|
|
22
|
-
export function driversFor(dialect) {
|
|
23
|
-
return dialect === 'sqlite' ? [] : [`@nocobase/db-${dialect}`];
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* The environment every install step runs with. pnpm 11 holds back versions younger than a day by default, which would
|
|
27
|
-
* make a template released today uninstallable until tomorrow; the NocoBase documentation clears it the same way.
|
|
28
|
-
*/
|
|
29
|
-
export function installEnv(base = process.env) {
|
|
30
|
-
return { ...base, PNPM_CONFIG_MINIMUM_RELEASE_AGE: '0' };
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* `pnpm create` prints pnpm's own notices around create-app's result; the result is the last line that parses. It is
|
|
34
|
-
* the application CLI's envelope, with the stage under `error.details`. `pnpm create` runs whichever create-app the
|
|
35
|
-
* registry serves as latest, so the flat `status`, `stage` and `message` a create-app before that envelope printed are
|
|
36
|
-
* read too.
|
|
37
|
-
*/
|
|
38
|
-
export function parseCreateResult(stdout) {
|
|
39
|
-
for (const line of stdout.trim().split('\n').reverse()) {
|
|
40
|
-
if (!line.startsWith('{'))
|
|
41
|
-
continue;
|
|
42
|
-
let parsed;
|
|
43
|
-
try {
|
|
44
|
-
parsed = JSON.parse(line);
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
const stage = parsed.error?.details?.stage;
|
|
50
|
-
return {
|
|
51
|
-
ok: parsed.ok ?? parsed.status === 'success',
|
|
52
|
-
stage: typeof stage === 'string' ? stage : parsed.stage,
|
|
53
|
-
message: parsed.error?.message ?? parsed.message,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
return { ok: false };
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* The range the installed runtime accepts for a driver, read from `@nocobase/app-server`'s peer dependencies the same
|
|
60
|
-
* way `nocobase config init` suggests it. A bare `pnpm add` would take the newest driver, which during a prerelease can
|
|
61
|
-
* be one the runtime was never built against.
|
|
62
|
-
*/
|
|
63
|
-
export async function driverSpecifier(projectDir, driver) {
|
|
64
|
-
try {
|
|
65
|
-
const manifest = JSON.parse(await readFile(path.join(projectDir, 'node_modules/@nocobase/app-server/package.json'), 'utf8'));
|
|
66
|
-
const range = manifest.peerDependencies?.[driver]?.trim();
|
|
67
|
-
return range && !range.startsWith('workspace:')
|
|
68
|
-
? `${driver}@${range}`
|
|
69
|
-
: driver;
|
|
70
|
-
}
|
|
71
|
-
catch {
|
|
72
|
-
return driver;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
20
|
export function verifyBuildTarget(target, expected = {
|
|
76
21
|
platform: process.platform,
|
|
77
22
|
arch: process.arch,
|
|
@@ -106,7 +51,6 @@ function stepFailure(code, step, error) {
|
|
|
106
51
|
export async function unpackRelease(options) {
|
|
107
52
|
const staging = stagingDir(options.layout);
|
|
108
53
|
const stagedApp = path.join(staging, RELEASE_APP_DIR);
|
|
109
|
-
const fromArchive = options.fallback === undefined;
|
|
110
54
|
await rm(staging, { recursive: true, force: true });
|
|
111
55
|
try {
|
|
112
56
|
await mkdir(stagedApp, { recursive: true });
|
|
@@ -135,7 +79,7 @@ export async function unpackRelease(options) {
|
|
|
135
79
|
buildTarget = verifyBuildTarget(manifest.nocobase?.buildTarget);
|
|
136
80
|
}
|
|
137
81
|
catch (error) {
|
|
138
|
-
if (!
|
|
82
|
+
if (!isInstallerError(error))
|
|
139
83
|
throw error;
|
|
140
84
|
throw new InstallerError(error.code, error.message, {
|
|
141
85
|
exitCode: EXIT_INVALID,
|
|
@@ -148,11 +92,9 @@ export async function unpackRelease(options) {
|
|
|
148
92
|
});
|
|
149
93
|
}
|
|
150
94
|
const version = manifest.version ?? '0.0.0';
|
|
151
|
-
const builtAt = manifest.nocobase?.builtAt
|
|
95
|
+
const builtAt = manifest.nocobase?.builtAt;
|
|
152
96
|
const relocatable = manifest.nocobase?.relocatable === true;
|
|
153
|
-
const basePath = relocatable
|
|
154
|
-
? undefined
|
|
155
|
-
: (manifest.nocobase?.basePath ?? options.fallback?.basePath);
|
|
97
|
+
const basePath = relocatable ? undefined : manifest.nocobase?.basePath;
|
|
156
98
|
if (!builtAt || (!relocatable && !basePath) || !manifest.name) {
|
|
157
99
|
throw new InstallerError('ARCHIVE_TOO_OLD', `${options.archive} does not record where its client can be mounted and when it was built; it comes from a \`pnpm build\` older than app-installer needs.`, {
|
|
158
100
|
exitCode: EXIT_INVALID,
|
|
@@ -180,7 +122,6 @@ export async function unpackRelease(options) {
|
|
|
180
122
|
relocatable,
|
|
181
123
|
...(basePath === undefined ? {} : { basePath }),
|
|
182
124
|
buildTarget,
|
|
183
|
-
templateKind: manifest.nocobase?.templateKind,
|
|
184
125
|
reused,
|
|
185
126
|
};
|
|
186
127
|
}
|
|
@@ -188,102 +129,6 @@ export async function unpackRelease(options) {
|
|
|
188
129
|
await rm(staging, { recursive: true, force: true });
|
|
189
130
|
}
|
|
190
131
|
}
|
|
191
|
-
/**
|
|
192
|
-
* Builds one release from a published template: the project is generated and built in `.build/<version>/`, and only
|
|
193
|
-
* the deployment archive it produces is unpacked into `releases/<id>/app`. The build directory, with the sources and
|
|
194
|
-
* development dependencies, is removed afterwards unless `keepSource` is set. Nothing here touches the running
|
|
195
|
-
* application; on failure every directory this call created is removed again, so a retry starts clean.
|
|
196
|
-
*/
|
|
197
|
-
export async function buildFromTemplate(options) {
|
|
198
|
-
const { layout, template, version, reporter } = options;
|
|
199
|
-
const run = options.run ?? runCommand;
|
|
200
|
-
const build = buildRoot(layout, version);
|
|
201
|
-
const projectDir = path.join(build, template.projectName);
|
|
202
|
-
const env = installEnv();
|
|
203
|
-
const startedAt = new Date().toISOString();
|
|
204
|
-
try {
|
|
205
|
-
await rm(build, { recursive: true, force: true });
|
|
206
|
-
await mkdir(build, { recursive: true });
|
|
207
|
-
// `pnpm create` looks up @nocobase/create-app with the configuration of the directory it runs in, not with
|
|
208
|
-
// --registry, so the registry has to be named here too while NocoBase packages live outside the public npm.
|
|
209
|
-
await writeFile(path.join(build, '.npmrc'), `@nocobase:registry=${normalizeRegistry(options.registry)}/\n`);
|
|
210
|
-
reporter.progress(`Generating the ${template.title} ${version} project`);
|
|
211
|
-
let createStdout;
|
|
212
|
-
try {
|
|
213
|
-
({ stdout: createStdout } = await run('pnpm', [
|
|
214
|
-
'create',
|
|
215
|
-
'@nocobase/app',
|
|
216
|
-
template.projectName,
|
|
217
|
-
`--template=${template.package}@${version}`,
|
|
218
|
-
`--registry=${normalizeRegistry(options.registry)}`,
|
|
219
|
-
'--json',
|
|
220
|
-
], { cwd: build, env, timeoutMs: 20 * 60_000 }));
|
|
221
|
-
}
|
|
222
|
-
catch (error) {
|
|
223
|
-
if (isInstallerError(error))
|
|
224
|
-
throw error;
|
|
225
|
-
const result = error instanceof CommandFailedError
|
|
226
|
-
? parseCreateResult(error.stdout)
|
|
227
|
-
: { ok: false };
|
|
228
|
-
throw new InstallerError('CREATE_FAILED', `create-app failed${result.stage ? ` at its ${result.stage} stage` : ''}: ${result.message ?? (error instanceof Error ? error.message : String(error))}`, {
|
|
229
|
-
cause: error,
|
|
230
|
-
...(error instanceof CommandFailedError
|
|
231
|
-
? { details: { output: tail(error.stderr) } }
|
|
232
|
-
: {}),
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
const created = parseCreateResult(createStdout);
|
|
236
|
-
if (!created.ok) {
|
|
237
|
-
throw new InstallerError('CREATE_FAILED', `create-app did not succeed: ${created.message ?? 'no result'}`);
|
|
238
|
-
}
|
|
239
|
-
for (const driver of options.drivers) {
|
|
240
|
-
const specifier = await driverSpecifier(projectDir, driver);
|
|
241
|
-
reporter.progress(`Adding ${specifier}`);
|
|
242
|
-
try {
|
|
243
|
-
await run('pnpm', ['add', specifier], {
|
|
244
|
-
cwd: projectDir,
|
|
245
|
-
env,
|
|
246
|
-
timeoutMs: 10 * 60_000,
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
catch (error) {
|
|
250
|
-
throw stepFailure('DRIVER_INSTALL_FAILED', `pnpm add ${specifier}`, error);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
reporter.progress(`Building the ${template.title} ${version}`);
|
|
254
|
-
try {
|
|
255
|
-
// A template version from before relocatable builds compiles the base path into its client, so an APP_BASE_PATH
|
|
256
|
-
// left in the caller's shell must not leak in. A current version ignores it.
|
|
257
|
-
await run('pnpm', ['build', '--tar'], {
|
|
258
|
-
cwd: projectDir,
|
|
259
|
-
env: { ...env, APP_BASE_PATH: template.basePath },
|
|
260
|
-
timeoutMs: 30 * 60_000,
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
catch (error) {
|
|
264
|
-
throw stepFailure('BUILD_FAILED', 'pnpm build', error);
|
|
265
|
-
}
|
|
266
|
-
const prepared = await unpackRelease({
|
|
267
|
-
layout,
|
|
268
|
-
archive: path.join(projectDir, 'storage/exports/dist.tar.gz'),
|
|
269
|
-
// Published templates built before `pnpm build` recorded these have neither; the installer knows both.
|
|
270
|
-
fallback: { builtAt: startedAt, basePath: template.basePath },
|
|
271
|
-
});
|
|
272
|
-
if (!options.keepSource) {
|
|
273
|
-
await rm(build, { recursive: true, force: true });
|
|
274
|
-
// Only removes `.build/` once it is empty; another version's kept build stays.
|
|
275
|
-
await rmdir(layout.buildDir).catch(() => undefined);
|
|
276
|
-
}
|
|
277
|
-
return prepared;
|
|
278
|
-
}
|
|
279
|
-
catch (error) {
|
|
280
|
-
if (!options.keepSource) {
|
|
281
|
-
await rm(build, { recursive: true, force: true });
|
|
282
|
-
await rmdir(layout.buildDir).catch(() => undefined);
|
|
283
|
-
}
|
|
284
|
-
throw error;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
132
|
/**
|
|
288
133
|
* A deployment archive carries its database drivers in `dist/node_modules`, installed when it was built; nothing adds
|
|
289
134
|
* one afterwards. A dialect whose driver is absent would fail only when the application first connects.
|