oneworks 0.0.0 → 0.1.0-alpha.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.
@@ -0,0 +1,211 @@
1
+ import { chmod, mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
2
+ import os from 'node:os'
3
+ import path from 'node:path'
4
+ import process from 'node:process'
5
+
6
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
7
+
8
+ import { checkRuntimePackage, installRuntimePackage } from '../src/runtime-package'
9
+
10
+ describe('bootstrap runtime package commands', () => {
11
+ const originalPath = process.env.PATH
12
+ let tempDir: string
13
+
14
+ beforeEach(async () => {
15
+ tempDir = await mkdtemp(path.join(os.tmpdir(), 'ow-bootstrap-runtime-'))
16
+ vi.restoreAllMocks()
17
+ vi.stubEnv('__ONEWORKS_PROJECT_REAL_HOME__', tempDir)
18
+ vi.stubEnv('ONEWORKS_BOOTSTRAP_DISABLE_BACKGROUND_REFRESH', '1')
19
+ vi.stubEnv('ONEWORKS_BOOTSTRAP_PACKAGE_CACHE_FIRST', '0')
20
+ await installFakeNpm()
21
+ })
22
+
23
+ afterEach(async () => {
24
+ vi.restoreAllMocks()
25
+ vi.unstubAllEnvs()
26
+ await rm(tempDir, { force: true, recursive: true })
27
+ })
28
+
29
+ const writeCachedPackage = async (packageName: string, version: string) => {
30
+ const sanitizedName = packageName.replace(/^@/, '').replace(/[\\/]/g, '__')
31
+ const packageDir = path.join(
32
+ tempDir,
33
+ '.oneworks/bootstrap/npm',
34
+ sanitizedName,
35
+ version,
36
+ 'node_modules',
37
+ ...packageName.split('/')
38
+ )
39
+ await mkdir(packageDir, { recursive: true })
40
+ await writeFile(
41
+ path.join(packageDir, 'package.json'),
42
+ JSON.stringify({ name: packageName, version }),
43
+ 'utf8'
44
+ )
45
+ }
46
+
47
+ const installFakeNpm = async () => {
48
+ const binDir = path.join(tempDir, 'bin')
49
+ const npmBin = path.join(binDir, 'npm')
50
+ await mkdir(binDir, { recursive: true })
51
+ await writeFile(
52
+ npmBin,
53
+ `#!/usr/bin/env node
54
+ const fs = require('node:fs')
55
+ const path = require('node:path')
56
+ const version = process.env.ONEWORKS_TEST_NPM_VERSION || '2.0.0'
57
+ const parsePackageSpec = (spec) => {
58
+ const lastAt = spec.lastIndexOf('@')
59
+ return {
60
+ packageName: spec.slice(0, lastAt),
61
+ version: spec.slice(lastAt + 1)
62
+ }
63
+ }
64
+ if (process.argv[2] === 'view') {
65
+ process.stdout.write(JSON.stringify(version) + '\\n')
66
+ process.exit(0)
67
+ }
68
+ if (process.argv[2] === 'install') {
69
+ const prefix = process.argv[process.argv.indexOf('--prefix') + 1]
70
+ const spec = process.argv[process.argv.length - 1]
71
+ const parsed = parsePackageSpec(spec)
72
+ const packageDir = path.join(prefix, 'node_modules', ...parsed.packageName.split('/'))
73
+ fs.mkdirSync(packageDir, { recursive: true })
74
+ fs.writeFileSync(path.join(packageDir, 'package.json'), JSON.stringify({
75
+ name: parsed.packageName,
76
+ version: parsed.version
77
+ }))
78
+ process.exit(0)
79
+ }
80
+ process.exit(1)
81
+ `,
82
+ 'utf8'
83
+ )
84
+ await chmod(npmBin, 0o755)
85
+ vi.stubEnv('PATH', [binDir, originalPath].filter(Boolean).join(path.delimiter))
86
+ }
87
+
88
+ it('checks the published CLI version against the bootstrap cache', async () => {
89
+ await writeCachedPackage('@oneworks/cli', '1.0.0')
90
+ vi.stubEnv('ONEWORKS_TEST_NPM_VERSION', '2.0.0')
91
+
92
+ await expect(checkRuntimePackage('cli')).resolves.toMatchObject({
93
+ installedVersion: '1.0.0',
94
+ latestVersion: '2.0.0',
95
+ packageName: '@oneworks/cli',
96
+ updateAvailable: true
97
+ })
98
+ })
99
+
100
+ it('checks the server runtime package target', async () => {
101
+ await writeCachedPackage('@oneworks/server', '1.0.0')
102
+ vi.stubEnv('ONEWORKS_TEST_NPM_VERSION', '2.0.0')
103
+
104
+ await expect(checkRuntimePackage('server')).resolves.toMatchObject({
105
+ installedVersion: '1.0.0',
106
+ latestVersion: '2.0.0',
107
+ packageName: '@oneworks/server',
108
+ target: 'server',
109
+ updateAvailable: true
110
+ })
111
+ })
112
+
113
+ it('reports an empty runtime package cache without installing anything on check', async () => {
114
+ vi.stubEnv('ONEWORKS_TEST_NPM_VERSION', '2.0.0')
115
+
116
+ await expect(checkRuntimePackage('server')).resolves.toMatchObject({
117
+ installed: false,
118
+ latestInstalled: false,
119
+ latestVersion: '2.0.0',
120
+ packageName: '@oneworks/server',
121
+ target: 'server',
122
+ updateAvailable: true
123
+ })
124
+ })
125
+
126
+ it('checks an explicit runtime package version without resolving latest', async () => {
127
+ await writeCachedPackage('@oneworks/server', '1.0.0')
128
+ vi.stubEnv('ONEWORKS_TEST_NPM_VERSION', '2.0.0')
129
+
130
+ await expect(checkRuntimePackage('server', { version: '1.0.0' })).resolves.toMatchObject({
131
+ installedVersion: '1.0.0',
132
+ latestInstalled: true,
133
+ latestVersion: '1.0.0',
134
+ packageName: '@oneworks/server',
135
+ requestedVersion: '1.0.0',
136
+ target: 'server',
137
+ updateAvailable: false
138
+ })
139
+ })
140
+
141
+ it('installs the latest CLI version into the bootstrap cache', async () => {
142
+ vi.stubEnv('ONEWORKS_TEST_NPM_VERSION', '2.1.0')
143
+
144
+ await expect(installRuntimePackage('cli')).resolves.toMatchObject({
145
+ installedVersion: '2.1.0',
146
+ latestInstalled: true,
147
+ latestVersion: '2.1.0',
148
+ updateAvailable: false
149
+ })
150
+ })
151
+
152
+ it('installs an explicit runtime package version into the bootstrap cache', async () => {
153
+ vi.stubEnv('ONEWORKS_TEST_NPM_VERSION', '9.9.9')
154
+
155
+ await expect(installRuntimePackage('client', { version: '2.2.0' })).resolves.toMatchObject({
156
+ installedVersion: '2.2.0',
157
+ latestInstalled: true,
158
+ latestVersion: '2.2.0',
159
+ packageName: '@oneworks/client',
160
+ requestedVersion: '2.2.0',
161
+ target: 'client',
162
+ updateAvailable: false
163
+ })
164
+ })
165
+
166
+ it('honors the configured package cache root for runtime packages', async () => {
167
+ const packageCacheRoot = path.join(tempDir, 'package-cache')
168
+ vi.stubEnv('__ONEWORKS_PROJECT_PACKAGE_CACHE_DIR__', packageCacheRoot)
169
+ vi.stubEnv('ONEWORKS_TEST_NPM_VERSION', '8.8.8')
170
+
171
+ await expect(installRuntimePackage('server', { version: '2.2.0' })).resolves.toMatchObject({
172
+ installedVersion: '2.2.0',
173
+ latestInstalled: true,
174
+ packageName: '@oneworks/server'
175
+ })
176
+ await expect(
177
+ writeFile(
178
+ path.join(
179
+ packageCacheRoot,
180
+ 'npm',
181
+ 'oneworks__server',
182
+ '2.2.0',
183
+ 'node_modules',
184
+ '@oneworks',
185
+ 'server',
186
+ 'probe'
187
+ ),
188
+ 'ok'
189
+ )
190
+ ).resolves.toBeUndefined()
191
+ })
192
+
193
+ it('installs the latest client runtime package target', async () => {
194
+ vi.stubEnv('ONEWORKS_TEST_NPM_VERSION', '2.2.0')
195
+
196
+ await expect(installRuntimePackage('client')).resolves.toMatchObject({
197
+ installedVersion: '2.2.0',
198
+ latestInstalled: true,
199
+ latestVersion: '2.2.0',
200
+ packageName: '@oneworks/client',
201
+ target: 'client',
202
+ updateAvailable: false
203
+ })
204
+ })
205
+
206
+ it('rejects non-exact runtime package versions', async () => {
207
+ await expect(checkRuntimePackage('cli', { version: 'latest' })).rejects.toThrow(
208
+ 'Runtime package version must be an exact semver version'
209
+ )
210
+ })
211
+ })
package/cli.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('@oneworks/cli-helper/entry').runCliPackageEntrypoint({
4
+ packageDir: __dirname
5
+ })
@@ -0,0 +1,324 @@
1
+ /* eslint-disable max-lines -- Standalone background worker avoids booting the TS loader on the startup path. */
2
+ const { Buffer } = require('node:buffer')
3
+ const { spawn } = require('node:child_process')
4
+ const { createHash } = require('node:crypto')
5
+ const { existsSync } = require('node:fs')
6
+ const { access, mkdir, readFile, rename, rm, stat, writeFile } = require('node:fs/promises')
7
+ const os = require('node:os')
8
+ const path = require('node:path')
9
+ const process = require('node:process')
10
+
11
+ const DEFAULT_PACKAGE_TAG = 'latest'
12
+ const NPM_BIN = process.platform === 'win32' ? 'npm.cmd' : 'npm'
13
+ const STALE_LOCK_MS = 5 * 60 * 1000
14
+
15
+ const resolveRealHomeDir = () => {
16
+ const realHome = process.env.__ONEWORKS_PROJECT_REAL_HOME__?.trim() || process.env.HOME?.trim()
17
+ return realHome || os.homedir()
18
+ }
19
+
20
+ const resolveBootstrapDataDir = () => path.join(resolveRealHomeDir(), '.oneworks', 'bootstrap')
21
+
22
+ const resolveBootstrapPackageCacheDir = () => (
23
+ process.env.__ONEWORKS_PROJECT_PACKAGE_CACHE_DIR__?.trim() || resolveBootstrapDataDir()
24
+ )
25
+
26
+ const sanitizePackageName = packageName => packageName.replace(/^@/, '').replace(/[\\/]/g, '__')
27
+
28
+ const splitPackageName = packageName => packageName.split('/')
29
+
30
+ const hashValue = value => createHash('sha1').update(value).digest('hex')
31
+
32
+ const resolvePackageTag = () => process.env.ONEWORKS_BOOTSTRAP_PACKAGE_TAG?.trim() || DEFAULT_PACKAGE_TAG
33
+
34
+ const resolvePackageCacheDir = (packageName, version) => (
35
+ path.join(resolveBootstrapPackageCacheDir(), 'npm', sanitizePackageName(packageName), version)
36
+ )
37
+
38
+ const resolvePackageInstallDir = (cacheDir, packageName) => (
39
+ path.join(cacheDir, 'node_modules', ...splitPackageName(packageName))
40
+ )
41
+
42
+ const resolveProjectNpmrc = () => {
43
+ const projectNpmrc = path.resolve(process.cwd(), '.npmrc')
44
+ return existsSync(projectNpmrc) ? projectNpmrc : undefined
45
+ }
46
+
47
+ const resolvePackageManagerEnv = () => {
48
+ const userConfig = process.env.npm_config_userconfig ?? process.env.NPM_CONFIG_USERCONFIG ?? resolveProjectNpmrc()
49
+
50
+ return {
51
+ ...process.env,
52
+ HOME: resolveRealHomeDir(),
53
+ USERPROFILE: resolveRealHomeDir(),
54
+ npm_config_cache: path.join(resolveBootstrapPackageCacheDir(), 'npm-cache'),
55
+ npm_config_replace_registry_host: 'never',
56
+ npm_config_update_notifier: 'false',
57
+ NPM_CONFIG_REPLACE_REGISTRY_HOST: 'never',
58
+ ...(userConfig != null
59
+ ? {
60
+ NPM_CONFIG_USERCONFIG: userConfig,
61
+ npm_config_userconfig: userConfig
62
+ }
63
+ : {})
64
+ }
65
+ }
66
+
67
+ const readOptionalFile = async filePath => {
68
+ if (filePath == null || filePath === '') {
69
+ return undefined
70
+ }
71
+
72
+ try {
73
+ return await readFile(filePath, 'utf8')
74
+ } catch {
75
+ return undefined
76
+ }
77
+ }
78
+
79
+ const resolvePackageLookupKey = async packageName => {
80
+ const env = resolvePackageManagerEnv()
81
+ const userConfig = env.npm_config_userconfig ?? env.NPM_CONFIG_USERCONFIG
82
+ const userConfigContent = await readOptionalFile(userConfig)
83
+
84
+ return JSON.stringify({
85
+ packageName,
86
+ packageTag: resolvePackageTag(),
87
+ registry: env.npm_config_registry ?? env.NPM_CONFIG_REGISTRY ?? '',
88
+ userConfig: userConfig ?? '',
89
+ userConfigContentHash: userConfigContent == null ? '' : hashValue(userConfigContent)
90
+ })
91
+ }
92
+
93
+ const resolvePackageVersionMetadataPath = async packageName => {
94
+ const lookupKey = await resolvePackageLookupKey(packageName)
95
+ return {
96
+ lookupKey,
97
+ metadataPath: path.join(
98
+ resolveBootstrapPackageCacheDir(),
99
+ 'npm-version-cache',
100
+ `${sanitizePackageName(packageName)}-${hashValue(lookupKey)}.json`
101
+ )
102
+ }
103
+ }
104
+
105
+ const ensureDirectory = async targetPath => {
106
+ await mkdir(targetPath, { recursive: true })
107
+ }
108
+
109
+ const isExistingPath = async targetPath => {
110
+ try {
111
+ await access(targetPath)
112
+ return true
113
+ } catch {
114
+ return false
115
+ }
116
+ }
117
+
118
+ const runBufferedCommand = async input => {
119
+ const child = spawn(input.command, input.args, {
120
+ cwd: input.cwd,
121
+ env: input.env,
122
+ stdio: input.stdio ?? 'pipe'
123
+ })
124
+
125
+ let stdout = ''
126
+ let stderr = ''
127
+
128
+ if (input.stdio !== 'inherit') {
129
+ child.stdout?.on('data', chunk => {
130
+ stdout += String(chunk)
131
+ })
132
+ child.stderr?.on('data', chunk => {
133
+ stderr += String(chunk)
134
+ })
135
+ }
136
+
137
+ return await new Promise((resolve, reject) => {
138
+ child.once('error', reject)
139
+ child.once('exit', code => {
140
+ resolve({
141
+ code: code ?? 0,
142
+ stderr,
143
+ stdout
144
+ })
145
+ })
146
+ })
147
+ }
148
+
149
+ const parseVersionOutput = (spec, stdout) => {
150
+ const normalizedOutput = stdout.trim()
151
+ if (!normalizedOutput) {
152
+ throw new Error(`No version was returned for ${spec}.`)
153
+ }
154
+
155
+ try {
156
+ const parsed = JSON.parse(normalizedOutput)
157
+ if (typeof parsed === 'string' && parsed.trim()) {
158
+ return parsed.trim()
159
+ }
160
+ } catch {
161
+ // fall through
162
+ }
163
+
164
+ const unquotedOutput = normalizedOutput.replace(/^"|"$/g, '').trim()
165
+ if (!unquotedOutput) {
166
+ throw new Error(`Invalid published version for ${spec}: ${normalizedOutput}`)
167
+ }
168
+
169
+ return unquotedOutput
170
+ }
171
+
172
+ const resolvePublishedPackageVersion = async packageName => {
173
+ const spec = `${packageName}@${resolvePackageTag()}`
174
+ const result = await runBufferedCommand({
175
+ command: NPM_BIN,
176
+ args: ['view', spec, 'version', '--json'],
177
+ env: resolvePackageManagerEnv()
178
+ })
179
+
180
+ if (result.code !== 0) {
181
+ throw new Error(`Failed to resolve published version for ${spec}:\n${result.stderr.trim()}`)
182
+ }
183
+
184
+ return parseVersionOutput(spec, result.stdout)
185
+ }
186
+
187
+ const writePublishedPackageVersionMetadata = async (packageName, version) => {
188
+ const { lookupKey, metadataPath } = await resolvePackageVersionMetadataPath(packageName)
189
+ await ensureDirectory(path.dirname(metadataPath))
190
+
191
+ const tempPath = `${metadataPath}.${process.pid}.${Date.now()}.tmp`
192
+ await writeFile(
193
+ tempPath,
194
+ `${
195
+ JSON.stringify(
196
+ {
197
+ lookupKey,
198
+ packageName,
199
+ packageTag: resolvePackageTag(),
200
+ resolvedAt: new Date().toISOString(),
201
+ version
202
+ },
203
+ null,
204
+ 2
205
+ )
206
+ }\n`,
207
+ 'utf8'
208
+ )
209
+ await rename(tempPath, metadataPath)
210
+ }
211
+
212
+ const readInstalledPackageVersion = async packageDir => {
213
+ const packageJsonPath = path.join(packageDir, 'package.json')
214
+ if (!(await isExistingPath(packageJsonPath))) {
215
+ return undefined
216
+ }
217
+
218
+ try {
219
+ const content = await readFile(packageJsonPath, 'utf8')
220
+ const packageJson = JSON.parse(content)
221
+ return typeof packageJson.version === 'string' ? packageJson.version : undefined
222
+ } catch {
223
+ return undefined
224
+ }
225
+ }
226
+
227
+ const installPublishedPackage = async (packageName, version) => {
228
+ const cacheDir = resolvePackageCacheDir(packageName, version)
229
+ const packageDir = resolvePackageInstallDir(cacheDir, packageName)
230
+ const installedVersion = await readInstalledPackageVersion(packageDir)
231
+ if (installedVersion === version) {
232
+ return
233
+ }
234
+
235
+ const stagingDir = `${cacheDir}.tmp-${process.pid}-${Date.now()}`
236
+ await rm(stagingDir, { recursive: true, force: true })
237
+ await ensureDirectory(stagingDir)
238
+
239
+ const result = await runBufferedCommand({
240
+ command: NPM_BIN,
241
+ args: [
242
+ 'install',
243
+ '--prefix',
244
+ stagingDir,
245
+ '--no-audit',
246
+ '--no-fund',
247
+ '--loglevel=error',
248
+ `${packageName}@${version}`
249
+ ],
250
+ env: resolvePackageManagerEnv(),
251
+ stdio: 'ignore'
252
+ })
253
+
254
+ if (result.code !== 0) {
255
+ await rm(stagingDir, { recursive: true, force: true })
256
+ throw new Error(`Failed to install ${packageName}@${version}.`)
257
+ }
258
+
259
+ await ensureDirectory(path.dirname(cacheDir))
260
+ await rm(cacheDir, { recursive: true, force: true })
261
+ try {
262
+ await rename(stagingDir, cacheDir)
263
+ } catch (error) {
264
+ await rm(stagingDir, { recursive: true, force: true })
265
+ throw error
266
+ }
267
+ }
268
+
269
+ const acquireLock = async lockPath => {
270
+ try {
271
+ await mkdir(lockPath)
272
+ return true
273
+ } catch {
274
+ try {
275
+ const lockStat = await stat(lockPath)
276
+ if (Date.now() - lockStat.mtimeMs > STALE_LOCK_MS) {
277
+ await rm(lockPath, { force: true, recursive: true })
278
+ await mkdir(lockPath)
279
+ return true
280
+ }
281
+ } catch {
282
+ return false
283
+ }
284
+ }
285
+
286
+ return false
287
+ }
288
+
289
+ const decodePayload = () => {
290
+ const rawPayload = process.argv[2]
291
+ if (!rawPayload) {
292
+ throw new Error('Missing refresh payload.')
293
+ }
294
+
295
+ const parsed = JSON.parse(Buffer.from(rawPayload, 'base64url').toString('utf8'))
296
+ if (typeof parsed.packageName !== 'string' || parsed.packageName.trim() === '') {
297
+ throw new Error('Invalid refresh payload.')
298
+ }
299
+
300
+ return {
301
+ packageName: parsed.packageName
302
+ }
303
+ }
304
+
305
+ const main = async () => {
306
+ const { packageName } = decodePayload()
307
+ const { metadataPath } = await resolvePackageVersionMetadataPath(packageName)
308
+ const lockPath = `${metadataPath}.lock`
309
+ if (!(await acquireLock(lockPath))) {
310
+ return
311
+ }
312
+
313
+ try {
314
+ const version = await resolvePublishedPackageVersion(packageName)
315
+ await writePublishedPackageVersionMetadata(packageName, version)
316
+ await installPublishedPackage(packageName, version)
317
+ } finally {
318
+ await rm(lockPath, { force: true, recursive: true })
319
+ }
320
+ }
321
+
322
+ main().catch(() => {
323
+ process.exitCode = 0
324
+ })
package/package.json CHANGED
@@ -1,16 +1,29 @@
1
1
  {
2
2
  "name": "oneworks",
3
- "version": "0.0.0",
4
- "description": "Reserved placeholder package for OneWorks.",
5
- "private": false,
6
- "license": "UNLICENSED",
7
- "main": "index.js",
8
- "files": [
9
- "index.js",
10
- "README.md"
11
- ],
12
- "publishConfig": {
13
- "access": "public",
14
- "registry": "https://registry.npmjs.org"
3
+ "version": "0.1.0-alpha.0",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "https://github.com/oneworks-ai/app.git",
7
+ "directory": "apps/bootstrap"
8
+ },
9
+ "description": "One Works bootstrap launcher",
10
+ "oneworks": {
11
+ "runtimeTranspile": true
12
+ },
13
+ "exports": {
14
+ "./package.json": "./package.json"
15
+ },
16
+ "bin": {
17
+ "oneworks": "./cli.js",
18
+ "ow": "./cli.js",
19
+ "owo": "./cli.js"
20
+ },
21
+ "dependencies": {
22
+ "@clack/prompts": "^0.11.0",
23
+ "commander": "^12.1.0",
24
+ "@oneworks/cli-helper": "0.1.0-alpha.0"
25
+ },
26
+ "scripts": {
27
+ "test": "pnpm -C ../.. exec vitest run --workspace vitest.workspace.ts --project node apps/bootstrap/__tests__"
15
28
  }
16
- }
29
+ }