create-platformatic 0.24.0 → 0.26.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-platformatic",
3
- "version": "0.24.0",
3
+ "version": "0.26.0",
4
4
  "description": "Create platformatic-db interactive tool",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,6 +15,7 @@
15
15
  "license": "Apache-2.0",
16
16
  "author": "Marco Piraccini <marco.piraccini@gmail.com>",
17
17
  "dependencies": {
18
+ "boring-name-generator": "^1.0.3",
18
19
  "chalk": "^5.2.0",
19
20
  "commist": "^3.2.0",
20
21
  "desm": "^1.3.0",
@@ -22,30 +23,30 @@
22
23
  "execa": "^7.1.1",
23
24
  "fastify": "^4.17.0",
24
25
  "help-me": "^4.2.0",
25
- "inquirer": "^9.2.0",
26
+ "inquirer": "^9.2.6",
26
27
  "log-update": "^5.0.1",
27
28
  "minimist": "^1.2.8",
28
- "mkdirp": "^2.1.6",
29
- "ora": "^6.3.0",
30
- "pino": "^8.12.0",
29
+ "ora": "^6.3.1",
30
+ "pino": "^8.14.1",
31
31
  "pino-pretty": "^10.0.0",
32
32
  "pupa": "^3.1.0",
33
- "semver": "^7.5.0",
34
- "undici": "^5.22.0",
35
- "@platformatic/config": "0.24.0"
33
+ "semver": "^7.5.1",
34
+ "undici": "^5.22.1",
35
+ "which": "^3.0.1",
36
+ "@platformatic/config": "0.26.0"
36
37
  },
37
38
  "devDependencies": {
38
39
  "ajv": "^8.12.0",
39
40
  "c8": "^7.13.0",
40
41
  "cross-env": "^7.0.3",
41
42
  "dotenv": "^16.0.3",
42
- "esmock": "^2.2.1",
43
+ "esmock": "^2.2.3",
43
44
  "snazzy": "^9.0.0",
44
45
  "standard": "^17.0.0",
45
46
  "tap": "^16.3.4",
46
47
  "yaml": "^2.2.2",
47
- "@platformatic/db": "0.24.0",
48
- "@platformatic/service": "0.24.0"
48
+ "@platformatic/db": "0.26.0",
49
+ "@platformatic/service": "0.26.0"
49
50
  },
50
51
  "scripts": {
51
52
  "test": "standard | snazzy && cross-env NODE_OPTIONS=\"--loader=esmock --no-warnings\" c8 --100 tap --no-coverage test/*test.mjs test/*/*test.mjs",
@@ -2,11 +2,11 @@ import { validatePath } from './utils.mjs'
2
2
  import inquirer from 'inquirer'
3
3
  import { resolve } from 'path'
4
4
 
5
- const askProjectDir = async (logger, defaultName) => {
5
+ const askProjectDir = async (logger, defaultName, message = 'Where would you like to create your project?') => {
6
6
  const options = await inquirer.prompt({
7
7
  type: 'input',
8
8
  name: 'dir',
9
- message: 'Where would you like to create your project?',
9
+ message,
10
10
  default: defaultName,
11
11
  validate: validatePath
12
12
  })
@@ -18,3 +18,17 @@ export const getUseTypescript = typescript => {
18
18
  choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
19
19
  }
20
20
  }
21
+
22
+ let port = 3042
23
+ export const getPort = (nextPort) => {
24
+ if (nextPort === undefined) {
25
+ nextPort = port++
26
+ }
27
+
28
+ return {
29
+ type: 'input',
30
+ name: 'port',
31
+ message: 'What port do you want to use?',
32
+ default: nextPort
33
+ }
34
+ }
@@ -0,0 +1,30 @@
1
+ # Platformatic Composer API
2
+
3
+ This is a generated [Platformatic Composer](https://oss.platformatic.dev/docs/reference/composer/introduction) application.
4
+
5
+ ## Requirements
6
+
7
+ Platformatic supports macOS, Linux and Windows ([WSL](https://docs.microsoft.com/windows/wsl/) recommended).
8
+ You'll need to have [Node.js](https://nodejs.org/) >= v18.8.0
9
+
10
+ ## Setup
11
+
12
+ 1. Install dependencies:
13
+
14
+ ```bash
15
+ npm install
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ Run the API with:
21
+
22
+ ```bash
23
+ npm start
24
+ ```
25
+
26
+ ### Explore
27
+ - ⚡ The Platformatic Composer server is running at http://localhost:3042/
28
+ - 📔 View the REST API's Swagger documentation at http://localhost:3042/documentation/
29
+
30
+
@@ -0,0 +1,107 @@
1
+ import { getVersion, getDependencyVersion, isFileAccessible } from '../utils.mjs'
2
+ import { createPackageJson } from '../create-package-json.mjs'
3
+ import { createGitignore } from '../create-gitignore.mjs'
4
+ import { getPkgManager } from '../get-pkg-manager.mjs'
5
+ import parseArgs from 'minimist'
6
+ import { join } from 'path'
7
+ import inquirer from 'inquirer'
8
+ import { readFile, writeFile, mkdir } from 'fs/promises'
9
+ import pino from 'pino'
10
+ import pretty from 'pino-pretty'
11
+ import { execa } from 'execa'
12
+ import ora from 'ora'
13
+ import createComposer from './create-composer.mjs'
14
+ import askDir from '../ask-dir.mjs'
15
+ import { askDynamicWorkspaceCreateGHAction, askStaticWorkspaceGHAction } from '../ghaction.mjs'
16
+ import { getRunPackageManagerInstall, getPort } from '../cli-options.mjs'
17
+
18
+ export const createReadme = async (logger, dir = '.') => {
19
+ const readmeFileName = join(dir, 'README.md')
20
+ let isReadmeExists = await isFileAccessible(readmeFileName)
21
+ if (isReadmeExists) {
22
+ logger.debug(`${readmeFileName} found, asking to overwrite it.`)
23
+ const { shouldReplace } = await inquirer.prompt([{
24
+ type: 'list',
25
+ name: 'shouldReplace',
26
+ message: 'Do you want to overwrite the existing README.md?',
27
+ default: true,
28
+ choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
29
+ }])
30
+ isReadmeExists = !shouldReplace
31
+ }
32
+
33
+ if (isReadmeExists) {
34
+ logger.debug(`${readmeFileName} found, skipping creation of README.md file.`)
35
+ return
36
+ }
37
+
38
+ const readmeFile = new URL('README.md', import.meta.url)
39
+ const readme = await readFile(readmeFile, 'utf-8')
40
+ await writeFile(readmeFileName, readme)
41
+ logger.debug(`${readmeFileName} successfully created.`)
42
+ }
43
+
44
+ const createPlatformaticComposer = async (_args, opts) => {
45
+ const logger = opts.logger || pino(pretty({
46
+ translateTime: 'SYS:HH:MM:ss',
47
+ ignore: 'hostname,pid'
48
+ }))
49
+
50
+ const args = parseArgs(_args, {
51
+ default: {
52
+ hostname: '127.0.0.1'
53
+ },
54
+ alias: {
55
+ h: 'hostname',
56
+ p: 'port'
57
+ }
58
+ })
59
+
60
+ const version = await getVersion()
61
+ const pkgManager = getPkgManager()
62
+
63
+ const projectDir = opts.dir || await askDir(logger, '.')
64
+
65
+ const toAsk = [getPort(args.port)]
66
+
67
+ if (!opts.skipPackageJson) {
68
+ toAsk.push(getRunPackageManagerInstall(pkgManager))
69
+ }
70
+
71
+ const { runPackageManagerInstall, port } = await inquirer.prompt(toAsk)
72
+
73
+ // Create the project directory
74
+ await mkdir(projectDir, { recursive: true })
75
+
76
+ const params = {
77
+ hostname: args.hostname,
78
+ port
79
+ }
80
+
81
+ const env = await createComposer(params, logger, projectDir, version)
82
+
83
+ const fastifyVersion = await getDependencyVersion('fastify')
84
+
85
+ // Create the package.json, notes that we don't have the option for TS (yet) so we don't generate
86
+ // the package.json with the TS build
87
+ if (!opts.skipPackageJson) {
88
+ await createPackageJson('composer', version, fastifyVersion, logger, projectDir, false)
89
+ }
90
+ if (!opts.skipGitignore) {
91
+ await createGitignore(logger, projectDir)
92
+ }
93
+ await createReadme(logger, projectDir)
94
+
95
+ if (runPackageManagerInstall) {
96
+ const spinner = ora('Installing dependencies...').start()
97
+ await execa(pkgManager, ['install'], { cwd: projectDir })
98
+ spinner.succeed('...done!')
99
+ }
100
+
101
+ if (!opts.skipGitHubActions) {
102
+ await askDynamicWorkspaceCreateGHAction(logger, env, 'composer', false, projectDir)
103
+ await askStaticWorkspaceGHAction(logger, env, 'composer', false, projectDir)
104
+ }
105
+ }
106
+
107
+ export default createPlatformaticComposer
@@ -0,0 +1,76 @@
1
+ import { readFile, writeFile, appendFile } from 'fs/promises'
2
+ import { findComposerConfigFile, isFileAccessible } from '../utils.mjs'
3
+ import { join } from 'path'
4
+ import * as desm from 'desm'
5
+
6
+ function generateConfig (version) {
7
+ const config = {
8
+ $schema: `https://platformatic.dev/schemas/v${version}/composer`,
9
+ server: {
10
+ hostname: '{PLT_SERVER_HOSTNAME}',
11
+ port: '{PORT}',
12
+ logger: {
13
+ level: '{PLT_SERVER_LOGGER_LEVEL}'
14
+ }
15
+ },
16
+ composer: {
17
+ services: [{
18
+ id: 'example',
19
+ origin: '{PLT_EXAMPLE_ORIGIN}',
20
+ openapi: {
21
+ url: '/documentation/json'
22
+ }
23
+ }],
24
+ refreshTimeout: 1000
25
+ },
26
+ watch: true
27
+ }
28
+
29
+ return config
30
+ }
31
+
32
+ function generateEnv (hostname, port) {
33
+ const env = `\
34
+ PLT_SERVER_HOSTNAME=${hostname}
35
+ PORT=${port}
36
+ PLT_SERVER_LOGGER_LEVEL=info
37
+ PLT_EXAMPLE_ORIGIN=
38
+ `
39
+
40
+ return env
41
+ }
42
+
43
+ async function createComposer ({ hostname, port }, logger, currentDir = process.cwd(), version) {
44
+ if (!version) {
45
+ const pkg = await readFile(desm.join(import.meta.url, '..', '..', 'package.json'))
46
+ version = JSON.parse(pkg).version
47
+ }
48
+ const accessibleConfigFilename = await findComposerConfigFile(currentDir)
49
+
50
+ if (accessibleConfigFilename === undefined) {
51
+ const config = generateConfig(version)
52
+ await writeFile(join(currentDir, 'platformatic.composer.json'), JSON.stringify(config, null, 2))
53
+ logger.info('Configuration file platformatic.composer.json successfully created.')
54
+
55
+ const env = generateEnv(hostname, port)
56
+ const envFileExists = await isFileAccessible('.env', currentDir)
57
+ await appendFile(join(currentDir, '.env'), env)
58
+ await writeFile(join(currentDir, '.env.sample'), env)
59
+ /* c8 ignore next 5 */
60
+ if (envFileExists) {
61
+ logger.info('Environment file .env found, appending new environment variables to existing .env file.')
62
+ } else {
63
+ logger.info('Environment file .env successfully created.')
64
+ }
65
+ } else {
66
+ logger.info(`Configuration file ${accessibleConfigFilename} found, skipping creation of configuration file.`)
67
+ }
68
+
69
+ return {
70
+ PLT_SERVER_LOGGER_LEVEL: 'info',
71
+ PORT: port,
72
+ PLT_SERVER_HOSTNAME: hostname
73
+ }
74
+ }
75
+
76
+ export default createComposer
@@ -5,16 +5,16 @@ import { getPkgManager } from '../get-pkg-manager.mjs'
5
5
  import parseArgs from 'minimist'
6
6
  import { join } from 'path'
7
7
  import inquirer from 'inquirer'
8
- import { readFile, writeFile } from 'fs/promises'
8
+ import which from 'which'
9
+ import { readFile, writeFile, mkdir } from 'fs/promises'
9
10
  import pino from 'pino'
10
11
  import pretty from 'pino-pretty'
11
12
  import { execa } from 'execa'
12
13
  import ora from 'ora'
13
14
  import createDB from './create-db.mjs'
14
- import askProjectDir from '../ask-project-dir.mjs'
15
+ import askDir from '../ask-dir.mjs'
15
16
  import { askDynamicWorkspaceCreateGHAction, askStaticWorkspaceGHAction } from '../ghaction.mjs'
16
- import { getRunPackageManagerInstall, getUseTypescript } from '../cli-options.mjs'
17
- import mkdirp from 'mkdirp'
17
+ import { getRunPackageManagerInstall, getUseTypescript, getPort } from '../cli-options.mjs'
18
18
 
19
19
  export const createReadme = async (logger, dir = '.') => {
20
20
  const readmeFileName = join(dir, 'README.md')
@@ -42,11 +42,10 @@ export const createReadme = async (logger, dir = '.') => {
42
42
  logger.debug(`${readmeFileName} successfully created.`)
43
43
  }
44
44
 
45
- export const parseDBArgs = (_args) => {
45
+ export function parseDBArgs (_args) {
46
46
  return parseArgs(_args, {
47
47
  default: {
48
48
  hostname: '127.0.0.1',
49
- port: 3042,
50
49
  database: 'sqlite',
51
50
  migrations: 'migrations',
52
51
  plugin: true,
@@ -66,8 +65,8 @@ export const parseDBArgs = (_args) => {
66
65
  })
67
66
  }
68
67
 
69
- const createPlatformaticDB = async (_args) => {
70
- const logger = pino(pretty({
68
+ const createPlatformaticDB = async (_args, opts) => {
69
+ const logger = opts.logger || pino(pretty({
71
70
  translateTime: 'SYS:HH:MM:ss',
72
71
  ignore: 'hostname,pid'
73
72
  }))
@@ -75,7 +74,7 @@ const createPlatformaticDB = async (_args) => {
75
74
  const args = parseDBArgs(_args)
76
75
  const version = await getVersion()
77
76
  const pkgManager = getPkgManager()
78
- const projectDir = await askProjectDir(logger, '.')
77
+ const projectDir = opts.dir || await askDir(logger, '.')
79
78
 
80
79
  const wizardOptions = await inquirer.prompt([{
81
80
  type: 'list',
@@ -90,11 +89,12 @@ const createPlatformaticDB = async (_args) => {
90
89
  default: args.plugin,
91
90
  choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
92
91
  },
93
- getUseTypescript(args.typescript)
92
+ getUseTypescript(args.typescript),
93
+ getPort(args.port)
94
94
  ])
95
95
 
96
96
  // Create the project directory
97
- await mkdirp(projectDir)
97
+ await mkdir(projectDir, { recursive: true })
98
98
 
99
99
  const generatePlugin = args.plugin || wizardOptions.generatePlugin
100
100
  const useTypescript = args.typescript || wizardOptions.useTypescript
@@ -102,7 +102,7 @@ const createPlatformaticDB = async (_args) => {
102
102
 
103
103
  const params = {
104
104
  hostname: args.hostname,
105
- port: args.port,
105
+ port: wizardOptions.port,
106
106
  database: args.database,
107
107
  migrations: wizardOptions.defaultMigrations ? args.migrations : '',
108
108
  plugin: generatePlugin,
@@ -119,17 +119,35 @@ const createPlatformaticDB = async (_args) => {
119
119
  await createGitignore(logger, projectDir)
120
120
  await createReadme(logger, projectDir)
121
121
 
122
- const { runPackageManagerInstall } = await inquirer.prompt([
123
- getRunPackageManagerInstall(pkgManager)
124
- ])
122
+ let hasPlatformaticInstalled = false
123
+ if (!opts.skipPackageJson) {
124
+ const { runPackageManagerInstall } = await inquirer.prompt([
125
+ getRunPackageManagerInstall(pkgManager)
126
+ ])
127
+
128
+ if (runPackageManagerInstall) {
129
+ const spinner = ora('Installing dependencies...').start()
130
+ await execa(pkgManager, ['install'], { cwd: projectDir })
131
+ spinner.succeed('...done!')
132
+ hasPlatformaticInstalled = true
133
+ }
134
+ }
135
+
136
+ if (!hasPlatformaticInstalled) {
137
+ try {
138
+ const npmLs = JSON.parse(await execa('npm', ['ls', '--json']))
139
+ hasPlatformaticInstalled = !!npmLs.dependencies.platformatic
140
+ } catch {
141
+ // Ignore all errors, this can fail
142
+ }
143
+ }
125
144
 
126
- if (runPackageManagerInstall) {
127
- const spinner = ora('Installing dependencies...').start()
128
- await execa(pkgManager, ['install'], { cwd: projectDir })
129
- spinner.succeed('...done!')
145
+ if (!hasPlatformaticInstalled) {
146
+ const exe = await which('platformatic', { noThrow: true })
147
+ hasPlatformaticInstalled = !!exe
130
148
  }
131
149
 
132
- if (runPackageManagerInstall) {
150
+ if (hasPlatformaticInstalled) {
133
151
  // We applied package manager install, so we can:
134
152
  // - run the migrations
135
153
  // - generate types
@@ -166,8 +184,11 @@ const createPlatformaticDB = async (_args) => {
166
184
  }
167
185
  }
168
186
  }
169
- await askDynamicWorkspaceCreateGHAction(logger, env, 'db', useTypescript, projectDir)
170
- await askStaticWorkspaceGHAction(logger, env, 'db', useTypescript, projectDir)
187
+
188
+ if (!opts.skipGitHubActions) {
189
+ await askDynamicWorkspaceCreateGHAction(logger, env, 'db', useTypescript, projectDir)
190
+ await askStaticWorkspaceGHAction(logger, env, 'db', useTypescript, projectDir)
191
+ }
171
192
  }
172
193
 
173
194
  export default createPlatformaticDB
package/src/ghaction.mjs CHANGED
@@ -1,10 +1,9 @@
1
- import mkdirp from 'mkdirp'
2
1
  import { join } from 'path'
3
2
  import inquirer from 'inquirer'
4
3
  import { isFileAccessible } from './utils.mjs'
5
- import { writeFile } from 'fs/promises'
4
+ import { writeFile, mkdir } from 'fs/promises'
6
5
 
7
- export const dynamicWorkspaceGHTemplate = (workspaceId, env, config, buildTS = false) => {
6
+ export const dynamicWorkspaceGHTemplate = (env, config, buildTS = false) => {
8
7
  const envAsStr = Object.keys(env).reduce((acc, key) => {
9
8
  acc += ` ${key}: ${env[key]} \n`
10
9
  return acc
@@ -36,7 +35,7 @@ jobs:
36
35
  uses: platformatic/onestep@latest
37
36
  with:
38
37
  github_token: \${{ secrets.GITHUB_TOKEN }}
39
- platformatic_workspace_id: ${workspaceId}
38
+ platformatic_workspace_id: \${{ secrets.PLATFORMATIC_DYNAMIC_WORKSPACE_ID }}
40
39
  platformatic_workspace_key: \${{ secrets.PLATFORMATIC_DYNAMIC_WORKSPACE_API_KEY }}
41
40
  platformatic_config_path: ${config}
42
41
  env:
@@ -44,7 +43,7 @@ ${envAsStr}
44
43
  `
45
44
  }
46
45
 
47
- export const staticWorkspaceGHTemplate = (workspaceId, env, config, buildTS = false) => {
46
+ export const staticWorkspaceGHTemplate = (env, config, buildTS = false) => {
48
47
  const envAsStr = Object.keys(env).reduce((acc, key) => {
49
48
  acc += ` ${key}: ${env[key]} \n`
50
49
  return acc
@@ -77,7 +76,7 @@ jobs:
77
76
  uses: platformatic/onestep@latest
78
77
  with:
79
78
  github_token: \${{ secrets.GITHUB_TOKEN }}
80
- platformatic_workspace_id: ${workspaceId}
79
+ platformatic_workspace_id: \${{ secrets.PLATFORMATIC_STATIC_WORKSPACE_ID }}
81
80
  platformatic_workspace_key: \${{ secrets.PLATFORMATIC_STATIC_WORKSPACE_API_KEY }}
82
81
  platformatic_config_path: ${config}
83
82
  env:
@@ -85,19 +84,14 @@ ${envAsStr}
85
84
  `
86
85
  }
87
86
 
88
- export const createDynamicWorkspaceGHAction = async (logger, workspaceId, env, config, projectDir, buildTS) => {
87
+ export const createDynamicWorkspaceGHAction = async (logger, env, config, projectDir, buildTS) => {
89
88
  const ghActionFileName = 'platformatic-dynamic-workspace-deploy.yml'
90
89
  const ghActionFilePath = join(projectDir, '.github', 'workflows', ghActionFileName)
91
90
  const isGithubActionExists = await isFileAccessible(ghActionFilePath)
92
91
  if (!isGithubActionExists) {
93
- if (!workspaceId) {
94
- logger.info('No workspace ID provided, skipping creation of github action file.')
95
- return
96
- }
97
-
98
- await mkdirp(join(projectDir, '.github', 'workflows'))
99
- await writeFile(ghActionFilePath, dynamicWorkspaceGHTemplate(workspaceId, env, config, buildTS))
100
- logger.info('Github action successfully created, please add PLATFORMATIC_DYNAMIC_WORKSPACE_API_KEY as repository secret.')
92
+ await mkdir(join(projectDir, '.github', 'workflows'), { recursive: true })
93
+ await writeFile(ghActionFilePath, dynamicWorkspaceGHTemplate(env, config, buildTS))
94
+ logger.info('Github action successfully created, please add PLATFORMATIC_DYNAMIC_WORKSPACE_ID and PLATFORMATIC_DYNAMIC_WORKSPACE_API_KEY as repository secrets.')
101
95
  const isGitDir = await isFileAccessible('.git', projectDir)
102
96
  if (!isGitDir) {
103
97
  logger.warn('No git repository found. The Github action won\'t be triggered.')
@@ -119,32 +113,20 @@ export const askDynamicWorkspaceCreateGHAction = async (logger, env, type, build
119
113
  }
120
114
  ])
121
115
  if (githubAction) {
122
- const { workspaceId } = await inquirer.prompt([
123
- {
124
- type: 'input',
125
- name: 'workspaceId',
126
- message: 'Please enter the workspace ID:'
127
- }
128
- ])
129
116
  const config = `./platformatic.${type}.json`
130
- await createDynamicWorkspaceGHAction(logger, workspaceId, env, config, projectDir, buildTS)
117
+ await createDynamicWorkspaceGHAction(logger, env, config, projectDir, buildTS)
131
118
  }
132
119
  /* c8 ignore next */
133
120
  }
134
121
 
135
- export const createStaticWorkspaceGHAction = async (logger, workspaceId, env, config, projectDir, buildTS) => {
122
+ export const createStaticWorkspaceGHAction = async (logger, env, config, projectDir, buildTS) => {
136
123
  const ghActionFileName = 'platformatic-static-workspace-deploy.yml'
137
124
  const ghActionFilePath = join(projectDir, '.github', 'workflows', ghActionFileName)
138
125
  const isGithubActionExists = await isFileAccessible(ghActionFilePath)
139
126
  if (!isGithubActionExists) {
140
- if (!workspaceId) {
141
- logger.info('No workspace ID provided, skipping creation of github action file.')
142
- return
143
- }
144
-
145
- await mkdirp(join(projectDir, '.github', 'workflows'))
146
- await writeFile(ghActionFilePath, staticWorkspaceGHTemplate(workspaceId, env, config, buildTS))
147
- logger.info('Github action successfully created, please add PLATFORMATIC_STATIC_WORKSPACE_API_KEY as repository secret.')
127
+ await mkdir(join(projectDir, '.github', 'workflows'), { recursive: true })
128
+ await writeFile(ghActionFilePath, staticWorkspaceGHTemplate(env, config, buildTS))
129
+ logger.info('Github action successfully created, please add PLATFORMATIC_STATIC_WORKSPACE_ID and PLATFORMATIC_STATIC_WORKSPACE_API_KEY as repository secret.')
148
130
  const isGitDir = await isFileAccessible('.git', projectDir)
149
131
  if (!isGitDir) {
150
132
  logger.warn('No git repository found. The Github action won\'t be triggered.')
@@ -166,15 +148,8 @@ export const askStaticWorkspaceGHAction = async (logger, env, type, buildTS, pro
166
148
  }
167
149
  ])
168
150
  if (githubAction) {
169
- const { workspaceId } = await inquirer.prompt([
170
- {
171
- type: 'input',
172
- name: 'workspaceId',
173
- message: 'Please enter the workspace ID:'
174
- }
175
- ])
176
151
  const config = `./platformatic.${type}.json`
177
- await createStaticWorkspaceGHAction(logger, workspaceId, env, config, projectDir, buildTS)
152
+ await createStaticWorkspaceGHAction(logger, env, config, projectDir, buildTS)
178
153
  }
179
154
  /* c8 ignore next */
180
155
  }
package/src/index.mjs CHANGED
@@ -2,10 +2,45 @@ import { say } from './say.mjs'
2
2
  import helpMe from 'help-me'
3
3
  import { join } from 'desm'
4
4
  import inquirer from 'inquirer'
5
+ import { readdir, readFile } from 'fs/promises'
5
6
  import createPlatformaticDB from './db/create-db-cli.mjs'
6
7
  import createPlatformaticService from './service/create-service-cli.mjs'
8
+ import createPlatformaticComposer from './composer/create-composer-cli.mjs'
9
+ import { createPlatformaticRuntime, createRuntimeService } from './runtime/create-runtime-cli.mjs'
7
10
  import commist from 'commist'
8
- import { getUsername, getVersion, minimumSupportedNodeVersions, isCurrentVersionSupported } from './utils.mjs'
11
+ import { getUsername, getVersion, minimumSupportedNodeVersions, isCurrentVersionSupported, findRuntimeConfigFile } from './utils.mjs'
12
+
13
+ export async function chooseKind (argv, opts = {}) {
14
+ const skip = opts.skip
15
+ const choices = [
16
+ { name: 'DB', value: 'db' },
17
+ { name: 'Service', value: 'service' },
18
+ { name: 'Composer', value: 'composer' },
19
+ { name: 'Runtime', value: 'runtime' }
20
+ ].filter((choice) => !skip || choice.value !== skip)
21
+
22
+ const options = await inquirer.prompt({
23
+ type: 'list',
24
+ name: 'type',
25
+ message: 'Which kind of project do you want to create?',
26
+ choices
27
+ })
28
+
29
+ switch (options.type) {
30
+ case 'db':
31
+ await createPlatformaticDB(argv, opts)
32
+ break
33
+ case 'service':
34
+ await createPlatformaticService(argv, opts)
35
+ break
36
+ case 'composer':
37
+ await createPlatformaticComposer(argv, opts)
38
+ break
39
+ case 'runtime':
40
+ await createPlatformaticRuntime(argv, opts)
41
+ break
42
+ }
43
+ }
9
44
 
10
45
  const createPlatformatic = async (argv) => {
11
46
  const help = helpMe({
@@ -20,6 +55,8 @@ const createPlatformatic = async (argv) => {
20
55
  program.register('service help', help.toStdout.bind(null, ['service']))
21
56
  program.register('db', createPlatformaticDB)
22
57
  program.register('service', createPlatformaticService)
58
+ program.register('composer', createPlatformaticComposer)
59
+ program.register('runtime', createPlatformaticRuntime)
23
60
 
24
61
  const result = program.parse(argv)
25
62
 
@@ -28,7 +65,6 @@ const createPlatformatic = async (argv) => {
28
65
  const version = await getVersion()
29
66
  const greeting = username ? `Hello, ${username}` : 'Hello,'
30
67
  await say(`${greeting} welcome to ${version ? `Platformatic ${version}!` : 'Platformatic!'}`)
31
- await say('Let\'s start by creating a new project.')
32
68
 
33
69
  const currentVersion = process.versions.node
34
70
  const supported = isCurrentVersionSupported(currentVersion)
@@ -38,18 +74,26 @@ const createPlatformatic = async (argv) => {
38
74
  await say(`Please use one of the following Node.js versions >= ${supportedVersions}.`)
39
75
  }
40
76
 
41
- const options = await inquirer.prompt({
42
- type: 'list',
43
- name: 'type',
44
- message: 'Which kind of project do you want to create?',
45
- default: 'db',
46
- choices: [{ name: 'DB', value: 'db' }, { name: 'Service', value: 'service' }]
47
- })
48
-
49
- if (options.type === 'db') {
50
- await createPlatformaticDB(argv)
51
- } else if (options.type === 'service') {
52
- await createPlatformaticService(argv)
77
+ const runtimeConfig = await findRuntimeConfigFile(process.cwd())
78
+ if (runtimeConfig) {
79
+ await say(`Found a ${runtimeConfig} file in the current directory.`)
80
+ const config = JSON.parse(await readFile(runtimeConfig, 'utf8'))
81
+ if (config.autoload?.path) {
82
+ const servicesDir = config.autoload.path
83
+ const names = []
84
+ for (const entry of await readdir(servicesDir)) {
85
+ names.push(entry)
86
+ }
87
+ if (!await createRuntimeService({ servicesDir, names })) {
88
+ process.exit(1)
89
+ }
90
+ } else {
91
+ await say('The current project does not have a services directory.')
92
+ process.exit(1)
93
+ }
94
+ } else {
95
+ await say('Let\'s start by creating a new project.')
96
+ await chooseKind(argv)
53
97
  }
54
98
 
55
99
  await say('\nAll done! Please open the project directory and check the README.')