create-platformatic 2.65.1 → 2.66.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/package.json +9 -8
- package/src/index.mjs +158 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-platformatic",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.66.0",
|
|
4
4
|
"description": "Create platformatic application interactive tool",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"desm": "^1.3.1",
|
|
21
21
|
"es-main": "^1.3.0",
|
|
22
22
|
"execa": "^9.0.0",
|
|
23
|
+
"glob": "^11.0.2",
|
|
23
24
|
"help-me": "^5.0.0",
|
|
24
25
|
"inquirer": "^9.2.16",
|
|
25
26
|
"minimist": "^1.2.8",
|
|
@@ -31,9 +32,9 @@
|
|
|
31
32
|
"strip-ansi": "^7.1.0",
|
|
32
33
|
"undici": "^7.0.0",
|
|
33
34
|
"which": "^3.0.1",
|
|
34
|
-
"@platformatic/
|
|
35
|
-
"@platformatic/
|
|
36
|
-
"@platformatic/
|
|
35
|
+
"@platformatic/config": "2.66.0",
|
|
36
|
+
"@platformatic/generators": "2.66.0",
|
|
37
|
+
"@platformatic/utils": "2.66.0"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
40
|
"@types/node": "^22.5.0",
|
|
@@ -48,10 +49,10 @@
|
|
|
48
49
|
"neostandard": "^0.12.0",
|
|
49
50
|
"typescript": "~5.8.0",
|
|
50
51
|
"yaml": "^2.4.1",
|
|
51
|
-
"@platformatic/composer": "2.
|
|
52
|
-
"@platformatic/db": "2.
|
|
53
|
-
"@platformatic/runtime": "2.
|
|
54
|
-
"@platformatic/service": "2.
|
|
52
|
+
"@platformatic/composer": "2.66.0",
|
|
53
|
+
"@platformatic/db": "2.66.0",
|
|
54
|
+
"@platformatic/runtime": "2.66.0",
|
|
55
|
+
"@platformatic/service": "2.66.0"
|
|
55
56
|
},
|
|
56
57
|
"scripts": {
|
|
57
58
|
"test:cli": "borp --pattern \"test/cli/*test.mjs\" --timeout=300000 --concurrency=1",
|
package/src/index.mjs
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import ConfigManager, { findConfigurationFile, loadConfigurationFile } from '@platformatic/config'
|
|
2
2
|
import { createDirectory, executeWithTimeout, generateDashedName, getPkgManager } from '@platformatic/utils'
|
|
3
3
|
import { execa } from 'execa'
|
|
4
|
+
import { glob } from 'glob'
|
|
4
5
|
import defaultInquirer from 'inquirer'
|
|
5
6
|
import parseArgs from 'minimist'
|
|
7
|
+
import { existsSync } from 'node:fs'
|
|
6
8
|
import { readFile, writeFile } from 'node:fs/promises'
|
|
7
|
-
import { basename, join, resolve
|
|
9
|
+
import { basename, dirname, join, resolve } from 'node:path'
|
|
8
10
|
import { pathToFileURL } from 'node:url'
|
|
9
11
|
import ora from 'ora'
|
|
10
12
|
import pino from 'pino'
|
|
11
13
|
import pretty from 'pino-pretty'
|
|
12
|
-
import
|
|
14
|
+
import * as resolveModule from 'resolve'
|
|
13
15
|
import { request } from 'undici'
|
|
14
16
|
import { createGitRepository } from './create-git-repository.mjs'
|
|
15
17
|
import { getUsername, getVersion, say } from './utils.mjs'
|
|
@@ -57,7 +59,7 @@ async function importOrLocal ({ pkgManager, name, projectDir, pkg }) {
|
|
|
57
59
|
return await import(pkg)
|
|
58
60
|
} catch (err) {
|
|
59
61
|
try {
|
|
60
|
-
const fileToImport =
|
|
62
|
+
const fileToImport = resolveModule.sync(pkg, { basedir: projectDir })
|
|
61
63
|
return await import(pathToFileURL(fileToImport))
|
|
62
64
|
} catch {
|
|
63
65
|
// No-op
|
|
@@ -81,11 +83,93 @@ async function importOrLocal ({ pkgManager, name, projectDir, pkg }) {
|
|
|
81
83
|
await execa(pkgManager, ['install', pkg + version], { cwd: projectDir })
|
|
82
84
|
spinner.succeed()
|
|
83
85
|
|
|
84
|
-
const fileToImport =
|
|
86
|
+
const fileToImport = resolveModule.sync(pkg, { basedir: projectDir })
|
|
85
87
|
return await import(pathToFileURL(fileToImport))
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
|
|
91
|
+
async function findApplicationRoot (projectDir) {
|
|
92
|
+
if (existsSync(resolve(projectDir, 'package.json'))) {
|
|
93
|
+
return projectDir
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const files = await glob('**/*.{js,mjs,cjs,ts,mts,cts}', { cwd: projectDir })
|
|
97
|
+
|
|
98
|
+
if (files.length > 0) {
|
|
99
|
+
return dirname(resolve(projectDir, files[0]))
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return null
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function determineApplicationType (projectDir) {
|
|
106
|
+
let rootPackageJson
|
|
107
|
+
try {
|
|
108
|
+
rootPackageJson = JSON.parse(await readFile(resolve(projectDir, 'package.json'), 'utf-8'))
|
|
109
|
+
} catch {
|
|
110
|
+
rootPackageJson = {}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const { dependencies, devDependencies } = rootPackageJson
|
|
114
|
+
|
|
115
|
+
if (dependencies?.next || devDependencies?.next) {
|
|
116
|
+
return ['@platformatic/next', 'Next.js']
|
|
117
|
+
} else if (dependencies?.['@remix-run/dev'] || devDependencies?.['@remix-run/dev']) {
|
|
118
|
+
return ['@platformatic/remix', 'Remix']
|
|
119
|
+
} else if (dependencies?.astro || devDependencies?.astro) {
|
|
120
|
+
return ['@platformatic/astro', 'Astro']
|
|
121
|
+
} else if (dependencies?.vite || devDependencies?.vite) {
|
|
122
|
+
return ['@platformatic/vite', 'Vite']
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return ['@platformatic/node', 'Node.js']
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export async function wrapApplication (
|
|
129
|
+
logger,
|
|
130
|
+
inquirer,
|
|
131
|
+
packageManager,
|
|
132
|
+
module,
|
|
133
|
+
install,
|
|
134
|
+
projectDir,
|
|
135
|
+
additionalGeneratorOptions = {},
|
|
136
|
+
additionalGeneratorConfig = {}
|
|
137
|
+
) {
|
|
138
|
+
const projectName = basename(projectDir)
|
|
139
|
+
|
|
140
|
+
const runtime = await importOrLocal({
|
|
141
|
+
pkgManager: packageManager,
|
|
142
|
+
name: projectName,
|
|
143
|
+
projectDir,
|
|
144
|
+
pkg: '@platformatic/runtime'
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
const generator = new runtime.WrappedGenerator({
|
|
148
|
+
logger,
|
|
149
|
+
module,
|
|
150
|
+
name: projectName,
|
|
151
|
+
inquirer,
|
|
152
|
+
...additionalGeneratorOptions
|
|
153
|
+
})
|
|
154
|
+
generator.setConfig({
|
|
155
|
+
...generator.config,
|
|
156
|
+
...additionalGeneratorConfig,
|
|
157
|
+
targetDirectory: projectDir,
|
|
158
|
+
typescript: false
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
await generator.ask()
|
|
162
|
+
await generator.prepare()
|
|
163
|
+
await generator.writeFiles()
|
|
164
|
+
|
|
165
|
+
if (install) {
|
|
166
|
+
logger.info(`Installing dependencies for the application using ${packageManager} ...`)
|
|
167
|
+
await execa(packageManager, ['install'], { cwd: projectDir, stdio: 'inherit' })
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
logger.info(`You are all set! Run \`${packageManager} start\` to start your project.`)
|
|
171
|
+
}
|
|
172
|
+
|
|
89
173
|
export async function createPlatformatic (argv) {
|
|
90
174
|
const args = parseArgs(argv, {
|
|
91
175
|
default: {
|
|
@@ -119,13 +203,75 @@ export async function createApplication (
|
|
|
119
203
|
modules,
|
|
120
204
|
marketplaceHost,
|
|
121
205
|
install,
|
|
122
|
-
additionalGeneratorOptions = {}
|
|
206
|
+
additionalGeneratorOptions = {},
|
|
207
|
+
additionalGeneratorConfig = {}
|
|
123
208
|
) {
|
|
124
209
|
// This is only used for testing for now, but might be useful in the future
|
|
125
|
-
const inquirer = process.env.
|
|
210
|
+
const inquirer = process.env.USER_INPUT_HANDLER ? await import(process.env.USER_INPUT_HANDLER) : defaultInquirer
|
|
126
211
|
|
|
212
|
+
// Check in the directory and its parents if there is a config file
|
|
213
|
+
let shouldChooseProjectDir = true
|
|
127
214
|
let projectDir = process.cwd()
|
|
128
|
-
|
|
215
|
+
const runtimeConfigFile = await findConfigurationFile(projectDir, null, 'runtime')
|
|
216
|
+
|
|
217
|
+
if (runtimeConfigFile) {
|
|
218
|
+
shouldChooseProjectDir = false
|
|
219
|
+
projectDir = dirname(runtimeConfigFile)
|
|
220
|
+
} else {
|
|
221
|
+
// Check the current directory for suitable config files
|
|
222
|
+
const applicationRoot = await findApplicationRoot(projectDir)
|
|
223
|
+
|
|
224
|
+
if (applicationRoot) {
|
|
225
|
+
const [module, label] = await determineApplicationType(projectDir)
|
|
226
|
+
|
|
227
|
+
// Check if the file belongs to a Watt application, this can happen for instance if we executed watt create
|
|
228
|
+
// in the services folder
|
|
229
|
+
const existingRuntime = await findConfigurationFile(applicationRoot, null, 'runtime')
|
|
230
|
+
|
|
231
|
+
if (!existingRuntime) {
|
|
232
|
+
// If there is a watt.json file with a runtime property, we assume we already executed watt create and we exit.
|
|
233
|
+
const existingService = await ConfigManager.findConfigFile(projectDir)
|
|
234
|
+
|
|
235
|
+
if (existingService) {
|
|
236
|
+
const serviceConfig = await loadConfigurationFile(existingService)
|
|
237
|
+
|
|
238
|
+
if (serviceConfig.runtime) {
|
|
239
|
+
await say(`The ${label} application has already been wrapped into Watt.`)
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const { shouldWrap } = await inquirer.prompt({
|
|
245
|
+
type: 'list',
|
|
246
|
+
name: 'shouldWrap',
|
|
247
|
+
message: `This folder seems to already contain a ${label} application. Do you want to wrap into Watt?`,
|
|
248
|
+
// default: 'yes',
|
|
249
|
+
choices: [
|
|
250
|
+
{ name: 'yes', value: true },
|
|
251
|
+
{ name: 'no', value: false }
|
|
252
|
+
]
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
if (shouldWrap) {
|
|
256
|
+
return wrapApplication(
|
|
257
|
+
logger,
|
|
258
|
+
inquirer,
|
|
259
|
+
packageManager,
|
|
260
|
+
module,
|
|
261
|
+
install,
|
|
262
|
+
process.cwd(),
|
|
263
|
+
additionalGeneratorOptions,
|
|
264
|
+
{ ...additionalGeneratorConfig, skipTypescript: true }
|
|
265
|
+
)
|
|
266
|
+
}
|
|
267
|
+
} else {
|
|
268
|
+
projectDir = dirname(existingRuntime)
|
|
269
|
+
shouldChooseProjectDir = false
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (shouldChooseProjectDir) {
|
|
129
275
|
const optionsDir = await inquirer.prompt({
|
|
130
276
|
type: 'input',
|
|
131
277
|
name: 'dir',
|
|
@@ -133,11 +279,11 @@ export async function createApplication (
|
|
|
133
279
|
default: 'platformatic'
|
|
134
280
|
})
|
|
135
281
|
|
|
136
|
-
projectDir =
|
|
282
|
+
projectDir = resolve(process.cwd(), optionsDir.dir)
|
|
283
|
+
await createDirectory(projectDir)
|
|
137
284
|
}
|
|
138
|
-
const projectName = basename(projectDir)
|
|
139
285
|
|
|
140
|
-
|
|
286
|
+
const projectName = basename(projectDir)
|
|
141
287
|
|
|
142
288
|
const runtime = await importOrLocal({
|
|
143
289
|
pkgManager: packageManager,
|
|
@@ -155,6 +301,7 @@ export async function createApplication (
|
|
|
155
301
|
|
|
156
302
|
generator.setConfig({
|
|
157
303
|
...generator.config,
|
|
304
|
+
...additionalGeneratorConfig,
|
|
158
305
|
targetDirectory: projectDir
|
|
159
306
|
})
|
|
160
307
|
|