create-platformatic 1.3.0 → 1.4.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": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Create platformatic-db interactive tool",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,7 +35,7 @@
35
35
  "strip-ansi": "^7.1.0",
36
36
  "undici": "^5.25.4",
37
37
  "which": "^3.0.1",
38
- "@platformatic/config": "1.3.0"
38
+ "@platformatic/config": "1.4.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "ajv": "^8.12.0",
@@ -48,12 +48,13 @@
48
48
  "tap": "^16.3.9",
49
49
  "typescript": "~5.2.2",
50
50
  "yaml": "^2.3.2",
51
- "@platformatic/db": "1.3.0",
52
- "@platformatic/service": "1.3.0"
51
+ "@platformatic/db": "1.4.0",
52
+ "@platformatic/service": "1.4.0"
53
53
  },
54
54
  "scripts": {
55
55
  "test:cli": "tap --no-coverage test/cli/*test.mjs -t120",
56
- "test": "standard | snazzy && cross-env NODE_OPTIONS=\"--loader=esmock --no-warnings\" c8 tap --no-coverage test/*test.mjs test/*[!cli]/*test.mjs && npm run test:cli",
56
+ "test:unit": "standard | snazzy && cross-env NODE_OPTIONS=\"--loader=esmock --no-warnings\" c8 tap --no-coverage test/*test.mjs test/*[!cli]/*test.mjs",
57
+ "test": "npm run test:unit && npm run test:cli",
57
58
  "lint": "standard | snazzy"
58
59
  }
59
60
  }
package/src/ask-dir.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ import { stat } from 'fs/promises'
3
4
  import inquirer from 'inquirer'
4
5
  import { resolve } from 'path'
5
6
 
@@ -12,6 +13,24 @@ const askProjectDir = async (logger, defaultName, message = 'Where would you lik
12
13
  })
13
14
 
14
15
  const projectDir = resolve(process.cwd(), options.dir)
16
+
17
+ try {
18
+ await stat(projectDir)
19
+ logger.warn(`Directory ${projectDir} is not empty. Some files may be overwritten without confirmation.`)
20
+ const confirmation = await inquirer.prompt({
21
+ type: 'list',
22
+ name: 'confirmExistingDirectory',
23
+ message: `Confirm you want to use ${projectDir} directory?`,
24
+ default: 'no',
25
+ choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
26
+ })
27
+ if (!confirmation.confirmExistingDirectory) {
28
+ logger.error('Please choose another directory.')
29
+ process.exit(1)
30
+ }
31
+ } catch (err) {
32
+ // directory is empty, we can proceed
33
+ }
15
34
  return projectDir
16
35
  }
17
36
 
@@ -1,10 +1,9 @@
1
- import { getVersion, getDependencyVersion } from '../utils.mjs'
1
+ import { getVersion, getDependencyVersion, safeMkdir } from '../utils.mjs'
2
2
  import { createPackageJson } from '../create-package-json.mjs'
3
3
  import { createGitignore } from '../create-gitignore.mjs'
4
4
  import { getPkgManager } from '../get-pkg-manager.mjs'
5
5
  import parseArgs from 'minimist'
6
6
  import inquirer from 'inquirer'
7
- import { mkdir } from 'fs/promises'
8
7
  import pino from 'pino'
9
8
  import pretty from 'pino-pretty'
10
9
  import { execa } from 'execa'
@@ -13,7 +12,6 @@ import createComposer from './create-composer.mjs'
13
12
  import askDir from '../ask-dir.mjs'
14
13
  import { getRunPackageManagerInstall, getPort, getUseTypescript, getInitGitRepository } from '../cli-options.mjs'
15
14
  import { createReadme } from '../create-readme.mjs'
16
- import { stat } from 'node:fs/promises'
17
15
  import { join } from 'path'
18
16
 
19
17
  export const getServicesToCompose = (servicesNames) => {
@@ -46,13 +44,6 @@ const createPlatformaticComposer = async (_args, opts) => {
46
44
  const pkgManager = getPkgManager()
47
45
 
48
46
  const projectDir = opts.dir || await askDir(logger, join('.', 'platformatic-composer'))
49
- // checks directory
50
- try {
51
- await stat(projectDir)
52
- logger.error(`Directory ${projectDir} already exists. Please choose another path.`)
53
- process.exit(1)
54
- } catch (err) {}
55
-
56
47
  const isRuntimeContext = opts.isRuntimeContext || false
57
48
 
58
49
  const toAsk = []
@@ -106,7 +97,7 @@ const createPlatformaticComposer = async (_args, opts) => {
106
97
  } = await inquirer.prompt(toAsk)
107
98
 
108
99
  // Create the project directory
109
- await mkdir(projectDir, { recursive: true })
100
+ await safeMkdir(projectDir)
110
101
 
111
102
  const params = {
112
103
  isRuntimeContext,
@@ -1,5 +1,4 @@
1
1
  import { readFile, writeFile, appendFile } from 'fs/promises'
2
- import { findComposerConfigFile, isFileAccessible } from '../utils.mjs'
3
2
  import { join } from 'path'
4
3
  import * as desm from 'desm'
5
4
  import { generatePlugins, generateRouteWithTypesSupport } from '../create-plugins.mjs'
@@ -107,28 +106,17 @@ async function createComposer (
107
106
  const pkg = await readFile(desm.join(import.meta.url, '..', '..', 'package.json'))
108
107
  version = JSON.parse(pkg).version
109
108
  }
110
- const accessibleConfigFilename = await findComposerConfigFile(currentDir)
111
-
112
- if (accessibleConfigFilename === undefined) {
113
- const envPrefix = runtimeContext !== undefined ? `${runtimeContext.envPrefix}_` : ''
114
-
115
- const config = generateConfig(isRuntimeContext, version, servicesToCompose, typescript, envPrefix)
116
- await writeFile(join(currentDir, 'platformatic.composer.json'), JSON.stringify(config, null, 2))
117
- logger.info('Configuration file platformatic.composer.json successfully created.')
118
-
119
- const env = generateEnv(isRuntimeContext, hostname, port, typescript, envPrefix)
120
- const envFileExists = await isFileAccessible('.env', currentDir)
121
- await appendFile(join(currentDir, '.env'), env)
122
- await writeFile(join(currentDir, '.env.sample'), env)
123
- /* c8 ignore next 5 */
124
- if (envFileExists) {
125
- logger.info('Environment file .env found, appending new environment variables to existing .env file.')
126
- } else {
127
- logger.info('Environment file .env successfully created.')
128
- }
129
- } else {
130
- logger.info(`Configuration file ${accessibleConfigFilename} found, skipping creation of configuration file.`)
131
- }
109
+ const envPrefix = runtimeContext !== undefined ? `${runtimeContext.envPrefix}_` : ''
110
+
111
+ const config = generateConfig(isRuntimeContext, version, servicesToCompose, typescript, envPrefix)
112
+ await writeFile(join(currentDir, 'platformatic.composer.json'), JSON.stringify(config, null, 2))
113
+ logger.info('Configuration file platformatic.composer.json successfully created.')
114
+
115
+ const env = generateEnv(isRuntimeContext, hostname, port, typescript, envPrefix)
116
+ await appendFile(join(currentDir, '.env'), env)
117
+ await writeFile(join(currentDir, '.env.sample'), env)
118
+ /* c8 ignore next 5 */
119
+ logger.info('Environment file .env successfully created.')
132
120
  await generatePlugins(logger, currentDir, typescript, 'composer')
133
121
  await generateRouteWithTypesSupport(logger, currentDir, true)
134
122
 
@@ -1,4 +1,3 @@
1
- import { isFileAccessible } from './utils.mjs'
2
1
  import { writeFile } from 'fs/promises'
3
2
  import { join } from 'node:path'
4
3
 
@@ -38,11 +37,6 @@ tags
38
37
  */
39
38
  export const createGitignore = async (logger, dir = '.') => {
40
39
  const gitignoreFileName = join(dir, '.gitignore')
41
- const isGitignoreExists = await isFileAccessible(gitignoreFileName)
42
- if (!isGitignoreExists) {
43
- await writeFile(gitignoreFileName, gitignore)
44
- logger.debug(`Gitignore file ${gitignoreFileName} successfully created.`)
45
- } else {
46
- logger.debug(`Gitignore file ${gitignoreFileName} found, skipping creation of gitignore file.`)
47
- }
40
+ await writeFile(gitignoreFileName, gitignore)
41
+ logger.debug(`Gitignore file ${gitignoreFileName} successfully created.`)
48
42
  }
@@ -1,4 +1,3 @@
1
- import { isFileAccessible } from './utils.mjs'
2
1
  import { writeFile, readFile } from 'fs/promises'
3
2
  import { join } from 'node:path'
4
3
  import { fileURLToPath } from 'node:url'
@@ -50,14 +49,9 @@ const packageJsonTemplate = async (addTSBuild, fastifyVersion, platVersion) => {
50
49
  */
51
50
  export const createPackageJson = async (platVersion, fastifyVersion, logger, dir, addTSBuild = false, scripts = {}, dependencies = {}) => {
52
51
  const packageJsonFileName = join(dir, 'package.json')
53
- const isPackageJsonExists = await isFileAccessible(packageJsonFileName)
54
- if (!isPackageJsonExists) {
55
- const pkg = await packageJsonTemplate(addTSBuild, fastifyVersion, platVersion)
56
- Object.assign(pkg.scripts, scripts)
57
- Object.assign(pkg.dependencies, dependencies)
58
- await writeFile(packageJsonFileName, JSON.stringify(pkg, null, 2))
59
- logger.debug(`${packageJsonFileName} successfully created.`)
60
- } else {
61
- logger.debug(`${packageJsonFileName} found, skipping creation of package.json file.`)
62
- }
52
+ const pkg = await packageJsonTemplate(addTSBuild, fastifyVersion, platVersion)
53
+ Object.assign(pkg.scripts, scripts)
54
+ Object.assign(pkg.dependencies, dependencies)
55
+ await writeFile(packageJsonFileName, JSON.stringify(pkg, null, 2))
56
+ logger.debug(`${packageJsonFileName} successfully created.`)
63
57
  }
@@ -1,6 +1,6 @@
1
1
  import { join } from 'path'
2
- import { writeFile, mkdir } from 'fs/promises'
3
- import { isFileAccessible } from './utils.mjs'
2
+ import { writeFile } from 'fs/promises'
3
+ import { safeMkdir } from './utils.mjs'
4
4
 
5
5
  const JS_PLUGIN_WITH_TYPES_SUPPORT = `\
6
6
  /// <reference path="../global.d.ts" />
@@ -168,12 +168,7 @@ test('example decorator', async (t) => {
168
168
  `
169
169
 
170
170
  export async function generatePluginWithTypesSupport (logger, currentDir, isTypescript) {
171
- const accessible = await isFileAccessible('plugins', currentDir)
172
- if (accessible) {
173
- logger.info('Plugins folder "plugins" found, skipping creation of plugins folder.')
174
- return
175
- }
176
- await mkdir(join(currentDir, 'plugins'))
171
+ await safeMkdir(join(currentDir, 'plugins'))
177
172
  const pluginTemplate = isTypescript
178
173
  ? TS_PLUGIN_WITH_TYPES_SUPPORT
179
174
  : JS_PLUGIN_WITH_TYPES_SUPPORT
@@ -185,12 +180,7 @@ export async function generatePluginWithTypesSupport (logger, currentDir, isType
185
180
  }
186
181
 
187
182
  export async function generateRouteWithTypesSupport (logger, currentDir, isTypescript) {
188
- const accessible = await isFileAccessible('routes', currentDir)
189
- if (accessible) {
190
- logger.info('Routes folder "routes" found, skipping creation of routes folder.')
191
- return
192
- }
193
- await mkdir(join(currentDir, 'routes'))
183
+ await safeMkdir(join(currentDir, 'routes'))
194
184
  const routesTemplate = isTypescript
195
185
  ? TS_ROUTES_WITH_TYPES_SUPPORT
196
186
  : JS_ROUTES_WITH_TYPES_SUPPORT
@@ -202,15 +192,9 @@ export async function generateRouteWithTypesSupport (logger, currentDir, isTypes
202
192
  }
203
193
 
204
194
  export async function generateTests (logger, currentDir, isTypescript, mod, customizations) {
205
- const accessible = await isFileAccessible('tests', currentDir)
206
- if (accessible) {
207
- logger.info('Test folder found, skipping creation of tests.')
208
- return
209
- }
210
-
211
- await mkdir(join(currentDir, 'test'))
212
- await mkdir(join(currentDir, 'test', 'plugins'))
213
- await mkdir(join(currentDir, 'test', 'routes'))
195
+ await safeMkdir(join(currentDir, 'test'))
196
+ await safeMkdir(join(currentDir, 'test', 'plugins'))
197
+ await safeMkdir(join(currentDir, 'test', 'routes'))
214
198
 
215
199
  if (isTypescript) {
216
200
  await writeFile(join(currentDir, 'test', 'helper.ts'), testHelperTS(mod, customizations))
@@ -1,11 +1,10 @@
1
- import { getVersion, getDependencyVersion } from '../utils.mjs'
1
+ import { getVersion, getDependencyVersion, safeMkdir } from '../utils.mjs'
2
2
  import { createPackageJson } from '../create-package-json.mjs'
3
3
  import { createGitignore } from '../create-gitignore.mjs'
4
4
  import { getPkgManager } from '../get-pkg-manager.mjs'
5
5
  import parseArgs from 'minimist'
6
6
  import inquirer from 'inquirer'
7
7
  import which from 'which'
8
- import { mkdir, stat } from 'fs/promises'
9
8
  import pino from 'pino'
10
9
  import pretty from 'pino-pretty'
11
10
  import { execa } from 'execa'
@@ -61,13 +60,6 @@ const createPlatformaticDB = async (_args, opts) => {
61
60
  const pkgManager = getPkgManager()
62
61
  const projectDir = opts.dir || await askDir(logger, join('.', 'platformatic-db'))
63
62
 
64
- // Create the project directory
65
- try {
66
- await stat(projectDir)
67
- logger.error(`Directory ${projectDir} already exists. Please choose another path.`)
68
- process.exit(1)
69
- } catch (err) {}
70
-
71
63
  const isRuntimeContext = opts.isRuntimeContext || false
72
64
  const toAsk = []
73
65
 
@@ -175,7 +167,7 @@ const createPlatformaticDB = async (_args, opts) => {
175
167
  // Prompt for questions
176
168
  const wizardOptions = await inquirer.prompt(toAsk)
177
169
 
178
- await mkdir(projectDir, { recursive: true })
170
+ await safeMkdir(projectDir)
179
171
 
180
172
  const generatePlugin = args.plugin || wizardOptions.generatePlugin
181
173
  const useTypescript = args.typescript || wizardOptions.useTypescript
@@ -1,6 +1,6 @@
1
- import { writeFile, mkdir, appendFile } from 'fs/promises'
1
+ import { writeFile, appendFile } from 'fs/promises'
2
2
  import { join } from 'path'
3
- import { addPrefixToEnv, findDBConfigFile, isFileAccessible } from '../utils.mjs'
3
+ import { addPrefixToEnv, safeMkdir } from '../utils.mjs'
4
4
  import { getTsConfig } from '../get-tsconfig.mjs'
5
5
  import { generatePlugins } from '../create-plugins.mjs'
6
6
  import { createDynamicWorkspaceGHAction, createStaticWorkspaceGHAction } from '../ghaction.mjs'
@@ -366,56 +366,33 @@ export async function createDB (params, logger, currentDir, version) {
366
366
  }
367
367
  connectionString = connectionString || getConnectionString(database)
368
368
  const createMigrations = !!migrations // If we don't define a migrations folder, we don't create it
369
- const accessibleConfigFilename = await findDBConfigFile(currentDir)
370
-
371
- if (accessibleConfigFilename === undefined) {
372
- const envPrefix = runtimeContext !== undefined ? `${runtimeContext.envPrefix}_` : ''
373
-
374
- const config = generateConfig(isRuntimeContext, migrations, plugin, types, typescript, version, envPrefix)
375
- await writeFile(join(currentDir, 'platformatic.db.json'), JSON.stringify(config, null, 2))
376
- logger.info('Configuration file platformatic.db.json successfully created.')
377
-
378
- const env = generateEnv(isRuntimeContext, hostname, port, connectionString, typescript, envPrefix)
379
- const envSample = generateEnv(isRuntimeContext, hostname, port, getConnectionString(database), typescript, envPrefix)
380
- const envFileExists = await isFileAccessible('.env', currentDir)
381
- await appendFile(join(currentDir, '.env'), env)
382
- await writeFile(join(currentDir, '.env.sample'), envSample)
383
- /* c8 ignore next 5 */
384
- if (envFileExists) {
385
- logger.info('Environment file .env found, appending new environment variables to existing .env file.')
386
- } else {
387
- logger.info('Environment file .env successfully created.')
388
- }
389
- } else {
390
- logger.info(`Configuration file ${accessibleConfigFilename} found, skipping creation of configuration file.`)
391
- }
369
+ const envPrefix = runtimeContext !== undefined ? `${runtimeContext.envPrefix}_` : ''
370
+
371
+ const config = generateConfig(isRuntimeContext, migrations, plugin, types, typescript, version, envPrefix)
372
+ await writeFile(join(currentDir, 'platformatic.db.json'), JSON.stringify(config, null, 2))
373
+ logger.info('Configuration file platformatic.db.json successfully created.')
374
+
375
+ const env = generateEnv(isRuntimeContext, hostname, port, connectionString, typescript, envPrefix)
376
+ const envSample = generateEnv(isRuntimeContext, hostname, port, getConnectionString(database), typescript, envPrefix)
377
+ await appendFile(join(currentDir, '.env'), env)
378
+ await writeFile(join(currentDir, '.env.sample'), envSample)
379
+ logger.info('Environment file .env found, appending new environment variables to existing .env file.')
392
380
 
393
381
  const migrationsFolderName = migrations
394
382
  if (createMigrations) {
395
- const isMigrationFolderExists = await isFileAccessible(migrationsFolderName, currentDir)
396
- if (!isMigrationFolderExists) {
397
- await mkdir(join(currentDir, migrationsFolderName), { recursive: true })
398
- logger.info(`Migrations folder ${migrationsFolderName} successfully created.`)
399
- } else {
400
- logger.info(`Migrations folder ${migrationsFolderName} found, skipping creation of migrations folder.`)
401
- }
383
+ await safeMkdir(join(currentDir, migrationsFolderName))
384
+ logger.info(`Migrations folder ${migrationsFolderName} successfully created.`)
402
385
  }
403
386
 
404
387
  const migrationFileNameDo = '001.do.sql'
405
388
  const migrationFileNameUndo = '001.undo.sql'
406
389
  const migrationFilePathDo = join(currentDir, migrationsFolderName, migrationFileNameDo)
407
390
  const migrationFilePathUndo = join(currentDir, migrationsFolderName, migrationFileNameUndo)
408
- const isMigrationFileDoExists = await isFileAccessible(migrationFilePathDo)
409
- const isMigrationFileUndoExists = await isFileAccessible(migrationFilePathUndo)
410
- if (!isMigrationFileDoExists && createMigrations) {
391
+ if (createMigrations) {
411
392
  await writeFile(migrationFilePathDo, moviesMigrationDo(database))
412
393
  logger.info(`Migration file ${migrationFileNameDo} successfully created.`)
413
- if (!isMigrationFileUndoExists) {
414
- await writeFile(migrationFilePathUndo, moviesMigrationUndo)
415
- logger.info(`Migration file ${migrationFileNameUndo} successfully created.`)
416
- }
417
- } else {
418
- logger.info(`Migration file ${migrationFileNameDo} found, skipping creation of migration file.`)
394
+ await writeFile(migrationFilePathUndo, moviesMigrationUndo)
395
+ logger.info(`Migration file ${migrationFileNameUndo} successfully created.`)
419
396
  }
420
397
 
421
398
  if (typescript === true) {
package/src/ghaction.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { join } from 'path'
2
- import { isFileAccessible } from './utils.mjs'
3
- import { writeFile, mkdir } from 'fs/promises'
2
+ import { isFileAccessible, safeMkdir } from './utils.mjs'
3
+ import { writeFile } from 'fs/promises'
4
4
  import columnify from 'columnify'
5
5
  function envAsString (env, indent) {
6
6
  const spaces = Array(indent * 2).join(' ')
@@ -125,49 +125,39 @@ ${envString}
125
125
  export const createDynamicWorkspaceGHAction = async (logger, env, config, projectDir, buildTS) => {
126
126
  const ghActionFileName = 'platformatic-dynamic-workspace-deploy.yml'
127
127
  const ghActionFilePath = join(projectDir, '.github', 'workflows', ghActionFileName)
128
- const isGithubActionExists = await isFileAccessible(ghActionFilePath)
129
- if (!isGithubActionExists) {
130
- await mkdir(join(projectDir, '.github', 'workflows'), { recursive: true })
131
- await writeFile(ghActionFilePath, dynamicWorkspaceGHTemplate(env, config, buildTS))
132
- logger.info('PR Previews are enabled for your app and the Github action was successfully created, please add the following secrets as repository secrets: ')
133
- const envToBeAdded = { ...env }
134
- delete envToBeAdded.PORT
135
- const secretsString = formatSecretsToAdd({
136
- PLATFORMATIC_DYNAMIC_WORKSPACE_ID: 'your workspace id',
137
- PLATFORMATIC_DYNAMIC_WORKSPACE_API_KEY: 'your workspace API key',
138
- ...envToBeAdded
139
- })
140
- logger.info(`\n ${secretsString}`)
141
- const isGitDir = await isFileAccessible('.git', projectDir)
142
- if (!isGitDir) {
143
- logger.warn('No git repository found. The Github action won\'t be triggered.')
144
- }
145
- } else {
146
- logger.info(`Github action file ${ghActionFilePath} found, skipping creation of github action file.`)
128
+ await safeMkdir(join(projectDir, '.github', 'workflows'), { recursive: true })
129
+ await writeFile(ghActionFilePath, dynamicWorkspaceGHTemplate(env, config, buildTS))
130
+ logger.info('PR Previews are enabled for your app and the Github action was successfully created, please add the following secrets as repository secrets: ')
131
+ const envToBeAdded = { ...env }
132
+ delete envToBeAdded.PORT
133
+ const secretsString = formatSecretsToAdd({
134
+ PLATFORMATIC_DYNAMIC_WORKSPACE_ID: 'your workspace id',
135
+ PLATFORMATIC_DYNAMIC_WORKSPACE_API_KEY: 'your workspace API key',
136
+ ...envToBeAdded
137
+ })
138
+ logger.info(`\n ${secretsString}`)
139
+ const isGitDir = await isFileAccessible('.git', projectDir)
140
+ if (!isGitDir) {
141
+ logger.warn('No git repository found. The Github action won\'t be triggered.')
147
142
  }
148
143
  }
149
144
 
150
145
  export const createStaticWorkspaceGHAction = async (logger, env, config, projectDir, buildTS) => {
151
146
  const ghActionFileName = 'platformatic-static-workspace-deploy.yml'
152
147
  const ghActionFilePath = join(projectDir, '.github', 'workflows', ghActionFileName)
153
- const isGithubActionExists = await isFileAccessible(ghActionFilePath)
154
- if (!isGithubActionExists) {
155
- await mkdir(join(projectDir, '.github', 'workflows'), { recursive: true })
156
- await writeFile(ghActionFilePath, staticWorkspaceGHTemplate(env, config, buildTS))
157
- logger.info('Github action successfully created, please add the following secrets as repository secrets: ')
158
- const envToBeAdded = { ...env }
159
- delete envToBeAdded.PORT
160
- const secretsString = formatSecretsToAdd({
161
- PLATFORMATIC_STATIC_WORKSPACE_ID: 'your workspace id',
162
- PLATFORMATIC_STATIC_WORKSPACE_API_KEY: 'your workspace API key',
163
- ...envToBeAdded
164
- })
165
- logger.info(`\n ${secretsString}`)
166
- const isGitDir = await isFileAccessible('.git', projectDir)
167
- if (!isGitDir) {
168
- logger.warn('No git repository found. The Github action won\'t be triggered.')
169
- }
170
- } else {
171
- logger.info(`Github action file ${ghActionFilePath} found, skipping creation of github action file.`)
148
+ await safeMkdir(join(projectDir, '.github', 'workflows'), { recursive: true })
149
+ await writeFile(ghActionFilePath, staticWorkspaceGHTemplate(env, config, buildTS))
150
+ logger.info('Github action successfully created, please add the following secrets as repository secrets: ')
151
+ const envToBeAdded = { ...env }
152
+ delete envToBeAdded.PORT
153
+ const secretsString = formatSecretsToAdd({
154
+ PLATFORMATIC_STATIC_WORKSPACE_ID: 'your workspace id',
155
+ PLATFORMATIC_STATIC_WORKSPACE_API_KEY: 'your workspace API key',
156
+ ...envToBeAdded
157
+ })
158
+ logger.info(`\n ${secretsString}`)
159
+ const isGitDir = await isFileAccessible('.git', projectDir)
160
+ if (!isGitDir) {
161
+ logger.warn('No git repository found. The Github action won\'t be triggered.')
172
162
  }
173
163
  }
@@ -1,10 +1,9 @@
1
- import { getVersion, getDependencyVersion, convertServiceNameToPrefix } from '../utils.mjs'
1
+ import { getVersion, getDependencyVersion, convertServiceNameToPrefix, safeMkdir } from '../utils.mjs'
2
2
  import { createPackageJson } from '../create-package-json.mjs'
3
3
  import { createGitignore } from '../create-gitignore.mjs'
4
4
  import { getPkgManager } from '../get-pkg-manager.mjs'
5
5
  import { join, relative, resolve } from 'path'
6
6
  import inquirer from 'inquirer'
7
- import { mkdir, stat } from 'fs/promises'
8
7
  import pino from 'pino'
9
8
  import pretty from 'pino-pretty'
10
9
  import { execa } from 'execa'
@@ -27,15 +26,9 @@ export async function createPlatformaticRuntime (_args) {
27
26
 
28
27
  const projectDir = await askDir(logger, join('.', 'platformatic-runtime'))
29
28
 
30
- // checks directory
31
- try {
32
- await stat(projectDir)
33
- logger.error(`Directory ${projectDir} already exists. Please choose another path.`)
34
- process.exit(1)
35
- } catch (err) {}
36
29
  const toAsk = []
37
30
  // Create the project directory
38
- await mkdir(projectDir, { recursive: true })
31
+ await safeMkdir(projectDir)
39
32
 
40
33
  const baseServicesDir = join(relative(process.cwd(), projectDir), 'services')
41
34
  const servicesDir = await askDir(logger, baseServicesDir, 'Where would you like to load your services from?')
@@ -75,7 +68,7 @@ export async function createPlatformaticRuntime (_args) {
75
68
  initGitRepository
76
69
  } = await inquirer.prompt(toAsk)
77
70
 
78
- await mkdir(servicesDir, { recursive: true })
71
+ await safeMkdir(servicesDir)
79
72
 
80
73
  const fastifyVersion = await getDependencyVersion('fastify')
81
74
 
@@ -1,5 +1,4 @@
1
1
  import { readFile, writeFile, readdir, unlink } from 'fs/promises'
2
- import { findRuntimeConfigFile } from '../utils.mjs'
3
2
  import { join, relative, isAbsolute } from 'path'
4
3
  import * as desm from 'desm'
5
4
  import { createDynamicWorkspaceGHAction, createStaticWorkspaceGHAction } from '../ghaction.mjs'
@@ -29,21 +28,14 @@ async function createRuntime (params, logger, currentDir = process.cwd(), versio
29
28
  dynamicWorkspaceGitHubAction,
30
29
  initGitRepository
31
30
  } = params
32
- console.log('@@@@@@@@@@@@@@@@', params)
33
31
  if (!version) {
34
32
  const pkg = await readFile(desm.join(import.meta.url, '..', '..', 'package.json'))
35
33
  version = JSON.parse(pkg).version
36
34
  }
37
- const accessibleConfigFilename = await findRuntimeConfigFile(currentDir)
38
-
39
- if (accessibleConfigFilename === undefined) {
40
- const path = isAbsolute(servicesDir) ? relative(currentDir, servicesDir) : servicesDir
41
- const config = generateConfig(version, path, entrypoint)
42
- await writeFile(join(currentDir, 'platformatic.runtime.json'), JSON.stringify(config, null, 2))
43
- logger.info('Configuration file platformatic.runtime.json successfully created.')
44
- } else {
45
- logger.info(`Configuration file ${accessibleConfigFilename} found, skipping creation of configuration file.`)
46
- }
35
+ const path = isAbsolute(servicesDir) ? relative(currentDir, servicesDir) : servicesDir
36
+ const config = generateConfig(version, path, entrypoint)
37
+ await writeFile(join(currentDir, 'platformatic.runtime.json'), JSON.stringify(config, null, 2))
38
+ logger.info('Configuration file platformatic.runtime.json successfully created.')
47
39
  let runtimeEnv = {}
48
40
  if (servicesDir && entrypoint && entrypointPort) {
49
41
  const servicesDirFullPath = isAbsolute(servicesDir)
@@ -1,11 +1,10 @@
1
- import { getVersion, getDependencyVersion } from '../utils.mjs'
1
+ import { getVersion, getDependencyVersion, safeMkdir } from '../utils.mjs'
2
2
  import { createPackageJson } from '../create-package-json.mjs'
3
3
  import { createGitignore } from '../create-gitignore.mjs'
4
4
  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 { mkdir, stat } from 'fs/promises'
9
8
  import pino from 'pino'
10
9
  import pretty from 'pino-pretty'
11
10
  import { execa } from 'execa'
@@ -37,13 +36,6 @@ const createPlatformaticService = async (_args, opts = {}) => {
37
36
  const projectDir = opts.dir || await askDir(logger, join('.', 'platformatic-service'))
38
37
  const isRuntimeContext = opts.isRuntimeContext || false
39
38
 
40
- // checks directory
41
- try {
42
- await stat(projectDir)
43
- logger.error(`Directory ${projectDir} already exists. Please choose another path.`)
44
- process.exit(1)
45
- } catch (err) {}
46
-
47
39
  const toAsk = []
48
40
  toAsk.push(getUseTypescript(args.typescript))
49
41
 
@@ -84,7 +76,7 @@ const createPlatformaticService = async (_args, opts = {}) => {
84
76
  } = await inquirer.prompt(toAsk)
85
77
 
86
78
  // Create the project directory
87
- await mkdir(projectDir, { recursive: true })
79
+ await safeMkdir(projectDir)
88
80
 
89
81
  const params = {
90
82
  isRuntimeContext,
@@ -122,7 +114,9 @@ const createPlatformaticService = async (_args, opts = {}) => {
122
114
 
123
115
  const spinner = ora('Generating types...').start()
124
116
  try {
125
- await execa(pkgManager, ['exec', 'platformatic', 'service', 'types'], { cwd: projectDir })
117
+ const options = ['exec', 'platformatic', 'service', 'types']
118
+ await execa(pkgManager, options, { cwd: projectDir })
119
+
126
120
  spinner.succeed('Types generated!')
127
121
  } catch (err) {
128
122
  logger.trace({ err })
@@ -1,7 +1,7 @@
1
1
  import { writeFile, readFile, appendFile } from 'fs/promises'
2
2
  import { join } from 'path'
3
3
  import * as desm from 'desm'
4
- import { addPrefixToEnv, findServiceConfigFile, isFileAccessible } from '../utils.mjs'
4
+ import { addPrefixToEnv } from '../utils.mjs'
5
5
  import { getTsConfig } from '../get-tsconfig.mjs'
6
6
  import { generatePlugins } from '../create-plugins.mjs'
7
7
  import { createDynamicWorkspaceGHAction, createStaticWorkspaceGHAction } from '../ghaction.mjs'
@@ -90,41 +90,23 @@ async function createService (params, logger, currentDir = process.cwd(), versio
90
90
  const pkg = await readFile(desm.join(import.meta.url, '..', '..', 'package.json'))
91
91
  version = JSON.parse(pkg).version
92
92
  }
93
- const accessibleConfigFilename = await findServiceConfigFile(currentDir)
94
93
  const envPrefix = runtimeContext !== undefined ? `${runtimeContext.envPrefix}_` : ''
95
- if (accessibleConfigFilename === undefined) {
96
- const config = generateConfig(isRuntimeContext, version, typescript, envPrefix)
97
- await writeFile(join(currentDir, 'platformatic.service.json'), JSON.stringify(config, null, 2))
98
- logger.info('Configuration file platformatic.service.json successfully created.')
99
-
100
- const env = generateEnv(isRuntimeContext, hostname, port, typescript, envPrefix)
101
- const envFileExists = await isFileAccessible('.env', currentDir)
102
- await appendFile(join(currentDir, '.env'), env)
103
- await writeFile(join(currentDir, '.env.sample'), env)
104
- /* c8 ignore next 5 */
105
- if (envFileExists) {
106
- logger.info('Environment file .env found, appending new environment variables to existing .env file.')
107
- } else {
108
- logger.info('Environment file .env successfully created.')
109
- }
110
- } else {
111
- logger.info(`Configuration file ${accessibleConfigFilename} found, skipping creation of configuration file.`)
112
- }
94
+ const config = generateConfig(isRuntimeContext, version, typescript, envPrefix)
95
+ await writeFile(join(currentDir, 'platformatic.service.json'), JSON.stringify(config, null, 2))
96
+ logger.info('Configuration file platformatic.service.json successfully created.')
97
+
98
+ const env = generateEnv(isRuntimeContext, hostname, port, typescript, envPrefix)
99
+ await appendFile(join(currentDir, '.env'), env)
100
+ await writeFile(join(currentDir, '.env.sample'), env)
101
+ logger.info('Environment file .env found, appending new environment variables to existing .env file.')
113
102
 
114
103
  if (typescript === true) {
115
104
  const tsConfigFileName = join(currentDir, 'tsconfig.json')
116
- const isTsConfigExists = await isFileAccessible(tsConfigFileName)
117
- if (!isTsConfigExists) {
118
- const tsConfig = getTsConfig(TS_OUT_DIR)
119
- await writeFile(tsConfigFileName, JSON.stringify(tsConfig, null, 2))
120
- logger.info(
121
- `Typescript configuration file ${tsConfigFileName} successfully created.`
122
- )
123
- } else {
124
- logger.info(
125
- `Typescript configuration file ${tsConfigFileName} found, skipping creation of typescript configuration file.`
126
- )
127
- }
105
+ const tsConfig = getTsConfig(TS_OUT_DIR)
106
+ await writeFile(tsConfigFileName, JSON.stringify(tsConfig, null, 2))
107
+ logger.info(
108
+ `Typescript configuration file ${tsConfigFileName} successfully created.`
109
+ )
128
110
  }
129
111
 
130
112
  if (!isRuntimeContext) {
package/src/utils.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { execa } from 'execa'
2
- import { access, constants, readFile } from 'fs/promises'
2
+ import { access, constants, mkdir, readFile } from 'fs/promises'
3
3
  import { resolve, join, dirname } from 'path'
4
4
  import { createRequire } from 'module'
5
5
  import semver from 'semver'
@@ -102,3 +102,11 @@ export function addPrefixToEnv (env, prefix) {
102
102
  })
103
103
  return output
104
104
  }
105
+
106
+ export async function safeMkdir (dir) {
107
+ try {
108
+ await mkdir(dir, { recursive: true })
109
+ } catch (err) {
110
+ // do nothing
111
+ }
112
+ }