wattpm-utils 3.37.0 → 3.38.1

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.
@@ -84,6 +84,24 @@ export async function installDependencies (logger, root, applications, productio
84
84
  )} using ${applicationPackageManager} ...`
85
85
  )
86
86
 
87
+ // yarn v1 will skip folders that have no version field in their package.json, so we need to add it if it's missing
88
+ if (applicationPackageManager === 'yarn') {
89
+ const packageJsonPath = resolve(root, path, 'package.json')
90
+
91
+ if (existsSync(packageJsonPath)) {
92
+ const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'))
93
+
94
+ if (!packageJson.version) {
95
+ logger.warn(
96
+ `The package.json of the application ${bold(id)} is missing the ${bold('version')} field, which is required by yarn version. Setting version to 0.1.0 ...`
97
+ )
98
+
99
+ packageJson.version = '0.1.0'
100
+ await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2))
101
+ }
102
+ }
103
+ }
104
+
87
105
  await executeCommand(root, applicationPackageManager, applicationPackageArgs, {
88
106
  cwd: resolve(root, path),
89
107
  stdio: 'inherit',
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  applicationToEnvVariable,
3
+ createDirectory,
3
4
  detectApplicationType,
4
5
  ensureLoggableError,
5
6
  findConfigurationFile,
@@ -9,6 +10,7 @@ import {
9
10
  loadConfigurationFile as loadRawConfigurationFile,
10
11
  logFatalError,
11
12
  parseArgs,
13
+ safeRemove,
12
14
  saveConfigurationFile
13
15
  } from '@platformatic/foundation'
14
16
  import { loadConfiguration } from '@platformatic/runtime'
@@ -16,8 +18,10 @@ import { bold } from 'colorette'
16
18
  import { execa } from 'execa'
17
19
  import { existsSync } from 'node:fs'
18
20
  import { readFile, writeFile } from 'node:fs/promises'
21
+ import { tmpdir } from 'node:os'
19
22
  import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path'
20
23
  import { parseEnv } from 'node:util'
24
+ import { extract } from 'tar'
21
25
  import { version } from '../version.js'
22
26
  import { installDependencies } from './dependencies.js'
23
27
 
@@ -326,6 +330,71 @@ async function importLocal (logger, root, configurationFile, path, overridenId)
326
330
  await saveConfigurationFile(resolve(path, 'package.json'), packageJson)
327
331
  }
328
332
 
333
+ async function resolveNpmApplication (application, root, childLogger) {
334
+ const absolutePath = application.path
335
+ const relativePath = relative(root, absolutePath)
336
+ const pkg = application.url.replace(/^npm:/, '')
337
+
338
+ childLogger.info(`Resolving application ${bold(application.id)} ...`)
339
+
340
+ // Download the package using npm pack. We do that in a temporary directory.
341
+ let temporaryDirectory
342
+ const originalWorkingDirectory = process.cwd()
343
+ try {
344
+ childLogger.info(`Downloading npm package ${bold(pkg)} into ${bold(relativePath)} ...`)
345
+
346
+ temporaryDirectory = join(tmpdir(), `wattpm-utils-resolve--${process.pid}-${Date.now()}`)
347
+ await createDirectory(temporaryDirectory)
348
+ process.chdir(temporaryDirectory)
349
+
350
+ // The last line of the output is the name of the generated tarball
351
+ const { stdout } = await execa('npm', ['pack', pkg])
352
+ const archive = stdout.trim().split('\n').at(-1)
353
+
354
+ await createDirectory(absolutePath)
355
+ await extract({ file: resolve(temporaryDirectory, archive), cwd: absolutePath, strip: 1 })
356
+ } finally {
357
+ await safeRemove(temporaryDirectory)
358
+ process.chdir(originalWorkingDirectory)
359
+ }
360
+ }
361
+
362
+ async function resolveGitApplication (application, root, childLogger, username, password) {
363
+ const absolutePath = application.path
364
+ const relativePath = relative(root, absolutePath)
365
+
366
+ childLogger.info(`Resolving application ${bold(application.id)} ...`)
367
+
368
+ const parsedGitUrl = parseGitUrl(application.url)
369
+ let url = parsedGitUrl.url
370
+ const effectiveBranch = application.gitBranch ?? parsedGitUrl.branch
371
+
372
+ if (url.startsWith('http') && username && password) {
373
+ const parsed = new URL(url)
374
+ parsed.username ||= username
375
+ parsed.password ||= password
376
+ url = parsed.toString()
377
+ }
378
+
379
+ const cloneArgs = ['clone', url, absolutePath, '--single-branch', '--depth', 1]
380
+
381
+ let branchLabel = ''
382
+ if (effectiveBranch && effectiveBranch !== 'main') {
383
+ cloneArgs.push('--branch', effectiveBranch)
384
+ branchLabel = ` (branch ${bold(effectiveBranch)})`
385
+ }
386
+
387
+ if (username) {
388
+ childLogger.info(
389
+ `Cloning ${bold(application.url)}${branchLabel} as user ${bold(username)} into ${bold(relativePath)} ...`
390
+ )
391
+ } else {
392
+ childLogger.info(`Cloning ${bold(application.url)}${branchLabel} into ${bold(relativePath)} ...`)
393
+ }
394
+
395
+ await execa('git', cloneArgs)
396
+ }
397
+
329
398
  export async function resolveApplications (
330
399
  logger,
331
400
  root,
@@ -393,45 +462,20 @@ export async function resolveApplications (
393
462
  for (const application of toResolve) {
394
463
  const childLogger = logger.child({ name: application.id })
395
464
 
465
+ let operation
396
466
  try {
397
- const absolutePath = application.path
398
- const relativePath = relative(root, absolutePath)
399
-
400
- childLogger.info(`Resolving application ${bold(application.id)} ...`)
401
-
402
- const parsedGitUrl = parseGitUrl(application.url)
403
- let url = parsedGitUrl.url
404
- const effectiveBranch = application.gitBranch ?? parsedGitUrl.branch
405
-
406
- if (url.startsWith('http') && username && password) {
407
- const parsed = new URL(url)
408
- parsed.username ||= username
409
- parsed.password ||= password
410
- url = parsed.toString()
411
- }
412
-
413
- const cloneArgs = ['clone', url, absolutePath, '--single-branch', '--depth', 1]
414
-
415
- let branchLabel = ''
416
- if (effectiveBranch && effectiveBranch !== 'main') {
417
- cloneArgs.push('--branch', effectiveBranch)
418
- branchLabel = ` (branch ${bold(effectiveBranch)})`
419
- }
420
-
421
- if (username) {
422
- childLogger.info(
423
- `Cloning ${bold(application.url)}${branchLabel} as user ${bold(username)} into ${bold(relativePath)} ...`
424
- )
467
+ if (application.url.startsWith('npm')) {
468
+ operation = 'download npm package'
469
+ await resolveNpmApplication(application, root, childLogger)
425
470
  } else {
426
- childLogger.info(`Cloning ${bold(application.url)}${branchLabel} into ${bold(relativePath)} ...`)
471
+ operation = 'clone repository'
472
+ await resolveGitApplication(application, root, childLogger, username, password)
427
473
  }
428
-
429
- await execa('git', cloneArgs)
430
474
  } catch (error) {
431
475
  return logFatalError(
432
476
  childLogger,
433
477
  { error: ensureLoggableError(error) },
434
- `Unable to clone repository of the application ${bold(application.id)}`
478
+ `Unable to ${operation} of the application ${bold(application.id)}.`
435
479
  )
436
480
  }
437
481
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wattpm-utils",
3
- "version": "3.37.0",
3
+ "version": "3.38.1",
4
4
  "description": "The Node.js Application Server Utilities Commands",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -28,9 +28,10 @@
28
28
  "dotenv": "^16.4.5",
29
29
  "execa": "^9.4.0",
30
30
  "semver": "^7.7.0",
31
- "@platformatic/foundation": "3.37.0",
32
- "@platformatic/runtime": "3.37.0",
33
- "create-wattpm": "3.37.0"
31
+ "tar": "^7.5.7",
32
+ "@platformatic/runtime": "3.38.1",
33
+ "create-wattpm": "3.38.1",
34
+ "@platformatic/foundation": "3.38.1"
34
35
  },
35
36
  "devDependencies": {
36
37
  "cleaner-spec-reporter": "^0.5.0",
@@ -40,7 +41,7 @@
40
41
  "neostandard": "^0.12.0",
41
42
  "typescript": "^5.5.4",
42
43
  "undici": "^7.0.0",
43
- "@platformatic/node": "3.37.0"
44
+ "@platformatic/node": "3.38.1"
44
45
  },
45
46
  "engines": {
46
47
  "node": ">=22.19.0"