platformatic 1.7.1 → 1.8.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/lib/deploy.js +202 -19
- package/lib/errors.js +5 -1
- package/package.json +13 -13
package/lib/deploy.js
CHANGED
|
@@ -4,6 +4,7 @@ import { isAbsolute, dirname, relative, join } from 'path'
|
|
|
4
4
|
import { readFile } from 'fs/promises'
|
|
5
5
|
|
|
6
6
|
import { request } from 'undici'
|
|
7
|
+
import { bold, green } from 'colorette'
|
|
7
8
|
import pino from 'pino'
|
|
8
9
|
import pretty from 'pino-pretty'
|
|
9
10
|
import dotenv from 'dotenv'
|
|
@@ -18,6 +19,9 @@ export const DEPLOY_SERVICE_HOST = 'https://deploy.platformatic.cloud'
|
|
|
18
19
|
const WORKSPACE_TYPES = ['static', 'dynamic']
|
|
19
20
|
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
|
20
21
|
|
|
22
|
+
const CREATE_NEW_WORKSPACE_CHOICE = Symbol('CREATE_NEW_WORKSPACE_CHOICE')
|
|
23
|
+
const CREATE_NEW_APPLICATION_CHOICE = Symbol('CREATE_NEW_APPLICATION_CHOICE')
|
|
24
|
+
|
|
21
25
|
const logger = pino(pretty({
|
|
22
26
|
translateTime: 'SYS:HH:MM:ss',
|
|
23
27
|
ignore: 'hostname,pid'
|
|
@@ -76,7 +80,7 @@ async function askMissingWorkspaceDetails (
|
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
|
|
79
|
-
/* c8 ignore next
|
|
83
|
+
/* c8 ignore next 27 */
|
|
80
84
|
async function askToChooseApplication (applications) {
|
|
81
85
|
const applicationChoices = applications.map((application) => {
|
|
82
86
|
return {
|
|
@@ -85,7 +89,11 @@ async function askToChooseApplication (applications) {
|
|
|
85
89
|
}
|
|
86
90
|
})
|
|
87
91
|
applicationChoices.push({
|
|
88
|
-
name: '
|
|
92
|
+
name: bold('Create new application'),
|
|
93
|
+
value: CREATE_NEW_APPLICATION_CHOICE
|
|
94
|
+
})
|
|
95
|
+
applicationChoices.push({
|
|
96
|
+
name: bold('Deploy to another application'),
|
|
89
97
|
value: null
|
|
90
98
|
})
|
|
91
99
|
|
|
@@ -93,14 +101,11 @@ async function askToChooseApplication (applications) {
|
|
|
93
101
|
type: 'list',
|
|
94
102
|
name: 'application',
|
|
95
103
|
message: 'Select application to deploy:',
|
|
96
|
-
choices: applicationChoices
|
|
104
|
+
choices: applicationChoices,
|
|
105
|
+
loop: false
|
|
97
106
|
})
|
|
98
107
|
|
|
99
108
|
const chosenApplication = answer.application
|
|
100
|
-
if (chosenApplication === null) {
|
|
101
|
-
return null
|
|
102
|
-
}
|
|
103
|
-
|
|
104
109
|
return chosenApplication
|
|
105
110
|
}
|
|
106
111
|
|
|
@@ -113,7 +118,11 @@ async function askToChooseWorkspace (workspaces) {
|
|
|
113
118
|
}
|
|
114
119
|
})
|
|
115
120
|
workspaceChoices.push({
|
|
116
|
-
name: '
|
|
121
|
+
name: bold('Create new workspace'),
|
|
122
|
+
value: CREATE_NEW_WORKSPACE_CHOICE
|
|
123
|
+
})
|
|
124
|
+
workspaceChoices.push({
|
|
125
|
+
name: bold('Deploy to another workspace'),
|
|
117
126
|
value: null
|
|
118
127
|
})
|
|
119
128
|
|
|
@@ -121,15 +130,63 @@ async function askToChooseWorkspace (workspaces) {
|
|
|
121
130
|
type: 'list',
|
|
122
131
|
name: 'workspace',
|
|
123
132
|
message: 'Select workspace to deploy:',
|
|
124
|
-
choices: workspaceChoices
|
|
133
|
+
choices: workspaceChoices,
|
|
134
|
+
loop: false
|
|
125
135
|
})
|
|
126
136
|
|
|
127
137
|
const chosenWorkspace = answer.workspace
|
|
128
|
-
|
|
129
|
-
|
|
138
|
+
return chosenWorkspace
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* c8 ignore next 14 */
|
|
142
|
+
async function askToChooseOrg (orgs) {
|
|
143
|
+
const orgsChoices = orgs.map((org) => {
|
|
144
|
+
return { name: org.name, value: org.id }
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
const answer = await inquirer.prompt({
|
|
148
|
+
type: 'list',
|
|
149
|
+
name: 'orgId',
|
|
150
|
+
message: 'Select organisation to publish to:',
|
|
151
|
+
choices: orgsChoices
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
return answer.orgId
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* c8 ignore next 21 */
|
|
158
|
+
async function askNewWorkspaceDetails () {
|
|
159
|
+
const answer = await inquirer.prompt([
|
|
160
|
+
{
|
|
161
|
+
type: 'input',
|
|
162
|
+
name: 'workspaceName',
|
|
163
|
+
message: 'Enter workspace name:'
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
type: 'list',
|
|
167
|
+
name: 'workspaceType',
|
|
168
|
+
message: 'Select workspace type:',
|
|
169
|
+
choices: WORKSPACE_TYPES
|
|
170
|
+
}
|
|
171
|
+
])
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
workspaceName: answer.workspaceName,
|
|
175
|
+
workspaceType: answer.workspaceType
|
|
130
176
|
}
|
|
177
|
+
}
|
|
131
178
|
|
|
132
|
-
|
|
179
|
+
/* c8 ignore next 12 */
|
|
180
|
+
async function askNewApplicationDetails () {
|
|
181
|
+
const answer = await inquirer.prompt({
|
|
182
|
+
type: 'input',
|
|
183
|
+
name: 'applicationName',
|
|
184
|
+
message: 'Enter application name:'
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
applicationName: answer.applicationName
|
|
189
|
+
}
|
|
133
190
|
}
|
|
134
191
|
|
|
135
192
|
/* c8 ignore next 19 */
|
|
@@ -216,6 +273,25 @@ async function getUserApplications (deployServiceHost, userApiKey) {
|
|
|
216
273
|
return applications
|
|
217
274
|
}
|
|
218
275
|
|
|
276
|
+
/* c8 ignore next 18 */
|
|
277
|
+
async function getUserOrgs (deployServiceHost, userApiKey) {
|
|
278
|
+
const url = deployServiceHost + '/organisations'
|
|
279
|
+
const { statusCode, body } = await request(url, {
|
|
280
|
+
method: 'GET',
|
|
281
|
+
headers: {
|
|
282
|
+
'content-type': 'application/json',
|
|
283
|
+
'x-platformatic-user-api-key': userApiKey
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
if (statusCode !== 200) {
|
|
288
|
+
throw new errors.CouldNotFetchUserOrgsError()
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const { orgs } = await body.json()
|
|
292
|
+
return orgs
|
|
293
|
+
}
|
|
294
|
+
|
|
219
295
|
/* c8 ignore next 18 */
|
|
220
296
|
async function getWorkspaceLabels (deployServiceHost, workspaceId, userApiKey) {
|
|
221
297
|
const { statusCode, body } = await request(`${deployServiceHost}/entrypoints`, {
|
|
@@ -236,27 +312,134 @@ async function getWorkspaceLabels (deployServiceHost, workspaceId, userApiKey) {
|
|
|
236
312
|
return entryPoints.map((entryPoint) => entryPoint.label)
|
|
237
313
|
}
|
|
238
314
|
|
|
239
|
-
/* c8 ignore next
|
|
240
|
-
async function
|
|
315
|
+
/* c8 ignore next 30 */
|
|
316
|
+
async function createWorkspace (
|
|
317
|
+
deployServiceHost,
|
|
318
|
+
userApiKey,
|
|
319
|
+
appId,
|
|
320
|
+
workspaceName,
|
|
321
|
+
workspaceType
|
|
322
|
+
) {
|
|
323
|
+
const { statusCode, body } = await request(`${deployServiceHost}/workspaces`, {
|
|
324
|
+
method: 'POST',
|
|
325
|
+
headers: {
|
|
326
|
+
'Content-Type': 'application/json',
|
|
327
|
+
'x-platformatic-user-api-key': userApiKey
|
|
328
|
+
},
|
|
329
|
+
body: JSON.stringify({
|
|
330
|
+
appId,
|
|
331
|
+
name: workspaceName,
|
|
332
|
+
type: workspaceType
|
|
333
|
+
})
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
if (statusCode !== 200) {
|
|
337
|
+
const error = await body.text()
|
|
338
|
+
console.error(error)
|
|
339
|
+
throw new errors.CouldNotCreateWorkspaceError()
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const { id: workspaceId } = await body.json()
|
|
343
|
+
return workspaceId
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* c8 ignore next 25 */
|
|
347
|
+
async function createApplication (
|
|
348
|
+
deployServiceHost,
|
|
349
|
+
userApiKey,
|
|
350
|
+
orgId,
|
|
351
|
+
applicationName
|
|
352
|
+
) {
|
|
353
|
+
const { statusCode, body } = await request(`${deployServiceHost}/applications`, {
|
|
354
|
+
method: 'POST',
|
|
355
|
+
headers: {
|
|
356
|
+
'Content-Type': 'application/json',
|
|
357
|
+
'x-platformatic-user-api-key': userApiKey
|
|
358
|
+
},
|
|
359
|
+
body: JSON.stringify({ orgId, name: applicationName })
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
if (statusCode !== 200) {
|
|
363
|
+
const error = await body.text()
|
|
364
|
+
console.error(error)
|
|
365
|
+
throw new errors.CouldNotCreateApplicationError()
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const { id: applicationId } = await body.json()
|
|
369
|
+
return applicationId
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/* c8 ignore next 16 */
|
|
373
|
+
async function getUserOrgDetails (deployServiceHost, userApiKey) {
|
|
374
|
+
const userOrgs = await getUserOrgs(deployServiceHost, userApiKey)
|
|
375
|
+
if (userOrgs.length === 0) {
|
|
376
|
+
throw new errors.NoUserOrgsError()
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
let orgId = null
|
|
380
|
+
if (userOrgs.length === 1) {
|
|
381
|
+
orgId = userOrgs[0].id
|
|
382
|
+
} else {
|
|
383
|
+
orgId = await askToChooseOrg(userOrgs)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return { id: orgId }
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/* c8 ignore next 26 */
|
|
390
|
+
async function getUserApplicationDetails (deployServiceHost, userApiKey) {
|
|
241
391
|
const applications = await getUserApplications(deployServiceHost, userApiKey)
|
|
242
392
|
if (applications.length === 0) return null
|
|
243
393
|
|
|
244
394
|
const application = await askToChooseApplication(applications)
|
|
245
395
|
if (application === null) return null
|
|
246
396
|
|
|
247
|
-
|
|
248
|
-
|
|
397
|
+
if (application === CREATE_NEW_APPLICATION_CHOICE) {
|
|
398
|
+
const { id: orgId } = await getUserOrgDetails(deployServiceHost, userApiKey)
|
|
399
|
+
const { applicationName } = await askNewApplicationDetails()
|
|
400
|
+
const applicationId = await createApplication(
|
|
401
|
+
deployServiceHost,
|
|
402
|
+
userApiKey,
|
|
403
|
+
orgId,
|
|
404
|
+
applicationName
|
|
405
|
+
)
|
|
406
|
+
return { id: applicationId, name: applicationName, workspaces: [] }
|
|
407
|
+
}
|
|
408
|
+
return {
|
|
409
|
+
id: application.id,
|
|
410
|
+
name: application.name,
|
|
411
|
+
workspaces: application.workspaces
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/* c8 ignore next 24 */
|
|
416
|
+
async function getUserWorkspaceDetails (deployServiceHost, userApiKey) {
|
|
417
|
+
const application = await getUserApplicationDetails(deployServiceHost, userApiKey)
|
|
418
|
+
if (application === null) return null
|
|
249
419
|
|
|
250
|
-
const workspaceDetails = await askToChooseWorkspace(workspaces)
|
|
420
|
+
const workspaceDetails = await askToChooseWorkspace(application.workspaces)
|
|
251
421
|
if (workspaceDetails === null) return null
|
|
252
422
|
|
|
423
|
+
if (workspaceDetails === CREATE_NEW_WORKSPACE_CHOICE) {
|
|
424
|
+
const { workspaceName, workspaceType } = await askNewWorkspaceDetails()
|
|
425
|
+
const workspaceId = await createWorkspace(
|
|
426
|
+
deployServiceHost,
|
|
427
|
+
userApiKey,
|
|
428
|
+
application.id,
|
|
429
|
+
workspaceName,
|
|
430
|
+
workspaceType
|
|
431
|
+
)
|
|
432
|
+
return { workspaceId, workspaceType }
|
|
433
|
+
}
|
|
434
|
+
|
|
253
435
|
return {
|
|
254
|
-
|
|
255
|
-
|
|
436
|
+
workspaceId: workspaceDetails.id,
|
|
437
|
+
workspaceType: workspaceDetails.type
|
|
256
438
|
}
|
|
257
439
|
}
|
|
258
440
|
|
|
259
441
|
export async function deploy (argv) {
|
|
442
|
+
console.log('This application will be deployed to ' + bold(green('Platformatic Cloud')) + '. To change the target use the --deploy-service-host flag')
|
|
260
443
|
try {
|
|
261
444
|
const args = parseArgs(argv, {
|
|
262
445
|
alias: {
|
package/lib/errors.js
CHANGED
|
@@ -9,7 +9,11 @@ const errors = {
|
|
|
9
9
|
InvalidWorkspaceIdError: createError(`${ERROR_PREFIX}_INVALID_WORKSPACE_ID`, 'Invalid workspace id provided. Workspace id must be a valid uuid.'),
|
|
10
10
|
CouldNotFindWorkspaceKeysError: createError(`${ERROR_PREFIX}_COULD_NOT_FIND_WORKSPACE_KEYS`, 'Could not find workspace keys in provided file.'),
|
|
11
11
|
CouldNotFetchUserApplicationsError: createError(`${ERROR_PREFIX}_COULD_NOT_FETCH_USER_APPLICATIONS`, 'Could not fetch user applications'),
|
|
12
|
-
CouldNotFetchDeployLabelsError: createError(`${ERROR_PREFIX}_COULD_NOT_FETCH_DEPLOY_LABELS`, 'Could not fetch deploy labels')
|
|
12
|
+
CouldNotFetchDeployLabelsError: createError(`${ERROR_PREFIX}_COULD_NOT_FETCH_DEPLOY_LABELS`, 'Could not fetch deploy labels'),
|
|
13
|
+
CouldNotCreateWorkspaceError: createError(`${ERROR_PREFIX}_COULD_NOT_CREATE_WORKSPACE`, 'Could not create workspace'),
|
|
14
|
+
CouldNotCreateApplicationError: createError(`${ERROR_PREFIX}_COULD_NOT_CREATE_APPLICATION`, 'Could not create application'),
|
|
15
|
+
CouldNotFetchUserOrgsError: createError(`${ERROR_PREFIX}_COULD_NOT_FETCH_USER_ORGS`, 'Could not fetch user ogranisations'),
|
|
16
|
+
NoUserOrgsError: createError(`${ERROR_PREFIX}_NO_USER_ORGS`, 'User does not have any organisations.')
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
export default errors
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "platformatic",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "Platformatic CLI",
|
|
5
5
|
"main": "cli.js",
|
|
6
6
|
"type": "module",
|
|
@@ -49,18 +49,18 @@
|
|
|
49
49
|
"pino": "^8.15.3",
|
|
50
50
|
"pino-pretty": "^10.2.0",
|
|
51
51
|
"undici": "^5.25.4",
|
|
52
|
-
"@platformatic/authenticate": "1.
|
|
53
|
-
"@platformatic/
|
|
54
|
-
"@platformatic/
|
|
55
|
-
"@platformatic/config": "1.
|
|
56
|
-
"@platformatic/db": "1.
|
|
57
|
-
"@platformatic/deploy-client": "1.
|
|
58
|
-
"@platformatic/frontend-template": "1.
|
|
59
|
-
"@platformatic/
|
|
60
|
-
"@platformatic/
|
|
61
|
-
"@platformatic/service": "1.
|
|
62
|
-
"@platformatic/utils": "^1.
|
|
63
|
-
"create-platformatic": "1.
|
|
52
|
+
"@platformatic/authenticate": "1.8.1",
|
|
53
|
+
"@platformatic/composer": "1.8.1",
|
|
54
|
+
"@platformatic/client-cli": "1.8.1",
|
|
55
|
+
"@platformatic/config": "1.8.1",
|
|
56
|
+
"@platformatic/db": "1.8.1",
|
|
57
|
+
"@platformatic/deploy-client": "1.8.1",
|
|
58
|
+
"@platformatic/frontend-template": "1.8.1",
|
|
59
|
+
"@platformatic/runtime": "1.8.1",
|
|
60
|
+
"@platformatic/metaconfig": "1.8.1",
|
|
61
|
+
"@platformatic/service": "1.8.1",
|
|
62
|
+
"@platformatic/utils": "^1.8.1",
|
|
63
|
+
"create-platformatic": "1.8.1"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|
|
66
66
|
"test": "standard | snazzy && c8 node ./test/runner.js",
|