onework 0.1.0-alpha.2 → 0.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/cli.spec.ts +57 -0
- package/__tests__/runtime-package.spec.ts +51 -2
- package/package.json +3 -3
- package/src/npm-package-cache.ts +34 -2
- package/src/npm-package-install.ts +23 -6
- package/src/program.ts +35 -4
- package/src/runtime-package.ts +42 -10
package/__tests__/cli.spec.ts
CHANGED
|
@@ -69,6 +69,23 @@ describe('bootstrap cli', () => {
|
|
|
69
69
|
})
|
|
70
70
|
})
|
|
71
71
|
|
|
72
|
+
it('routes runtime package cache versions from flags', () => {
|
|
73
|
+
expect(routeBootstrapCommand('runtime', [
|
|
74
|
+
'install',
|
|
75
|
+
'server',
|
|
76
|
+
'--version=2.3.4',
|
|
77
|
+
'--cache-version',
|
|
78
|
+
'dev-local'
|
|
79
|
+
])).toEqual({
|
|
80
|
+
action: 'install',
|
|
81
|
+
cacheVersion: 'dev-local',
|
|
82
|
+
json: false,
|
|
83
|
+
kind: 'runtime-package',
|
|
84
|
+
target: 'server',
|
|
85
|
+
version: '2.3.4'
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
72
89
|
it('routes unknown commands through the CLI package', () => {
|
|
73
90
|
expect(routeBootstrapCommand('hello', [])).toEqual({
|
|
74
91
|
commandName: 'oneworks',
|
|
@@ -197,6 +214,46 @@ describe('bootstrap cli', () => {
|
|
|
197
214
|
expect(writeSpy).toHaveBeenCalledWith(expect.stringContaining('"requestedVersion":"1.2.3"'))
|
|
198
215
|
})
|
|
199
216
|
|
|
217
|
+
it('dispatches runtime package installation with a cache version', async () => {
|
|
218
|
+
const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true)
|
|
219
|
+
const installRuntimePackage = vi.fn(async () => ({
|
|
220
|
+
cacheVersion: 'dev-local',
|
|
221
|
+
installed: true,
|
|
222
|
+
installedVersion: '1.2.3',
|
|
223
|
+
latestInstalled: true,
|
|
224
|
+
latestVersion: '1.2.3',
|
|
225
|
+
packageName: '@oneworks/server',
|
|
226
|
+
requestedVersion: '1.2.3',
|
|
227
|
+
target: 'server' as const,
|
|
228
|
+
updateAvailable: false
|
|
229
|
+
}))
|
|
230
|
+
const cli = createBootstrapCli({
|
|
231
|
+
checkRuntimePackage: vi.fn(async () => {
|
|
232
|
+
throw new Error('unexpected check')
|
|
233
|
+
}),
|
|
234
|
+
installRuntimePackage,
|
|
235
|
+
launchDesktopApp: vi.fn(async () => {}),
|
|
236
|
+
launchInstalledPackage: vi.fn(async () => 0)
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
await cli.parseAsync([
|
|
240
|
+
'node',
|
|
241
|
+
'oneworks',
|
|
242
|
+
'runtime',
|
|
243
|
+
'install',
|
|
244
|
+
'server',
|
|
245
|
+
'--version=1.2.3',
|
|
246
|
+
'--cache-version=dev-local',
|
|
247
|
+
'--json'
|
|
248
|
+
])
|
|
249
|
+
|
|
250
|
+
expect(installRuntimePackage).toHaveBeenCalledWith('server', {
|
|
251
|
+
cacheVersion: 'dev-local',
|
|
252
|
+
version: '1.2.3'
|
|
253
|
+
})
|
|
254
|
+
expect(writeSpy).toHaveBeenCalledWith(expect.stringContaining('"cacheVersion":"dev-local"'))
|
|
255
|
+
})
|
|
256
|
+
|
|
200
257
|
it('forwards --help after a routed command', async () => {
|
|
201
258
|
const launchDesktopApp = vi.fn(async () => {})
|
|
202
259
|
const launchInstalledPackage = vi.fn(async () => 0)
|
|
@@ -26,13 +26,13 @@ describe('bootstrap runtime package commands', () => {
|
|
|
26
26
|
await rm(tempDir, { force: true, recursive: true })
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
const writeCachedPackage = async (packageName: string, version: string) => {
|
|
29
|
+
const writeCachedPackage = async (packageName: string, version: string, cacheVersion = version) => {
|
|
30
30
|
const sanitizedName = packageName.replace(/^@/, '').replace(/[\\/]/g, '__')
|
|
31
31
|
const packageDir = path.join(
|
|
32
32
|
tempDir,
|
|
33
33
|
'.oneworks/bootstrap/npm',
|
|
34
34
|
sanitizedName,
|
|
35
|
-
|
|
35
|
+
cacheVersion,
|
|
36
36
|
'node_modules',
|
|
37
37
|
...packageName.split('/')
|
|
38
38
|
)
|
|
@@ -190,6 +190,49 @@ process.exit(1)
|
|
|
190
190
|
).resolves.toBeUndefined()
|
|
191
191
|
})
|
|
192
192
|
|
|
193
|
+
it('installs a runtime package under an explicit cache version', async () => {
|
|
194
|
+
vi.stubEnv('ONEWORKS_TEST_NPM_VERSION', '9.9.9')
|
|
195
|
+
|
|
196
|
+
await expect(installRuntimePackage('server', {
|
|
197
|
+
cacheVersion: 'dev-local',
|
|
198
|
+
version: '2.2.0'
|
|
199
|
+
})).resolves.toMatchObject({
|
|
200
|
+
cacheVersion: 'dev-local',
|
|
201
|
+
installedVersion: '2.2.0',
|
|
202
|
+
latestInstalled: true,
|
|
203
|
+
latestVersion: '2.2.0',
|
|
204
|
+
packageName: '@oneworks/server',
|
|
205
|
+
requestedVersion: '2.2.0',
|
|
206
|
+
target: 'server',
|
|
207
|
+
updateAvailable: false
|
|
208
|
+
})
|
|
209
|
+
await expect(
|
|
210
|
+
writeFile(
|
|
211
|
+
path.join(
|
|
212
|
+
tempDir,
|
|
213
|
+
'.oneworks/bootstrap/npm/oneworks__server/dev-local/node_modules/@oneworks/server/probe'
|
|
214
|
+
),
|
|
215
|
+
'ok'
|
|
216
|
+
)
|
|
217
|
+
).resolves.toBeUndefined()
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
it('uses the runtime package cache version env for check and install', async () => {
|
|
221
|
+
await writeCachedPackage('@oneworks/server', '2.2.0', 'dev-env')
|
|
222
|
+
vi.stubEnv('ONEWORKS_RUNTIME_PACKAGE_CACHE_VERSION', 'dev-env')
|
|
223
|
+
vi.stubEnv('ONEWORKS_TEST_NPM_VERSION', '2.2.0')
|
|
224
|
+
|
|
225
|
+
await expect(checkRuntimePackage('server')).resolves.toMatchObject({
|
|
226
|
+
cacheVersion: 'dev-env',
|
|
227
|
+
installedVersion: '2.2.0',
|
|
228
|
+
latestInstalled: true,
|
|
229
|
+
latestVersion: '2.2.0',
|
|
230
|
+
packageName: '@oneworks/server',
|
|
231
|
+
target: 'server',
|
|
232
|
+
updateAvailable: false
|
|
233
|
+
})
|
|
234
|
+
})
|
|
235
|
+
|
|
193
236
|
it('installs the latest client runtime package target', async () => {
|
|
194
237
|
vi.stubEnv('ONEWORKS_TEST_NPM_VERSION', '2.2.0')
|
|
195
238
|
|
|
@@ -208,4 +251,10 @@ process.exit(1)
|
|
|
208
251
|
'Runtime package version must be an exact semver version'
|
|
209
252
|
)
|
|
210
253
|
})
|
|
254
|
+
|
|
255
|
+
it('rejects unsafe runtime package cache versions', async () => {
|
|
256
|
+
await expect(checkRuntimePackage('cli', { cacheVersion: '../dev', version: '1.0.0' })).rejects.toThrow(
|
|
257
|
+
'Runtime package cache version contains unsupported characters'
|
|
258
|
+
)
|
|
259
|
+
})
|
|
211
260
|
})
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "onework",
|
|
3
|
-
"version": "0.1.0-
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"description": "One Works bootstrap launcher",
|
|
4
5
|
"repository": {
|
|
5
6
|
"type": "git",
|
|
6
7
|
"url": "https://github.com/oneworks-ai/app.git",
|
|
7
8
|
"directory": "apps/bootstrap"
|
|
8
9
|
},
|
|
9
|
-
"description": "One Works bootstrap launcher",
|
|
10
10
|
"oneworks": {
|
|
11
11
|
"runtimeTranspile": true
|
|
12
12
|
},
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@clack/prompts": "^0.11.0",
|
|
21
21
|
"commander": "^12.1.0",
|
|
22
|
-
"@oneworks/cli-helper": "0.1.0-
|
|
22
|
+
"@oneworks/cli-helper": "0.1.0-beta.0"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"test": "pnpm -C ../.. exec vitest run --workspace vitest.workspace.ts --project node apps/bootstrap/__tests__"
|
package/src/npm-package-cache.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable max-lines -- package cache resolution keeps shared cache lookup and version fallback policy together. */
|
|
1
2
|
import { createHash } from 'node:crypto'
|
|
2
3
|
import { existsSync } from 'node:fs'
|
|
3
4
|
import { access, mkdir, readFile, rename, writeFile } from 'node:fs/promises'
|
|
@@ -9,6 +10,12 @@ import { resolveBootstrapPackageCacheDir, resolveRealHomeDir } from './paths'
|
|
|
9
10
|
const DEFAULT_PACKAGE_TAG = 'latest'
|
|
10
11
|
const DEFAULT_PACKAGE_LOOKUP_TIMEOUT_MS = 1_000
|
|
11
12
|
const DEFAULT_CACHE_FIRST = true
|
|
13
|
+
const PACKAGE_CACHE_VERSION_PATTERN = /^[\w.+-]+$/u
|
|
14
|
+
|
|
15
|
+
export const RUNTIME_PACKAGE_CACHE_VERSION_ENV = '__ONEWORKS_RUNTIME_PACKAGE_CACHE_VERSION__'
|
|
16
|
+
export const PUBLIC_RUNTIME_PACKAGE_CACHE_VERSION_ENV = 'ONEWORKS_RUNTIME_PACKAGE_CACHE_VERSION'
|
|
17
|
+
export const DESKTOP_DEV_RUNTIME_VERSION_ENV = '__ONEWORKS_DESKTOP_DEV_RUNTIME_VERSION__'
|
|
18
|
+
export const PUBLIC_DESKTOP_DEV_RUNTIME_VERSION_ENV = 'ONEWORKS_DESKTOP_DEV_RUNTIME_VERSION'
|
|
12
19
|
|
|
13
20
|
interface PublishedPackageVersionMetadata {
|
|
14
21
|
lookupKey: string
|
|
@@ -58,8 +65,33 @@ export const shouldUseCachedPackageVersionFirst = () => {
|
|
|
58
65
|
return !['0', 'false', 'no', 'off'].includes(rawValue)
|
|
59
66
|
}
|
|
60
67
|
|
|
61
|
-
export const
|
|
62
|
-
|
|
68
|
+
export const normalizePackageCacheVersion = (value: string | undefined) => {
|
|
69
|
+
const normalized = value?.trim()
|
|
70
|
+
if (normalized == null || normalized === '') return undefined
|
|
71
|
+
if (!PACKAGE_CACHE_VERSION_PATTERN.test(normalized) || normalized === '.' || normalized === '..') {
|
|
72
|
+
throw new Error(`Runtime package cache version contains unsupported characters: ${normalized}.`)
|
|
73
|
+
}
|
|
74
|
+
return normalized
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const resolveRuntimePackageCacheVersion = () => (
|
|
78
|
+
normalizePackageCacheVersion(process.env[RUNTIME_PACKAGE_CACHE_VERSION_ENV]) ??
|
|
79
|
+
normalizePackageCacheVersion(process.env[PUBLIC_RUNTIME_PACKAGE_CACHE_VERSION_ENV]) ??
|
|
80
|
+
normalizePackageCacheVersion(process.env[DESKTOP_DEV_RUNTIME_VERSION_ENV]) ??
|
|
81
|
+
normalizePackageCacheVersion(process.env[PUBLIC_DESKTOP_DEV_RUNTIME_VERSION_ENV])
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
export const resolvePackageCacheDir = (
|
|
85
|
+
packageName: string,
|
|
86
|
+
version: string,
|
|
87
|
+
options: { cacheVersion?: string } = {}
|
|
88
|
+
) => (
|
|
89
|
+
path.join(
|
|
90
|
+
resolveBootstrapPackageCacheDir(),
|
|
91
|
+
'npm',
|
|
92
|
+
sanitizePackageName(packageName),
|
|
93
|
+
normalizePackageCacheVersion(options.cacheVersion) ?? version
|
|
94
|
+
)
|
|
63
95
|
)
|
|
64
96
|
|
|
65
97
|
export const resolvePackageCacheRootDir = (packageName: string) => (
|
|
@@ -6,10 +6,12 @@ import {
|
|
|
6
6
|
compareVersionLike,
|
|
7
7
|
ensureDirectory,
|
|
8
8
|
isExistingPath,
|
|
9
|
+
normalizePackageCacheVersion,
|
|
9
10
|
resolvePackageCacheDir,
|
|
10
11
|
resolvePackageCacheRootDir,
|
|
11
12
|
resolvePackageInstallDir,
|
|
12
|
-
resolvePackageManagerEnv
|
|
13
|
+
resolvePackageManagerEnv,
|
|
14
|
+
resolveRuntimePackageCacheVersion
|
|
13
15
|
} from './npm-package-cache'
|
|
14
16
|
import { runBufferedCommand } from './process-utils'
|
|
15
17
|
import { createBootstrapProgress } from './progress'
|
|
@@ -17,6 +19,7 @@ import { createBootstrapProgress } from './progress'
|
|
|
17
19
|
const NPM_BIN = process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
18
20
|
|
|
19
21
|
interface InstalledPackageInfo {
|
|
22
|
+
cacheVersion: string
|
|
20
23
|
packageDir: string
|
|
21
24
|
version: string
|
|
22
25
|
}
|
|
@@ -63,12 +66,19 @@ const formatInstallError = (message: string, stderr: string) => {
|
|
|
63
66
|
return detail ? `${message}\n${detail}` : message
|
|
64
67
|
}
|
|
65
68
|
|
|
66
|
-
export const installPublishedPackage = async (
|
|
67
|
-
|
|
69
|
+
export const installPublishedPackage = async (
|
|
70
|
+
packageName: string,
|
|
71
|
+
version: string,
|
|
72
|
+
options: { cacheVersion?: string } = {}
|
|
73
|
+
): Promise<InstalledPackageInfo> => {
|
|
74
|
+
const cacheVersion = normalizePackageCacheVersion(options.cacheVersion) ??
|
|
75
|
+
resolveRuntimePackageCacheVersion() ??
|
|
76
|
+
version
|
|
77
|
+
const cacheDir = resolvePackageCacheDir(packageName, version, { cacheVersion })
|
|
68
78
|
const packageDir = resolvePackageInstallDir(cacheDir, packageName)
|
|
69
79
|
const installedVersion = await readInstalledPackageVersion(packageDir)
|
|
70
80
|
if (installedVersion === version) {
|
|
71
|
-
return { packageDir, version }
|
|
81
|
+
return { cacheVersion, packageDir, version }
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
const stagingDir = `${cacheDir}.tmp-${process.pid}-${Date.now()}`
|
|
@@ -76,7 +86,9 @@ export const installPublishedPackage = async (packageName: string, version: stri
|
|
|
76
86
|
await ensureDirectory(stagingDir)
|
|
77
87
|
|
|
78
88
|
const progress = createBootstrapProgress({
|
|
79
|
-
label:
|
|
89
|
+
label: cacheVersion === version
|
|
90
|
+
? `installing ${packageName}@${version} into bootstrap cache`
|
|
91
|
+
: `installing ${packageName}@${version} into bootstrap cache ${cacheVersion}`
|
|
80
92
|
})
|
|
81
93
|
try {
|
|
82
94
|
const result = await runBufferedCommand({
|
|
@@ -100,7 +112,11 @@ export const installPublishedPackage = async (packageName: string, version: stri
|
|
|
100
112
|
await ensureDirectory(path.dirname(cacheDir))
|
|
101
113
|
await rm(cacheDir, { recursive: true, force: true })
|
|
102
114
|
await rename(stagingDir, cacheDir)
|
|
103
|
-
progress.finish(
|
|
115
|
+
progress.finish(
|
|
116
|
+
cacheVersion === version
|
|
117
|
+
? `cached ${packageName}@${version}`
|
|
118
|
+
: `cached ${packageName}@${version} as ${cacheVersion}`
|
|
119
|
+
)
|
|
104
120
|
} catch (error) {
|
|
105
121
|
progress.fail(`failed to cache ${packageName}@${version}`)
|
|
106
122
|
await rm(stagingDir, { recursive: true, force: true }).catch(() => {})
|
|
@@ -108,6 +124,7 @@ export const installPublishedPackage = async (packageName: string, version: stri
|
|
|
108
124
|
}
|
|
109
125
|
|
|
110
126
|
return {
|
|
127
|
+
cacheVersion,
|
|
111
128
|
packageDir: resolvePackageInstallDir(cacheDir, packageName),
|
|
112
129
|
version
|
|
113
130
|
}
|
package/src/program.ts
CHANGED
|
@@ -35,6 +35,7 @@ type BootstrapTarget =
|
|
|
35
35
|
}
|
|
36
36
|
| {
|
|
37
37
|
action: RuntimePackageAction
|
|
38
|
+
cacheVersion?: string
|
|
38
39
|
json: boolean
|
|
39
40
|
kind: 'runtime-package'
|
|
40
41
|
target?: string
|
|
@@ -88,6 +89,7 @@ const parseRuntimePackageTarget = (args: string[]): BootstrapTarget => {
|
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
let version: string | undefined
|
|
92
|
+
let cacheVersion: string | undefined
|
|
91
93
|
for (let index = 0; index < forwardedArgs.length; index += 1) {
|
|
92
94
|
const arg = forwardedArgs[index]
|
|
93
95
|
if (arg === '--version') {
|
|
@@ -109,6 +111,28 @@ const parseRuntimePackageTarget = (args: string[]): BootstrapTarget => {
|
|
|
109
111
|
version = value
|
|
110
112
|
forwardedArgs.splice(index, 1)
|
|
111
113
|
index -= 1
|
|
114
|
+
continue
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (arg === '--cache-version') {
|
|
118
|
+
const value = forwardedArgs[index + 1]
|
|
119
|
+
if (value == null || value.trim() === '') {
|
|
120
|
+
throw new Error('Runtime package --cache-version requires a value.')
|
|
121
|
+
}
|
|
122
|
+
cacheVersion = value
|
|
123
|
+
forwardedArgs.splice(index, 2)
|
|
124
|
+
index -= 1
|
|
125
|
+
continue
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (arg?.startsWith('--cache-version=')) {
|
|
129
|
+
const value = arg.slice('--cache-version='.length)
|
|
130
|
+
if (value.trim() === '') {
|
|
131
|
+
throw new Error('Runtime package --cache-version requires a value.')
|
|
132
|
+
}
|
|
133
|
+
cacheVersion = value
|
|
134
|
+
forwardedArgs.splice(index, 1)
|
|
135
|
+
index -= 1
|
|
112
136
|
}
|
|
113
137
|
}
|
|
114
138
|
|
|
@@ -130,6 +154,7 @@ const parseRuntimePackageTarget = (args: string[]): BootstrapTarget => {
|
|
|
130
154
|
|
|
131
155
|
return {
|
|
132
156
|
action,
|
|
157
|
+
...(cacheVersion != null ? { cacheVersion } : {}),
|
|
133
158
|
json,
|
|
134
159
|
kind: 'runtime-package',
|
|
135
160
|
target: selectorTarget,
|
|
@@ -216,6 +241,7 @@ Examples:
|
|
|
216
241
|
npx oneworks runtime check cli@0.1.0-alpha.0
|
|
217
242
|
npx oneworks runtime install server
|
|
218
243
|
npx oneworks runtime install server --version 0.1.0-alpha.0
|
|
244
|
+
npx oneworks runtime install server --version 0.1.0-alpha.0 --cache-version dev-local
|
|
219
245
|
npx oneworks app
|
|
220
246
|
npx oneworks app cache
|
|
221
247
|
npx oneworks app --no-cache
|
|
@@ -240,15 +266,20 @@ Examples:
|
|
|
240
266
|
}
|
|
241
267
|
|
|
242
268
|
if (target.kind === 'runtime-package') {
|
|
269
|
+
const runtimeOptions: RuntimePackageOptions = {
|
|
270
|
+
...(target.version == null ? {} : { version: target.version }),
|
|
271
|
+
...(target.cacheVersion == null ? {} : { cacheVersion: target.cacheVersion })
|
|
272
|
+
}
|
|
273
|
+
const hasRuntimeOptions = Object.keys(runtimeOptions).length > 0
|
|
243
274
|
let status: RuntimePackageStatus
|
|
244
275
|
if (target.action === 'install') {
|
|
245
|
-
status =
|
|
276
|
+
status = !hasRuntimeOptions
|
|
246
277
|
? await deps.installRuntimePackage(target.target)
|
|
247
|
-
: await deps.installRuntimePackage(target.target,
|
|
278
|
+
: await deps.installRuntimePackage(target.target, runtimeOptions)
|
|
248
279
|
} else {
|
|
249
|
-
status =
|
|
280
|
+
status = !hasRuntimeOptions
|
|
250
281
|
? await deps.checkRuntimePackage(target.target)
|
|
251
|
-
: await deps.checkRuntimePackage(target.target,
|
|
282
|
+
: await deps.checkRuntimePackage(target.target, runtimeOptions)
|
|
252
283
|
}
|
|
253
284
|
const output = target.json ? JSON.stringify(status) : formatRuntimePackageStatus(status)
|
|
254
285
|
process.stdout.write(`${output}\n`)
|
package/src/runtime-package.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { resolvePublishedPackageVersion } from './npm-package'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
normalizePackageCacheVersion,
|
|
4
|
+
resolvePackageCacheDir,
|
|
5
|
+
resolvePackageInstallDir,
|
|
6
|
+
resolveRuntimePackageCacheVersion
|
|
7
|
+
} from './npm-package-cache'
|
|
3
8
|
import {
|
|
4
9
|
findInstalledPublishedPackageVersion,
|
|
5
10
|
installPublishedPackage,
|
|
@@ -10,10 +15,12 @@ export type RuntimePackageAction = 'check' | 'install'
|
|
|
10
15
|
export type RuntimePackageTarget = 'cli' | 'client' | 'server' | 'web'
|
|
11
16
|
|
|
12
17
|
export interface RuntimePackageOptions {
|
|
18
|
+
cacheVersion?: string
|
|
13
19
|
version?: string
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
export interface RuntimePackageStatus {
|
|
23
|
+
cacheVersion?: string
|
|
17
24
|
installed: boolean
|
|
18
25
|
installedVersion?: string
|
|
19
26
|
latestInstalled: boolean
|
|
@@ -56,8 +63,11 @@ export const resolveRuntimePackageTarget = (value: string | undefined): RuntimeP
|
|
|
56
63
|
)
|
|
57
64
|
}
|
|
58
65
|
|
|
59
|
-
const readVersionInstalledAt = async (packageName: string, version: string) => {
|
|
60
|
-
const packageDir = resolvePackageInstallDir(
|
|
66
|
+
const readVersionInstalledAt = async (packageName: string, version: string, cacheVersion = version) => {
|
|
67
|
+
const packageDir = resolvePackageInstallDir(
|
|
68
|
+
resolvePackageCacheDir(packageName, version, { cacheVersion }),
|
|
69
|
+
packageName
|
|
70
|
+
)
|
|
61
71
|
return await readInstalledPackageVersion(packageDir)
|
|
62
72
|
}
|
|
63
73
|
|
|
@@ -70,12 +80,19 @@ const createRuntimePackageStatus = async (
|
|
|
70
80
|
target: RuntimePackageTarget,
|
|
71
81
|
packageName: string,
|
|
72
82
|
targetVersion: string,
|
|
73
|
-
requestedVersion: string | undefined
|
|
83
|
+
requestedVersion: string | undefined,
|
|
84
|
+
requestedCacheVersion: string | undefined
|
|
74
85
|
): Promise<RuntimePackageStatus> => {
|
|
75
|
-
const
|
|
76
|
-
const
|
|
86
|
+
const cacheVersion = normalizePackageCacheVersion(requestedCacheVersion)
|
|
87
|
+
const resolvedCacheVersion = cacheVersion ?? targetVersion
|
|
88
|
+
const installedVersion = cacheVersion == null
|
|
89
|
+
? await findInstalledPublishedPackageVersion(packageName)
|
|
90
|
+
: await readVersionInstalledAt(packageName, targetVersion, resolvedCacheVersion)
|
|
91
|
+
const targetInstalled =
|
|
92
|
+
await readVersionInstalledAt(packageName, targetVersion, resolvedCacheVersion) === targetVersion
|
|
77
93
|
|
|
78
94
|
return {
|
|
95
|
+
...(cacheVersion != null ? { cacheVersion } : {}),
|
|
79
96
|
installed: installedVersion != null,
|
|
80
97
|
...(installedVersion != null ? { installedVersion } : {}),
|
|
81
98
|
latestInstalled: targetInstalled,
|
|
@@ -83,7 +100,9 @@ const createRuntimePackageStatus = async (
|
|
|
83
100
|
packageName,
|
|
84
101
|
...(requestedVersion != null ? { requestedVersion } : {}),
|
|
85
102
|
target,
|
|
86
|
-
updateAvailable: requestedVersion != null
|
|
103
|
+
updateAvailable: requestedVersion != null || cacheVersion != null
|
|
104
|
+
? !targetInstalled
|
|
105
|
+
: installedVersion !== targetVersion
|
|
87
106
|
}
|
|
88
107
|
}
|
|
89
108
|
|
|
@@ -94,8 +113,9 @@ export const checkRuntimePackage = async (
|
|
|
94
113
|
const target = resolveRuntimePackageTarget(targetValue)
|
|
95
114
|
const packageName = RUNTIME_PACKAGE_NAMES[target]
|
|
96
115
|
const requestedVersion = normalizeRequestedVersion(options.version)
|
|
116
|
+
const cacheVersion = normalizePackageCacheVersion(options.cacheVersion) ?? resolveRuntimePackageCacheVersion()
|
|
97
117
|
const targetVersion = requestedVersion ?? await resolveRuntimePackageVersion(packageName, options)
|
|
98
|
-
return await createRuntimePackageStatus(target, packageName, targetVersion, requestedVersion)
|
|
118
|
+
return await createRuntimePackageStatus(target, packageName, targetVersion, requestedVersion, cacheVersion)
|
|
99
119
|
}
|
|
100
120
|
|
|
101
121
|
export const installRuntimePackage = async (
|
|
@@ -105,19 +125,31 @@ export const installRuntimePackage = async (
|
|
|
105
125
|
const target = resolveRuntimePackageTarget(targetValue)
|
|
106
126
|
const packageName = RUNTIME_PACKAGE_NAMES[target]
|
|
107
127
|
const requestedVersion = normalizeRequestedVersion(options.version)
|
|
128
|
+
const cacheVersion = normalizePackageCacheVersion(options.cacheVersion) ?? resolveRuntimePackageCacheVersion()
|
|
108
129
|
const targetVersion = requestedVersion ?? await resolveRuntimePackageVersion(packageName, options)
|
|
109
|
-
await installPublishedPackage(packageName, targetVersion)
|
|
110
|
-
return await createRuntimePackageStatus(target, packageName, targetVersion, requestedVersion)
|
|
130
|
+
await installPublishedPackage(packageName, targetVersion, cacheVersion == null ? {} : { cacheVersion })
|
|
131
|
+
return await createRuntimePackageStatus(target, packageName, targetVersion, requestedVersion, cacheVersion)
|
|
111
132
|
}
|
|
112
133
|
|
|
113
134
|
export const formatRuntimePackageStatus = (status: RuntimePackageStatus) => {
|
|
114
135
|
const current = status.installedVersion ?? 'not installed'
|
|
115
136
|
if (status.requestedVersion != null) {
|
|
137
|
+
if (status.cacheVersion != null) {
|
|
138
|
+
return status.latestInstalled
|
|
139
|
+
? `${status.packageName}@${status.requestedVersion} cached as ${status.cacheVersion}`
|
|
140
|
+
: `${status.packageName}@${status.requestedVersion} not cached as ${status.cacheVersion} (${current})`
|
|
141
|
+
}
|
|
116
142
|
return status.latestInstalled
|
|
117
143
|
? `${status.packageName}@${status.requestedVersion} cached`
|
|
118
144
|
: `${status.packageName}@${status.requestedVersion} not cached (${current})`
|
|
119
145
|
}
|
|
120
146
|
|
|
147
|
+
if (status.cacheVersion != null) {
|
|
148
|
+
return status.latestInstalled
|
|
149
|
+
? `${status.packageName}@${status.latestVersion} cached as ${status.cacheVersion}`
|
|
150
|
+
: `${status.packageName}@${status.latestVersion} not cached as ${status.cacheVersion} (${current})`
|
|
151
|
+
}
|
|
152
|
+
|
|
121
153
|
const suffix = status.updateAvailable
|
|
122
154
|
? `update available: ${current} -> ${status.latestVersion}`
|
|
123
155
|
: `up to date: ${status.latestVersion}`
|