create-platformatic 1.2.0 → 1.3.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.
- package/create-platformatic.mjs +1 -1
- package/package.json +7 -6
- package/src/ask-dir.mjs +19 -0
- package/src/cli-options.mjs +10 -0
- package/src/composer/create-composer-cli.mjs +11 -14
- package/src/composer/create-composer.mjs +18 -24
- package/src/create-git-repository.mjs +105 -0
- package/src/create-gitignore.mjs +2 -8
- package/src/create-package-json.mjs +5 -11
- package/src/create-plugins.mjs +7 -23
- package/src/db/create-db-cli.mjs +8 -13
- package/src/db/create-db.mjs +26 -42
- package/src/ghaction.mjs +30 -40
- package/src/index.mjs +2 -0
- package/src/runtime/create-runtime-cli.mjs +10 -13
- package/src/runtime/create-runtime.mjs +10 -13
- package/src/service/create-service-cli.mjs +13 -14
- package/src/service/create-service.mjs +20 -34
- package/src/utils.mjs +9 -1
package/create-platformatic.mjs
CHANGED
|
@@ -37,5 +37,5 @@ export {
|
|
|
37
37
|
createDynamicWorkspaceGHAction
|
|
38
38
|
} from './src/ghaction.mjs'
|
|
39
39
|
|
|
40
|
-
export { createGitignore, createPackageJson, getDependencyVersion, getVersion } from './src/index.mjs'
|
|
40
|
+
export { createGitignore, createGitRepository, createPackageJson, getDependencyVersion, getVersion } from './src/index.mjs'
|
|
41
41
|
export { default as createService } from './src/service/create-service.mjs'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-platformatic",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
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.
|
|
38
|
+
"@platformatic/config": "1.3.1"
|
|
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.
|
|
52
|
-
"@platformatic/service": "1.
|
|
51
|
+
"@platformatic/db": "1.3.1",
|
|
52
|
+
"@platformatic/service": "1.3.1"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
|
-
"test:cli": "tap --no-coverage test/cli/*test.mjs -
|
|
56
|
-
"test": "standard | snazzy && cross-env NODE_OPTIONS=\"--loader=esmock --no-warnings\" c8 tap --no-coverage test/*test.mjs test/*[!cli]/*test.mjs
|
|
55
|
+
"test:cli": "tap --no-coverage test/cli/*test.mjs -t120",
|
|
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
|
|
package/src/cli-options.mjs
CHANGED
|
@@ -19,6 +19,16 @@ export const getUseTypescript = typescript => {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
export const getInitGitRepository = () => {
|
|
23
|
+
return {
|
|
24
|
+
type: 'list',
|
|
25
|
+
name: 'initGitRepository',
|
|
26
|
+
message: 'Do you want to init the git repository?',
|
|
27
|
+
default: false,
|
|
28
|
+
choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
22
32
|
let port = 3042
|
|
23
33
|
export const getPort = (nextPort) => {
|
|
24
34
|
if (nextPort === undefined) {
|
|
@@ -1,19 +1,17 @@
|
|
|
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'
|
|
11
10
|
import ora from 'ora'
|
|
12
11
|
import createComposer from './create-composer.mjs'
|
|
13
12
|
import askDir from '../ask-dir.mjs'
|
|
14
|
-
import { getRunPackageManagerInstall, getPort, getUseTypescript } from '../cli-options.mjs'
|
|
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 = []
|
|
@@ -91,17 +82,22 @@ const createPlatformaticComposer = async (_args, opts) => {
|
|
|
91
82
|
choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
|
|
92
83
|
})
|
|
93
84
|
}
|
|
85
|
+
|
|
86
|
+
if (!opts.skipGitRepository) {
|
|
87
|
+
toAsk.push(getInitGitRepository())
|
|
88
|
+
}
|
|
94
89
|
const {
|
|
95
90
|
runPackageManagerInstall,
|
|
96
91
|
servicesToCompose,
|
|
97
92
|
port,
|
|
98
93
|
staticWorkspaceGitHubAction,
|
|
99
94
|
dynamicWorkspaceGitHubAction,
|
|
100
|
-
useTypescript
|
|
95
|
+
useTypescript,
|
|
96
|
+
initGitRepository
|
|
101
97
|
} = await inquirer.prompt(toAsk)
|
|
102
98
|
|
|
103
99
|
// Create the project directory
|
|
104
|
-
await
|
|
100
|
+
await safeMkdir(projectDir)
|
|
105
101
|
|
|
106
102
|
const params = {
|
|
107
103
|
isRuntimeContext,
|
|
@@ -111,7 +107,8 @@ const createPlatformaticComposer = async (_args, opts) => {
|
|
|
111
107
|
staticWorkspaceGitHubAction,
|
|
112
108
|
dynamicWorkspaceGitHubAction,
|
|
113
109
|
runtimeContext: opts.runtimeContext,
|
|
114
|
-
typescript: useTypescript
|
|
110
|
+
typescript: useTypescript,
|
|
111
|
+
initGitRepository
|
|
115
112
|
}
|
|
116
113
|
|
|
117
114
|
await createComposer(
|
|
@@ -1,10 +1,10 @@
|
|
|
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'
|
|
6
5
|
import { createDynamicWorkspaceGHAction, createStaticWorkspaceGHAction } from '../ghaction.mjs'
|
|
7
6
|
import { getTsConfig } from '../get-tsconfig.mjs'
|
|
7
|
+
import { createGitRepository } from '../create-git-repository.mjs'
|
|
8
8
|
|
|
9
9
|
const TS_OUT_DIR = 'dist'
|
|
10
10
|
|
|
@@ -93,7 +93,8 @@ async function createComposer (
|
|
|
93
93
|
runtimeContext,
|
|
94
94
|
typescript,
|
|
95
95
|
staticWorkspaceGitHubAction,
|
|
96
|
-
dynamicWorkspaceGitHubAction
|
|
96
|
+
dynamicWorkspaceGitHubAction,
|
|
97
|
+
initGitRepository
|
|
97
98
|
} = params
|
|
98
99
|
|
|
99
100
|
const composerEnv = {
|
|
@@ -105,28 +106,17 @@ async function createComposer (
|
|
|
105
106
|
const pkg = await readFile(desm.join(import.meta.url, '..', '..', 'package.json'))
|
|
106
107
|
version = JSON.parse(pkg).version
|
|
107
108
|
}
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
await appendFile(join(currentDir, '.env'), env)
|
|
120
|
-
await writeFile(join(currentDir, '.env.sample'), env)
|
|
121
|
-
/* c8 ignore next 5 */
|
|
122
|
-
if (envFileExists) {
|
|
123
|
-
logger.info('Environment file .env found, appending new environment variables to existing .env file.')
|
|
124
|
-
} else {
|
|
125
|
-
logger.info('Environment file .env successfully created.')
|
|
126
|
-
}
|
|
127
|
-
} else {
|
|
128
|
-
logger.info(`Configuration file ${accessibleConfigFilename} found, skipping creation of configuration file.`)
|
|
129
|
-
}
|
|
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.')
|
|
130
120
|
await generatePlugins(logger, currentDir, typescript, 'composer')
|
|
131
121
|
await generateRouteWithTypesSupport(logger, currentDir, true)
|
|
132
122
|
|
|
@@ -147,6 +137,10 @@ async function createComposer (
|
|
|
147
137
|
await createDynamicWorkspaceGHAction(logger, composerEnv, './platformatic.service.json', currentDir, typescript)
|
|
148
138
|
}
|
|
149
139
|
|
|
140
|
+
if (initGitRepository) {
|
|
141
|
+
await createGitRepository(logger, currentDir)
|
|
142
|
+
}
|
|
143
|
+
|
|
150
144
|
return composerEnv
|
|
151
145
|
}
|
|
152
146
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { execa } from 'execa'
|
|
2
|
+
|
|
3
|
+
export const GIT_FIRST_COMMIT_MESSAGE = 'Platformatic project started! 🚀'
|
|
4
|
+
export const GIT_MAIN_BRANCH = 'main'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Creates a Git repository and performs the initial commit if it doesn't already exist.
|
|
8
|
+
*
|
|
9
|
+
* This function checks if Git is installed, initializes a Git repository in the specified
|
|
10
|
+
* directory if it's not already a Git repository, and performs the initial commit.
|
|
11
|
+
*
|
|
12
|
+
* @param {import('pino.').BaseLogger} logger - The logger interface for logging messages.
|
|
13
|
+
* @param {string} [dir='.'] - The target directory where the Git repository should be created.
|
|
14
|
+
*/
|
|
15
|
+
export async function createGitRepository (logger, dir = '.') {
|
|
16
|
+
if (!await isGitInstalled()) {
|
|
17
|
+
logger.error('Git is not installed')
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!await gitInit(logger, dir)) {
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!await gitCommit(logger, dir)) {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
logger.info('Git repository initialized.')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Checks if Git is installed on the system.
|
|
34
|
+
*
|
|
35
|
+
* @async
|
|
36
|
+
* @returns {Promise<boolean>} A Promise that resolves to true if Git is installed, false otherwise.
|
|
37
|
+
*/
|
|
38
|
+
async function isGitInstalled () {
|
|
39
|
+
try {
|
|
40
|
+
await execa('git', ['--version'])
|
|
41
|
+
return true
|
|
42
|
+
} catch (err) {
|
|
43
|
+
return false
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Checks if a Git repository exists in the specified directory.
|
|
49
|
+
*
|
|
50
|
+
* @async
|
|
51
|
+
* @param {string} dir - The directory to check for a Git repository.
|
|
52
|
+
* @returns {Promise<boolean>} A Promise that resolves to true if a Git repository exists in the directory, false otherwise.
|
|
53
|
+
*/
|
|
54
|
+
async function doesGitRepositoryExist (dir) {
|
|
55
|
+
try {
|
|
56
|
+
await execa('git', ['rev-parse', '--is-inside-work-tree'], { cwd: dir })
|
|
57
|
+
return true
|
|
58
|
+
} catch (e) {
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Initializes a Git repository in the specified directory if it doesn't already exist.
|
|
65
|
+
*
|
|
66
|
+
* @async
|
|
67
|
+
* @param {import('pino.').BaseLogger} - The logger object for logging messages.
|
|
68
|
+
* @param {string} dir - The directory where the Git repository should be initialized.
|
|
69
|
+
* @returns {Promise<boolean>} A Promise that resolves to true if the Git repository is successfully initialized, false otherwise.
|
|
70
|
+
*/
|
|
71
|
+
async function gitInit (logger, dir) {
|
|
72
|
+
try {
|
|
73
|
+
if (await doesGitRepositoryExist(dir)) {
|
|
74
|
+
logger.info('Git repository already exists.')
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
await execa('git', ['init', '-b', GIT_MAIN_BRANCH], { cwd: dir })
|
|
79
|
+
logger.debug('Git repository initialized.')
|
|
80
|
+
return true
|
|
81
|
+
} catch (err) {
|
|
82
|
+
logger.error('Git repository init failed.', err)
|
|
83
|
+
return false
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Commits changes in a Git repository located in the specified directory.
|
|
89
|
+
*
|
|
90
|
+
* @async
|
|
91
|
+
* @param {import('pino.').BaseLogger} - The logger object for logging messages.
|
|
92
|
+
* @param {string} dir - The directory of the Git repository where changes should be committed.
|
|
93
|
+
* @returns {Promise<boolean>} A Promise that resolves to true if the Git commit is successful, false otherwise.
|
|
94
|
+
*/
|
|
95
|
+
async function gitCommit (logger, dir) {
|
|
96
|
+
try {
|
|
97
|
+
await execa('git', ['add', '-A'], { cwd: dir })
|
|
98
|
+
await execa('git', ['commit', '-m', GIT_FIRST_COMMIT_MESSAGE], { cwd: dir })
|
|
99
|
+
logger.debug('Git commit done.')
|
|
100
|
+
return true
|
|
101
|
+
} catch (err) {
|
|
102
|
+
logger.error('Git commit failed.', err)
|
|
103
|
+
return false
|
|
104
|
+
}
|
|
105
|
+
}
|
package/src/create-gitignore.mjs
CHANGED
|
@@ -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
|
-
|
|
42
|
-
|
|
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
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
}
|
package/src/create-plugins.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join } from 'path'
|
|
2
|
-
import { writeFile
|
|
3
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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))
|
package/src/db/create-db-cli.mjs
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
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'
|
|
12
11
|
import ora from 'ora'
|
|
13
12
|
import { getConnectionString, createDB } from './create-db.mjs'
|
|
14
13
|
import askDir from '../ask-dir.mjs'
|
|
15
|
-
import { getRunPackageManagerInstall, getUseTypescript, getPort } from '../cli-options.mjs'
|
|
14
|
+
import { getRunPackageManagerInstall, getUseTypescript, getPort, getInitGitRepository } from '../cli-options.mjs'
|
|
16
15
|
import { createReadme } from '../create-readme.mjs'
|
|
17
16
|
import { join } from 'node:path'
|
|
18
17
|
|
|
@@ -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
|
|
|
@@ -169,11 +161,13 @@ const createPlatformaticDB = async (_args, opts) => {
|
|
|
169
161
|
when: !opts.skipGitHubActions,
|
|
170
162
|
choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
|
|
171
163
|
})
|
|
172
|
-
|
|
164
|
+
if (!opts.skipGitRepository) {
|
|
165
|
+
toAsk.push(getInitGitRepository())
|
|
166
|
+
}
|
|
173
167
|
// Prompt for questions
|
|
174
168
|
const wizardOptions = await inquirer.prompt(toAsk)
|
|
175
169
|
|
|
176
|
-
await
|
|
170
|
+
await safeMkdir(projectDir)
|
|
177
171
|
|
|
178
172
|
const generatePlugin = args.plugin || wizardOptions.generatePlugin
|
|
179
173
|
const useTypescript = args.typescript || wizardOptions.useTypescript
|
|
@@ -191,7 +185,8 @@ const createPlatformaticDB = async (_args, opts) => {
|
|
|
191
185
|
typescript: useTypescript,
|
|
192
186
|
staticWorkspaceGitHubAction: wizardOptions.staticWorkspaceGitHubAction,
|
|
193
187
|
dynamicWorkspaceGitHubAction: wizardOptions.dynamicWorkspaceGitHubAction,
|
|
194
|
-
runtimeContext: opts.runtimeContext
|
|
188
|
+
runtimeContext: opts.runtimeContext,
|
|
189
|
+
initGitRepository: wizardOptions.initGitRepository
|
|
195
190
|
}
|
|
196
191
|
|
|
197
192
|
await createDB(params, logger, projectDir, version)
|
package/src/db/create-db.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { writeFile,
|
|
1
|
+
import { writeFile, appendFile } from 'fs/promises'
|
|
2
2
|
import { join } from 'path'
|
|
3
|
-
import { addPrefixToEnv,
|
|
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'
|
|
7
|
+
import { createGitRepository } from '../create-git-repository.mjs'
|
|
7
8
|
|
|
8
9
|
const connectionStrings = {
|
|
9
10
|
postgres: 'postgres://postgres:postgres@127.0.0.1:5432/postgres',
|
|
@@ -349,7 +350,8 @@ export async function createDB (params, logger, currentDir, version) {
|
|
|
349
350
|
connectionString,
|
|
350
351
|
staticWorkspaceGitHubAction,
|
|
351
352
|
dynamicWorkspaceGitHubAction,
|
|
352
|
-
runtimeContext
|
|
353
|
+
runtimeContext,
|
|
354
|
+
initGitRepository
|
|
353
355
|
} = params
|
|
354
356
|
|
|
355
357
|
const dbEnv = {
|
|
@@ -364,56 +366,33 @@ export async function createDB (params, logger, currentDir, version) {
|
|
|
364
366
|
}
|
|
365
367
|
connectionString = connectionString || getConnectionString(database)
|
|
366
368
|
const createMigrations = !!migrations // If we don't define a migrations folder, we don't create it
|
|
367
|
-
const
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
const envFileExists = await isFileAccessible('.env', currentDir)
|
|
379
|
-
await appendFile(join(currentDir, '.env'), env)
|
|
380
|
-
await writeFile(join(currentDir, '.env.sample'), envSample)
|
|
381
|
-
/* c8 ignore next 5 */
|
|
382
|
-
if (envFileExists) {
|
|
383
|
-
logger.info('Environment file .env found, appending new environment variables to existing .env file.')
|
|
384
|
-
} else {
|
|
385
|
-
logger.info('Environment file .env successfully created.')
|
|
386
|
-
}
|
|
387
|
-
} else {
|
|
388
|
-
logger.info(`Configuration file ${accessibleConfigFilename} found, skipping creation of configuration file.`)
|
|
389
|
-
}
|
|
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.')
|
|
390
380
|
|
|
391
381
|
const migrationsFolderName = migrations
|
|
392
382
|
if (createMigrations) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
await mkdir(join(currentDir, migrationsFolderName), { recursive: true })
|
|
396
|
-
logger.info(`Migrations folder ${migrationsFolderName} successfully created.`)
|
|
397
|
-
} else {
|
|
398
|
-
logger.info(`Migrations folder ${migrationsFolderName} found, skipping creation of migrations folder.`)
|
|
399
|
-
}
|
|
383
|
+
await safeMkdir(join(currentDir, migrationsFolderName))
|
|
384
|
+
logger.info(`Migrations folder ${migrationsFolderName} successfully created.`)
|
|
400
385
|
}
|
|
401
386
|
|
|
402
387
|
const migrationFileNameDo = '001.do.sql'
|
|
403
388
|
const migrationFileNameUndo = '001.undo.sql'
|
|
404
389
|
const migrationFilePathDo = join(currentDir, migrationsFolderName, migrationFileNameDo)
|
|
405
390
|
const migrationFilePathUndo = join(currentDir, migrationsFolderName, migrationFileNameUndo)
|
|
406
|
-
|
|
407
|
-
const isMigrationFileUndoExists = await isFileAccessible(migrationFilePathUndo)
|
|
408
|
-
if (!isMigrationFileDoExists && createMigrations) {
|
|
391
|
+
if (createMigrations) {
|
|
409
392
|
await writeFile(migrationFilePathDo, moviesMigrationDo(database))
|
|
410
393
|
logger.info(`Migration file ${migrationFileNameDo} successfully created.`)
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
logger.info(`Migration file ${migrationFileNameUndo} successfully created.`)
|
|
414
|
-
}
|
|
415
|
-
} else {
|
|
416
|
-
logger.info(`Migration file ${migrationFileNameDo} found, skipping creation of migration file.`)
|
|
394
|
+
await writeFile(migrationFilePathUndo, moviesMigrationUndo)
|
|
395
|
+
logger.info(`Migration file ${migrationFileNameUndo} successfully created.`)
|
|
417
396
|
}
|
|
418
397
|
|
|
419
398
|
if (typescript === true) {
|
|
@@ -457,9 +436,14 @@ export async function createDB (params, logger, currentDir, version) {
|
|
|
457
436
|
await createDynamicWorkspaceGHAction(logger, dbEnv, './platformatic.db.json', currentDir, typescript)
|
|
458
437
|
}
|
|
459
438
|
|
|
439
|
+
if (initGitRepository) {
|
|
440
|
+
await createGitRepository(logger, currentDir)
|
|
441
|
+
}
|
|
442
|
+
|
|
460
443
|
if (isRuntimeContext) {
|
|
461
444
|
return addPrefixToEnv(isRuntimeContext)
|
|
462
445
|
}
|
|
446
|
+
|
|
463
447
|
return dbEnv
|
|
464
448
|
}
|
|
465
449
|
|
package/src/ghaction.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join } from 'path'
|
|
2
|
-
import { isFileAccessible } from './utils.mjs'
|
|
3
|
-
import { writeFile
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
}
|
package/src/index.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import commist from 'commist'
|
|
|
11
11
|
import { getUsername, getVersion, minimumSupportedNodeVersions, isCurrentVersionSupported, findRuntimeConfigFile, getDependencyVersion } from './utils.mjs'
|
|
12
12
|
import { createPackageJson } from './create-package-json.mjs'
|
|
13
13
|
import { createGitignore } from './create-gitignore.mjs'
|
|
14
|
+
import { createGitRepository } from './create-git-repository.mjs'
|
|
14
15
|
|
|
15
16
|
export async function chooseKind (argv, opts = {}) {
|
|
16
17
|
const skip = opts.skip
|
|
@@ -107,6 +108,7 @@ export default createPlatformatic
|
|
|
107
108
|
export {
|
|
108
109
|
createPackageJson,
|
|
109
110
|
createGitignore,
|
|
111
|
+
createGitRepository,
|
|
110
112
|
getVersion,
|
|
111
113
|
getDependencyVersion
|
|
112
114
|
}
|
|
@@ -1,17 +1,16 @@
|
|
|
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'
|
|
11
10
|
import ora from 'ora'
|
|
12
11
|
import createRuntime from './create-runtime.mjs'
|
|
13
12
|
import askDir from '../ask-dir.mjs'
|
|
14
|
-
import { getPort, getRunPackageManagerInstall } from '../cli-options.mjs'
|
|
13
|
+
import { getInitGitRepository, getPort, getRunPackageManagerInstall } from '../cli-options.mjs'
|
|
15
14
|
import generateName from 'boring-name-generator'
|
|
16
15
|
import { chooseKind } from '../index.mjs'
|
|
17
16
|
import { createReadme } from '../create-readme.mjs'
|
|
@@ -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
|
|
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?')
|
|
@@ -67,13 +60,15 @@ export async function createPlatformaticRuntime (_args) {
|
|
|
67
60
|
choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
|
|
68
61
|
})
|
|
69
62
|
|
|
63
|
+
toAsk.push(getInitGitRepository())
|
|
70
64
|
const {
|
|
71
65
|
runPackageManagerInstall,
|
|
72
66
|
staticWorkspaceGitHubAction,
|
|
73
|
-
dynamicWorkspaceGitHubAction
|
|
67
|
+
dynamicWorkspaceGitHubAction,
|
|
68
|
+
initGitRepository
|
|
74
69
|
} = await inquirer.prompt(toAsk)
|
|
75
70
|
|
|
76
|
-
await
|
|
71
|
+
await safeMkdir(servicesDir)
|
|
77
72
|
|
|
78
73
|
const fastifyVersion = await getDependencyVersion('fastify')
|
|
79
74
|
|
|
@@ -130,7 +125,8 @@ export async function createPlatformaticRuntime (_args) {
|
|
|
130
125
|
entrypointPort,
|
|
131
126
|
staticWorkspaceGitHubAction,
|
|
132
127
|
dynamicWorkspaceGitHubAction,
|
|
133
|
-
serviceNames: names
|
|
128
|
+
serviceNames: names,
|
|
129
|
+
initGitRepository
|
|
134
130
|
}
|
|
135
131
|
|
|
136
132
|
await createRuntime(params, logger, projectDir, version)
|
|
@@ -180,6 +176,7 @@ export async function createRuntimeService ({ servicesDir, names, logger }) {
|
|
|
180
176
|
skipGitHubActions: true,
|
|
181
177
|
skipPackageJson: true,
|
|
182
178
|
skipGitignore: true,
|
|
179
|
+
skipGitRepository: true,
|
|
183
180
|
port: '0',
|
|
184
181
|
isRuntimeContext: true,
|
|
185
182
|
runtimeContext: {
|
|
@@ -1,8 +1,8 @@
|
|
|
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'
|
|
5
|
+
import { createGitRepository } from '../create-git-repository.mjs'
|
|
6
6
|
|
|
7
7
|
function generateConfig (version, path, entrypoint) {
|
|
8
8
|
const config = {
|
|
@@ -25,23 +25,17 @@ async function createRuntime (params, logger, currentDir = process.cwd(), versio
|
|
|
25
25
|
entrypoint,
|
|
26
26
|
entrypointPort,
|
|
27
27
|
staticWorkspaceGitHubAction,
|
|
28
|
-
dynamicWorkspaceGitHubAction
|
|
28
|
+
dynamicWorkspaceGitHubAction,
|
|
29
|
+
initGitRepository
|
|
29
30
|
} = params
|
|
30
|
-
|
|
31
31
|
if (!version) {
|
|
32
32
|
const pkg = await readFile(desm.join(import.meta.url, '..', '..', 'package.json'))
|
|
33
33
|
version = JSON.parse(pkg).version
|
|
34
34
|
}
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const config = generateConfig(version, path, entrypoint)
|
|
40
|
-
await writeFile(join(currentDir, 'platformatic.runtime.json'), JSON.stringify(config, null, 2))
|
|
41
|
-
logger.info('Configuration file platformatic.runtime.json successfully created.')
|
|
42
|
-
} else {
|
|
43
|
-
logger.info(`Configuration file ${accessibleConfigFilename} found, skipping creation of configuration file.`)
|
|
44
|
-
}
|
|
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.')
|
|
45
39
|
let runtimeEnv = {}
|
|
46
40
|
if (servicesDir && entrypoint && entrypointPort) {
|
|
47
41
|
const servicesDirFullPath = isAbsolute(servicesDir)
|
|
@@ -59,6 +53,9 @@ async function createRuntime (params, logger, currentDir = process.cwd(), versio
|
|
|
59
53
|
await createDynamicWorkspaceGHAction(logger, runtimeEnv, './platformatic.runtime.json', currentDir, false)
|
|
60
54
|
}
|
|
61
55
|
|
|
56
|
+
if (initGitRepository) {
|
|
57
|
+
await createGitRepository(logger, currentDir)
|
|
58
|
+
}
|
|
62
59
|
return {}
|
|
63
60
|
}
|
|
64
61
|
/**
|
|
@@ -1,18 +1,17 @@
|
|
|
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'
|
|
12
11
|
import ora from 'ora'
|
|
13
12
|
import createService from './create-service.mjs'
|
|
14
13
|
import askDir from '../ask-dir.mjs'
|
|
15
|
-
import { getRunPackageManagerInstall, getUseTypescript, getPort } from '../cli-options.mjs'
|
|
14
|
+
import { getRunPackageManagerInstall, getUseTypescript, getPort, getInitGitRepository } from '../cli-options.mjs'
|
|
16
15
|
import { createReadme } from '../create-readme.mjs'
|
|
17
16
|
|
|
18
17
|
const createPlatformaticService = async (_args, opts = {}) => {
|
|
@@ -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
|
|
|
@@ -71,16 +63,20 @@ const createPlatformaticService = async (_args, opts = {}) => {
|
|
|
71
63
|
choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
|
|
72
64
|
})
|
|
73
65
|
}
|
|
66
|
+
if (!opts.skipGitRepository) {
|
|
67
|
+
toAsk.push(getInitGitRepository())
|
|
68
|
+
}
|
|
74
69
|
const {
|
|
75
70
|
runPackageManagerInstall,
|
|
76
71
|
useTypescript,
|
|
77
72
|
port,
|
|
78
73
|
staticWorkspaceGitHubAction,
|
|
79
|
-
dynamicWorkspaceGitHubAction
|
|
74
|
+
dynamicWorkspaceGitHubAction,
|
|
75
|
+
initGitRepository
|
|
80
76
|
} = await inquirer.prompt(toAsk)
|
|
81
77
|
|
|
82
78
|
// Create the project directory
|
|
83
|
-
await
|
|
79
|
+
await safeMkdir(projectDir)
|
|
84
80
|
|
|
85
81
|
const params = {
|
|
86
82
|
isRuntimeContext,
|
|
@@ -89,7 +85,8 @@ const createPlatformaticService = async (_args, opts = {}) => {
|
|
|
89
85
|
typescript: useTypescript,
|
|
90
86
|
staticWorkspaceGitHubAction,
|
|
91
87
|
dynamicWorkspaceGitHubAction,
|
|
92
|
-
runtimeContext: opts.runtimeContext
|
|
88
|
+
runtimeContext: opts.runtimeContext,
|
|
89
|
+
initGitRepository
|
|
93
90
|
}
|
|
94
91
|
|
|
95
92
|
await createService(params, logger, projectDir, version)
|
|
@@ -117,7 +114,9 @@ const createPlatformaticService = async (_args, opts = {}) => {
|
|
|
117
114
|
|
|
118
115
|
const spinner = ora('Generating types...').start()
|
|
119
116
|
try {
|
|
120
|
-
|
|
117
|
+
const options = ['exec', 'platformatic', 'service', 'types']
|
|
118
|
+
await execa(pkgManager, options, { cwd: projectDir })
|
|
119
|
+
|
|
121
120
|
spinner.succeed('Types generated!')
|
|
122
121
|
} catch (err) {
|
|
123
122
|
logger.trace({ err })
|
|
@@ -1,10 +1,11 @@
|
|
|
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
|
|
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'
|
|
8
|
+
import { createGitRepository } from '../create-git-repository.mjs'
|
|
8
9
|
|
|
9
10
|
const TS_OUT_DIR = 'dist'
|
|
10
11
|
|
|
@@ -72,7 +73,8 @@ async function createService (params, logger, currentDir = process.cwd(), versio
|
|
|
72
73
|
typescript = false,
|
|
73
74
|
staticWorkspaceGitHubAction,
|
|
74
75
|
dynamicWorkspaceGitHubAction,
|
|
75
|
-
runtimeContext
|
|
76
|
+
runtimeContext,
|
|
77
|
+
initGitRepository
|
|
76
78
|
} = params
|
|
77
79
|
|
|
78
80
|
const serviceEnv = {
|
|
@@ -88,41 +90,23 @@ async function createService (params, logger, currentDir = process.cwd(), versio
|
|
|
88
90
|
const pkg = await readFile(desm.join(import.meta.url, '..', '..', 'package.json'))
|
|
89
91
|
version = JSON.parse(pkg).version
|
|
90
92
|
}
|
|
91
|
-
const accessibleConfigFilename = await findServiceConfigFile(currentDir)
|
|
92
93
|
const envPrefix = runtimeContext !== undefined ? `${runtimeContext.envPrefix}_` : ''
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
await writeFile(join(currentDir, '.env.sample'), env)
|
|
102
|
-
/* c8 ignore next 5 */
|
|
103
|
-
if (envFileExists) {
|
|
104
|
-
logger.info('Environment file .env found, appending new environment variables to existing .env file.')
|
|
105
|
-
} else {
|
|
106
|
-
logger.info('Environment file .env successfully created.')
|
|
107
|
-
}
|
|
108
|
-
} else {
|
|
109
|
-
logger.info(`Configuration file ${accessibleConfigFilename} found, skipping creation of configuration file.`)
|
|
110
|
-
}
|
|
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.')
|
|
111
102
|
|
|
112
103
|
if (typescript === true) {
|
|
113
104
|
const tsConfigFileName = join(currentDir, 'tsconfig.json')
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
`Typescript configuration file ${tsConfigFileName} successfully created.`
|
|
120
|
-
)
|
|
121
|
-
} else {
|
|
122
|
-
logger.info(
|
|
123
|
-
`Typescript configuration file ${tsConfigFileName} found, skipping creation of typescript configuration file.`
|
|
124
|
-
)
|
|
125
|
-
}
|
|
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
|
+
)
|
|
126
110
|
}
|
|
127
111
|
|
|
128
112
|
if (!isRuntimeContext) {
|
|
@@ -139,7 +123,9 @@ async function createService (params, logger, currentDir = process.cwd(), versio
|
|
|
139
123
|
if (isRuntimeContext) {
|
|
140
124
|
return addPrefixToEnv(serviceEnv, runtimeContext.envPrefix)
|
|
141
125
|
}
|
|
142
|
-
|
|
126
|
+
if (initGitRepository) {
|
|
127
|
+
await createGitRepository(logger, currentDir)
|
|
128
|
+
}
|
|
143
129
|
return serviceEnv
|
|
144
130
|
}
|
|
145
131
|
|
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
|
+
}
|