directus-template-cli 0.7.4 → 0.7.6
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/bin/dev.js +0 -1
- package/bin/run.js +1 -0
- package/dist/commands/apply.d.ts +2 -1
- package/dist/commands/apply.js +42 -34
- package/dist/commands/base.d.ts +2 -2
- package/dist/commands/base.js +14 -14
- package/dist/commands/extract.d.ts +2 -2
- package/dist/commands/extract.js +17 -17
- package/dist/commands/init.d.ts +2 -2
- package/dist/commands/init.js +34 -26
- package/dist/lib/init/index.js +14 -13
- package/dist/lib/load/apply-flags.d.ts +2 -1
- package/dist/lib/load/load-collections.js +0 -2
- package/dist/lib/load/load-settings.js +0 -2
- package/dist/lib/sdk.d.ts +1 -1
- package/dist/lib/types/extension.d.ts +2 -2
- package/dist/lib/types.d.ts +4 -4
- package/dist/lib/utils/animated-bunny.js +2 -2
- package/dist/lib/utils/auth.d.ts +5 -5
- package/dist/lib/utils/auth.js +14 -13
- package/dist/lib/utils/catch-error.js +4 -4
- package/dist/lib/utils/logger.js +1 -1
- package/dist/lib/utils/parse-github-url.js +3 -3
- package/dist/lib/utils/path.js +1 -1
- package/dist/lib/utils/read-templates.d.ts +1 -1
- package/dist/lib/utils/sanitize-flags.js +2 -4
- package/dist/lib/utils/template-config.d.ts +1 -1
- package/dist/lib/utils/template-config.js +1 -1
- package/dist/services/docker.js +24 -19
- package/dist/services/execution-context.d.ts +1 -1
- package/dist/services/github.d.ts +1 -1
- package/dist/services/github.js +16 -16
- package/dist/services/posthog.d.ts +10 -10
- package/dist/services/posthog.js +5 -5
- package/oclif.manifest.json +28 -22
- package/package.json +8 -7
package/dist/commands/init.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Args, Flags
|
|
1
|
+
import { cancel, log as clackLog, confirm, intro, isCancel, select, text } from '@clack/prompts';
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
+
import { downloadTemplate } from 'giget';
|
|
4
5
|
import fs from 'node:fs';
|
|
5
6
|
import os from 'node:os';
|
|
6
7
|
import path from 'pathe';
|
|
@@ -8,12 +9,11 @@ import { disableTelemetry } from '../flags/common.js';
|
|
|
8
9
|
import { DIRECTUS_PURPLE } from '../lib/constants.js';
|
|
9
10
|
import { init } from '../lib/init/index.js';
|
|
10
11
|
import { animatedBunny } from '../lib/utils/animated-bunny.js';
|
|
11
|
-
import { createGitHub } from '../services/github.js';
|
|
12
|
-
import { readTemplateConfig } from '../lib/utils/template-config.js';
|
|
13
12
|
import { createGigetString, parseGitHubUrl } from '../lib/utils/parse-github-url.js';
|
|
14
|
-
import {
|
|
13
|
+
import { readTemplateConfig } from '../lib/utils/template-config.js';
|
|
14
|
+
import { createGitHub } from '../services/github.js';
|
|
15
|
+
import { shutdown, track } from '../services/posthog.js';
|
|
15
16
|
import { BaseCommand } from './base.js';
|
|
16
|
-
import { track, shutdown } from '../services/posthog.js';
|
|
17
17
|
export default class InitCommand extends BaseCommand {
|
|
18
18
|
static args = {
|
|
19
19
|
directory: Args.directory({
|
|
@@ -30,6 +30,7 @@ export default class InitCommand extends BaseCommand {
|
|
|
30
30
|
'$ directus-template-cli init my-project --frontend=nextjs --template=simple-cms',
|
|
31
31
|
];
|
|
32
32
|
static flags = {
|
|
33
|
+
disableTelemetry,
|
|
33
34
|
frontend: Flags.string({
|
|
34
35
|
description: 'Frontend framework to use (e.g., nextjs, nuxt, astro)',
|
|
35
36
|
}),
|
|
@@ -54,7 +55,6 @@ export default class InitCommand extends BaseCommand {
|
|
|
54
55
|
template: Flags.string({
|
|
55
56
|
description: 'Template name (e.g., simple-cms) or GitHub URL (e.g., https://github.com/directus-labs/starters/tree/main/simple-cms)',
|
|
56
57
|
}),
|
|
57
|
-
disableTelemetry: disableTelemetry,
|
|
58
58
|
};
|
|
59
59
|
targetDir = '.';
|
|
60
60
|
/**
|
|
@@ -79,6 +79,15 @@ export default class InitCommand extends BaseCommand {
|
|
|
79
79
|
// Show animated intro
|
|
80
80
|
await animatedBunny('Let\'s create a new Directus project!');
|
|
81
81
|
intro(`${chalk.bgHex(DIRECTUS_PURPLE).white.bold('Directus Template CLI')} - Create Project`);
|
|
82
|
+
// Check Docker availability before proceeding
|
|
83
|
+
const { createDocker } = await import('../services/docker.js');
|
|
84
|
+
const { DOCKER_CONFIG } = await import('../lib/init/config.js');
|
|
85
|
+
const dockerService = createDocker(DOCKER_CONFIG);
|
|
86
|
+
const dockerStatus = await dockerService.checkDocker();
|
|
87
|
+
if (!dockerStatus.installed || !dockerStatus.running) {
|
|
88
|
+
cancel(dockerStatus.message || 'Docker is required to initialize a Directus project.');
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
82
91
|
// Create GitHub service
|
|
83
92
|
const github = createGitHub();
|
|
84
93
|
// If no dir is provided, ask for it
|
|
@@ -100,8 +109,8 @@ export default class InitCommand extends BaseCommand {
|
|
|
100
109
|
}
|
|
101
110
|
if (fs.existsSync(this.targetDir) && !flags.overwriteDir) {
|
|
102
111
|
const overwriteDirResponse = await confirm({
|
|
103
|
-
message: 'Directory already exists. Would you like to overwrite it?',
|
|
104
112
|
initialValue: false,
|
|
113
|
+
message: 'Directory already exists. Would you like to overwrite it?',
|
|
105
114
|
});
|
|
106
115
|
if (isCancel(overwriteDirResponse) || overwriteDirResponse === false) {
|
|
107
116
|
cancel('Project creation cancelled.');
|
|
@@ -120,9 +129,9 @@ export default class InitCommand extends BaseCommand {
|
|
|
120
129
|
const templateResponse = await select({
|
|
121
130
|
message: 'Which Directus backend template would you like to use?',
|
|
122
131
|
options: availableTemplates.map(tmpl => ({
|
|
123
|
-
value: tmpl.id, // The value submitted will be the ID (directory name)
|
|
124
|
-
label: tmpl.name, // Display the friendly name
|
|
125
132
|
hint: tmpl.description, // Show the description as a hint
|
|
133
|
+
label: tmpl.name, // Display the friendly name
|
|
134
|
+
value: tmpl.id, // The value submitted will be the ID (directory name)
|
|
126
135
|
})),
|
|
127
136
|
});
|
|
128
137
|
if (isCancel(templateResponse)) {
|
|
@@ -164,13 +173,12 @@ export default class InitCommand extends BaseCommand {
|
|
|
164
173
|
if (templateInfo?.frontendOptions.length > 0 && (!chosenFrontend || !templateInfo.frontendOptions.find(f => f.id === chosenFrontend))) {
|
|
165
174
|
const frontendResponse = await select({
|
|
166
175
|
message: 'Which frontend framework do you want to use?',
|
|
167
|
-
options:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
],
|
|
176
|
+
options: templateInfo.frontendOptions.map(frontend => ({
|
|
177
|
+
label: frontend.name,
|
|
178
|
+
value: frontend.id,
|
|
179
|
+
}))
|
|
180
|
+
// { label: 'No frontend', value: '' },
|
|
181
|
+
,
|
|
174
182
|
});
|
|
175
183
|
if (isCancel(frontendResponse)) {
|
|
176
184
|
cancel('Project creation cancelled.');
|
|
@@ -183,7 +191,7 @@ export default class InitCommand extends BaseCommand {
|
|
|
183
191
|
finally {
|
|
184
192
|
// Clean up temporary directory
|
|
185
193
|
if (fs.existsSync(tempDir)) {
|
|
186
|
-
fs.rmSync(tempDir, {
|
|
194
|
+
fs.rmSync(tempDir, { force: true, recursive: true });
|
|
187
195
|
}
|
|
188
196
|
}
|
|
189
197
|
const installDepsResponse = await confirm({
|
|
@@ -207,17 +215,17 @@ export default class InitCommand extends BaseCommand {
|
|
|
207
215
|
// Track the command start unless telemetry is disabled
|
|
208
216
|
if (!flags.disableTelemetry) {
|
|
209
217
|
await track({
|
|
210
|
-
lifecycle: 'start',
|
|
211
|
-
distinctId: this.userConfig.distinctId,
|
|
212
218
|
command: 'init',
|
|
219
|
+
config: this.config,
|
|
220
|
+
distinctId: this.userConfig.distinctId,
|
|
213
221
|
flags: {
|
|
214
222
|
frontend: chosenFrontend,
|
|
215
223
|
gitInit: initGit,
|
|
216
224
|
installDeps,
|
|
217
225
|
template,
|
|
218
226
|
},
|
|
227
|
+
lifecycle: 'start',
|
|
219
228
|
runId: this.runId,
|
|
220
|
-
config: this.config,
|
|
221
229
|
});
|
|
222
230
|
}
|
|
223
231
|
// Initialize the project
|
|
@@ -227,28 +235,28 @@ export default class InitCommand extends BaseCommand {
|
|
|
227
235
|
frontend: chosenFrontend,
|
|
228
236
|
gitInit: initGit,
|
|
229
237
|
installDeps,
|
|
230
|
-
template,
|
|
231
238
|
overwriteDir: flags.overwriteDir,
|
|
239
|
+
template,
|
|
232
240
|
},
|
|
233
241
|
});
|
|
234
242
|
// Track the command completion unless telemetry is disabled
|
|
235
243
|
if (!flags.disableTelemetry) {
|
|
236
244
|
await track({
|
|
237
245
|
command: 'init',
|
|
238
|
-
|
|
246
|
+
config: this.config,
|
|
239
247
|
distinctId: this.userConfig.distinctId,
|
|
240
248
|
flags: {
|
|
241
249
|
frontend: chosenFrontend,
|
|
242
250
|
gitInit: initGit,
|
|
243
251
|
installDeps,
|
|
244
|
-
template,
|
|
245
252
|
overwriteDir: flags.overwriteDir,
|
|
253
|
+
template,
|
|
246
254
|
},
|
|
255
|
+
lifecycle: 'complete',
|
|
247
256
|
runId: this.runId,
|
|
248
|
-
config: this.config,
|
|
249
257
|
});
|
|
250
258
|
await shutdown();
|
|
251
259
|
}
|
|
252
|
-
|
|
260
|
+
process.exit(0);
|
|
253
261
|
}
|
|
254
262
|
}
|
package/dist/lib/init/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { note, outro, spinner
|
|
1
|
+
import { log as clackLog, note, outro, spinner } from '@clack/prompts';
|
|
2
2
|
import { ux } from '@oclif/core';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
3
4
|
import { execa } from 'execa';
|
|
4
5
|
import { downloadTemplate } from 'giget';
|
|
5
6
|
import { glob } from 'glob';
|
|
6
7
|
import fs from 'node:fs';
|
|
7
8
|
import { detectPackageManager, installDependencies } from 'nypm';
|
|
8
9
|
import path from 'pathe';
|
|
9
|
-
import dotenv from 'dotenv';
|
|
10
10
|
import ApplyCommand from '../../commands/apply.js';
|
|
11
11
|
import { createDocker } from '../../services/docker.js';
|
|
12
|
+
import { BSL_LICENSE_CTA, BSL_LICENSE_HEADLINE, BSL_LICENSE_TEXT, pinkText } from '../constants.js';
|
|
12
13
|
import catchError from '../utils/catch-error.js';
|
|
13
14
|
import { createGigetString, parseGitHubUrl } from '../utils/parse-github-url.js';
|
|
14
15
|
import { readTemplateConfig } from '../utils/template-config.js';
|
|
15
16
|
import { DOCKER_CONFIG } from './config.js';
|
|
16
|
-
import { BSL_LICENSE_TEXT, BSL_LICENSE_HEADLINE, BSL_LICENSE_CTA, pinkText } from '../constants.js';
|
|
17
17
|
export async function init({ dir, flags }) {
|
|
18
18
|
// Check target directory
|
|
19
19
|
const shouldForce = flags.overwriteDir;
|
|
@@ -36,15 +36,13 @@ export async function init({ dir, flags }) {
|
|
|
36
36
|
});
|
|
37
37
|
// For direct URLs, we need to check if there's a directus directory
|
|
38
38
|
// If not, assume the entire repo is a directus template
|
|
39
|
-
if (isDirectUrl) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
fs.renameSync(path.join(dir, file), path.join(directusDir, file));
|
|
47
|
-
}
|
|
39
|
+
if (isDirectUrl && !fs.existsSync(directusDir)) {
|
|
40
|
+
// Move all files to directus directory
|
|
41
|
+
fs.mkdirSync(directusDir, { recursive: true });
|
|
42
|
+
const files = fs.readdirSync(dir);
|
|
43
|
+
for (const file of files) {
|
|
44
|
+
if (file !== 'directus') {
|
|
45
|
+
fs.renameSync(path.join(dir, file), path.join(directusDir, file));
|
|
48
46
|
}
|
|
49
47
|
}
|
|
50
48
|
}
|
|
@@ -120,6 +118,7 @@ export async function init({ dir, flags }) {
|
|
|
120
118
|
await ApplyCommand.run([
|
|
121
119
|
`--directusUrl=${directusInfo.url || 'http://localhost:8055'}`,
|
|
122
120
|
'-p',
|
|
121
|
+
'--noExit',
|
|
123
122
|
`--userEmail=${directusInfo.email}`,
|
|
124
123
|
`--userPassword=${directusInfo.password}`,
|
|
125
124
|
`--templateLocation=${templatePath}`,
|
|
@@ -161,7 +160,9 @@ export async function init({ dir, flags }) {
|
|
|
161
160
|
const relativeDir = path.relative(process.cwd(), dir);
|
|
162
161
|
const directusUrl = directusInfo.url ?? 'http://localhost:8055';
|
|
163
162
|
const directusText = `- Directus is running on ${directusUrl}. \n`;
|
|
164
|
-
const directusLoginText =
|
|
163
|
+
const directusLoginText = directusInfo.email && directusInfo.password
|
|
164
|
+
? `- You can login with the email: ${pinkText(directusInfo.email)} and password: ${pinkText(directusInfo.password)}. \n`
|
|
165
|
+
: `- Complete the onboarding form at ${pinkText(directusInfo.url || 'http://localhost:8055')} to create your admin account. \n`;
|
|
165
166
|
const frontendText = flags.frontend ? `- To start the frontend, run ${pinkText(`cd ${flags.frontend}`)} and then ${pinkText(`${packageManager?.name} run dev`)}. \n` : '';
|
|
166
167
|
const projectText = `- Navigate to your project directory using ${pinkText(`cd ${relativeDir}`)}. \n`;
|
|
167
168
|
const readmeText = '- Review the \`./README.md\` file for more information and next steps.';
|
|
@@ -3,9 +3,11 @@ export interface ApplyFlags {
|
|
|
3
3
|
dashboards: boolean;
|
|
4
4
|
directusToken: string;
|
|
5
5
|
directusUrl: string;
|
|
6
|
+
disableTelemetry?: boolean;
|
|
6
7
|
extensions: boolean;
|
|
7
8
|
files: boolean;
|
|
8
9
|
flows: boolean;
|
|
10
|
+
noExit?: boolean;
|
|
9
11
|
partial: boolean;
|
|
10
12
|
permissions: boolean;
|
|
11
13
|
programmatic: boolean;
|
|
@@ -16,7 +18,6 @@ export interface ApplyFlags {
|
|
|
16
18
|
userEmail: string;
|
|
17
19
|
userPassword: string;
|
|
18
20
|
users?: boolean;
|
|
19
|
-
disableTelemetry?: boolean;
|
|
20
21
|
}
|
|
21
22
|
export declare const loadFlags: readonly ["content", "dashboards", "extensions", "files", "flows", "permissions", "schema", "settings", "users"];
|
|
22
23
|
export declare function validateProgrammaticFlags(flags: ApplyFlags): ApplyFlags;
|
|
@@ -36,11 +36,9 @@ const removeRequiredorIsNullable = (field) => {
|
|
|
36
36
|
field.meta.required = false;
|
|
37
37
|
}
|
|
38
38
|
if (field.schema?.is_nullable === false) {
|
|
39
|
-
// eslint-disable-next-line camelcase
|
|
40
39
|
field.schema.is_nullable = true;
|
|
41
40
|
}
|
|
42
41
|
if (field.schema?.is_unique === true) {
|
|
43
|
-
// eslint-disable-next-line camelcase
|
|
44
42
|
field.schema.is_unique = false;
|
|
45
43
|
}
|
|
46
44
|
return field;
|
|
@@ -20,12 +20,10 @@ const customDefu = createDefu((obj, key, value) => {
|
|
|
20
20
|
});
|
|
21
21
|
function mergeArrays(key, current, incoming) {
|
|
22
22
|
const mergeKeys = {
|
|
23
|
-
/* eslint-disable camelcase */
|
|
24
23
|
basemaps: ['key'],
|
|
25
24
|
custom_aspect_ratios: ['key'],
|
|
26
25
|
module_bar: ['id', 'type'],
|
|
27
26
|
storage_asset_presets: ['key'],
|
|
28
|
-
/* eslint-enable camelcase */
|
|
29
27
|
};
|
|
30
28
|
const keys = mergeKeys[key];
|
|
31
29
|
if (!keys)
|
package/dist/lib/sdk.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export declare class DirectusError extends Error {
|
|
|
14
14
|
parseErrors(): Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
declare class Api {
|
|
17
|
-
client: (
|
|
17
|
+
client: (AuthenticationClient<Schema> & RestClient<Schema>) | undefined;
|
|
18
18
|
private authData;
|
|
19
19
|
private limiter;
|
|
20
20
|
constructor();
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -3,16 +3,16 @@ export interface DirectusTemplateFrontend {
|
|
|
3
3
|
path: string;
|
|
4
4
|
}
|
|
5
5
|
export interface DirectusTemplateConfig {
|
|
6
|
-
name: string;
|
|
7
6
|
description: string;
|
|
8
|
-
template: string | null;
|
|
9
7
|
frontends: {
|
|
10
8
|
[key: string]: DirectusTemplateFrontend;
|
|
11
9
|
};
|
|
10
|
+
name: string;
|
|
11
|
+
template: null | string;
|
|
12
12
|
}
|
|
13
13
|
export interface TemplatePackageJson {
|
|
14
|
-
name: string;
|
|
15
|
-
version: string;
|
|
16
14
|
description: string;
|
|
17
15
|
'directus:template'?: DirectusTemplateConfig;
|
|
16
|
+
name: string;
|
|
17
|
+
version: string;
|
|
18
18
|
}
|
|
@@ -50,8 +50,8 @@ export async function animatedBunny(customMessage) {
|
|
|
50
50
|
}
|
|
51
51
|
}, 25);
|
|
52
52
|
try {
|
|
53
|
-
// Run the animation for the duration of typing plus
|
|
54
|
-
await new Promise(resolve => setTimeout(resolve, saying.length * 25 +
|
|
53
|
+
// Run the animation for the duration of typing plus 500ms
|
|
54
|
+
await new Promise(resolve => setTimeout(resolve, saying.length * 25 + 500));
|
|
55
55
|
}
|
|
56
56
|
finally {
|
|
57
57
|
cleanup();
|
package/dist/lib/utils/auth.d.ts
CHANGED
|
@@ -23,12 +23,12 @@ export declare function getDirectusEmailAndPassword(): Promise<{
|
|
|
23
23
|
* Initialize the Directus API with the provided flags and log in the user
|
|
24
24
|
* @param flags - The validated ApplyFlags
|
|
25
25
|
* @returns {Promise<void>} - Returns nothing
|
|
26
|
-
*/
|
|
26
|
+
*/
|
|
27
27
|
export declare function initializeDirectusApi(flags: AuthFlags): Promise<void>;
|
|
28
28
|
/**
|
|
29
|
-
* Validate the authentication flags
|
|
30
|
-
* @param flags - The AuthFlags
|
|
31
|
-
* @returns {void} - Errors if the flags are invalid
|
|
32
|
-
*/
|
|
29
|
+
* Validate the authentication flags
|
|
30
|
+
* @param flags - The AuthFlags
|
|
31
|
+
* @returns {void} - Errors if the flags are invalid
|
|
32
|
+
*/
|
|
33
33
|
export declare function validateAuthFlags(flags: AuthFlags): void;
|
|
34
34
|
export {};
|
package/dist/lib/utils/auth.js
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
|
+
import { isCancel, log, password, text } from '@clack/prompts';
|
|
1
2
|
import { readMe } from '@directus/sdk';
|
|
2
|
-
import { text, log, isCancel, password } from '@clack/prompts';
|
|
3
3
|
import { ux } from '@oclif/core';
|
|
4
|
+
import process from 'node:process';
|
|
5
|
+
import { DEFAULT_DIRECTUS_URL } from '../../lib/constants.js';
|
|
4
6
|
import { api } from '../sdk.js';
|
|
5
7
|
import catchError from './catch-error.js';
|
|
6
8
|
import validateUrl from './validate-url.js';
|
|
7
|
-
import { DEFAULT_DIRECTUS_URL } from '../../lib/constants.js';
|
|
8
9
|
/**
|
|
9
10
|
* Get the Directus URL from the user
|
|
10
11
|
* @returns The Directus URL
|
|
11
12
|
*/
|
|
12
13
|
export async function getDirectusUrl() {
|
|
13
14
|
const directusUrl = await text({
|
|
14
|
-
placeholder: DEFAULT_DIRECTUS_URL,
|
|
15
15
|
message: 'What is your Directus URL?',
|
|
16
|
+
placeholder: DEFAULT_DIRECTUS_URL,
|
|
16
17
|
});
|
|
17
18
|
if (isCancel(directusUrl)) {
|
|
18
19
|
log.info('Exiting...');
|
|
19
|
-
|
|
20
|
+
process.exit(0);
|
|
20
21
|
}
|
|
21
22
|
if (!directusUrl) {
|
|
22
23
|
ux.warn(`No URL provided, using default: ${DEFAULT_DIRECTUS_URL}`);
|
|
@@ -37,12 +38,12 @@ export async function getDirectusUrl() {
|
|
|
37
38
|
*/
|
|
38
39
|
export async function getDirectusToken(directusUrl) {
|
|
39
40
|
const directusToken = await text({
|
|
40
|
-
placeholder: 'admin-token-here',
|
|
41
41
|
message: 'What is your Directus Admin Token?',
|
|
42
|
+
placeholder: 'admin-token-here',
|
|
42
43
|
});
|
|
43
44
|
if (isCancel(directusToken)) {
|
|
44
45
|
log.info('Exiting...');
|
|
45
|
-
|
|
46
|
+
process.exit(0);
|
|
46
47
|
}
|
|
47
48
|
// Validate token by fetching the user
|
|
48
49
|
try {
|
|
@@ -72,7 +73,7 @@ export async function getDirectusEmailAndPassword() {
|
|
|
72
73
|
});
|
|
73
74
|
if (isCancel(userEmail)) {
|
|
74
75
|
log.info('Exiting...');
|
|
75
|
-
|
|
76
|
+
process.exit(0);
|
|
76
77
|
}
|
|
77
78
|
const userPassword = await password({
|
|
78
79
|
message: 'What is your password?',
|
|
@@ -84,7 +85,7 @@ export async function getDirectusEmailAndPassword() {
|
|
|
84
85
|
});
|
|
85
86
|
if (isCancel(userPassword)) {
|
|
86
87
|
log.info('Exiting...');
|
|
87
|
-
|
|
88
|
+
process.exit(0);
|
|
88
89
|
}
|
|
89
90
|
return { userEmail, userPassword };
|
|
90
91
|
}
|
|
@@ -92,7 +93,7 @@ export async function getDirectusEmailAndPassword() {
|
|
|
92
93
|
* Initialize the Directus API with the provided flags and log in the user
|
|
93
94
|
* @param flags - The validated ApplyFlags
|
|
94
95
|
* @returns {Promise<void>} - Returns nothing
|
|
95
|
-
*/
|
|
96
|
+
*/
|
|
96
97
|
export async function initializeDirectusApi(flags) {
|
|
97
98
|
api.initialize(flags.directusUrl);
|
|
98
99
|
try {
|
|
@@ -112,10 +113,10 @@ export async function initializeDirectusApi(flags) {
|
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
/**
|
|
115
|
-
* Validate the authentication flags
|
|
116
|
-
* @param flags - The AuthFlags
|
|
117
|
-
* @returns {void} - Errors if the flags are invalid
|
|
118
|
-
*/
|
|
116
|
+
* Validate the authentication flags
|
|
117
|
+
* @param flags - The AuthFlags
|
|
118
|
+
* @returns {void} - Errors if the flags are invalid
|
|
119
|
+
*/
|
|
119
120
|
export function validateAuthFlags(flags) {
|
|
120
121
|
if (!flags.directusUrl) {
|
|
121
122
|
ux.error('Directus URL is required.');
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ux } from '@oclif/core';
|
|
2
|
+
import { getExecutionContext } from '../../services/execution-context.js';
|
|
3
|
+
import { captureException } from '../../services/posthog.js';
|
|
2
4
|
import { DirectusError } from '../sdk.js';
|
|
3
5
|
import { logger } from '../utils/logger.js';
|
|
4
|
-
import { captureException } from '../../services/posthog.js';
|
|
5
|
-
import { getExecutionContext } from '../../services/execution-context.js';
|
|
6
6
|
/**
|
|
7
7
|
* Handles errors by formatting them and optionally logging to console and file.
|
|
8
8
|
* @param error - The error to be handled.
|
|
@@ -11,7 +11,7 @@ import { getExecutionContext } from '../../services/execution-context.js';
|
|
|
11
11
|
*/
|
|
12
12
|
export default function catchError(error, options = {}) {
|
|
13
13
|
const { context = {}, fatal = false, logToFile = true } = options;
|
|
14
|
-
const {
|
|
14
|
+
const { disableTelemetry, distinctId } = getExecutionContext();
|
|
15
15
|
let errorMessage;
|
|
16
16
|
if (error instanceof DirectusError) {
|
|
17
17
|
errorMessage = error.message;
|
|
@@ -24,7 +24,7 @@ export default function catchError(error, options = {}) {
|
|
|
24
24
|
}
|
|
25
25
|
// Capture exception before logging/exiting
|
|
26
26
|
if (!disableTelemetry && distinctId) {
|
|
27
|
-
captureException({
|
|
27
|
+
captureException({ distinctId, error, properties: { context } });
|
|
28
28
|
}
|
|
29
29
|
// Format the error message with context if provided
|
|
30
30
|
const formattedMessage = [
|
package/dist/lib/utils/logger.js
CHANGED
|
@@ -30,7 +30,7 @@ class Logger {
|
|
|
30
30
|
this.writeToFile(`Log started at ${timestamp}\n`);
|
|
31
31
|
}
|
|
32
32
|
sanitize(obj) {
|
|
33
|
-
const sensitiveFields = new Set(['
|
|
33
|
+
const sensitiveFields = new Set(['access_token', 'authorization', 'email', 'key', 'password', 'refresh_token', 'secret', 'token']);
|
|
34
34
|
return Object.fromEntries(Object.entries(obj).map(([key, value]) => {
|
|
35
35
|
if (sensitiveFields.has(key.toLowerCase())) {
|
|
36
36
|
return [key, '********'];
|
|
@@ -25,7 +25,7 @@ function cleanGitHubUrl(url) {
|
|
|
25
25
|
parsed.hash = '';
|
|
26
26
|
return parsed.toString();
|
|
27
27
|
}
|
|
28
|
-
catch
|
|
28
|
+
catch {
|
|
29
29
|
// If URL parsing fails, just remove .git suffix
|
|
30
30
|
return url.replace(/\.git$/, '');
|
|
31
31
|
}
|
|
@@ -80,7 +80,7 @@ export function parseGitHubUrl(url) {
|
|
|
80
80
|
// Ensure path is undefined if empty string
|
|
81
81
|
if (path === '')
|
|
82
82
|
path = undefined;
|
|
83
|
-
return { owner,
|
|
83
|
+
return { owner, path, ref, repo };
|
|
84
84
|
}
|
|
85
85
|
catch (error) {
|
|
86
86
|
throw new Error(`Invalid GitHub URL: ${url}. Error: ${error.message}`);
|
|
@@ -92,7 +92,7 @@ export function parseGitHubUrl(url) {
|
|
|
92
92
|
const [owner, repo, ...rest] = parts;
|
|
93
93
|
const path = rest.length > 0 ? rest.join('/') : undefined;
|
|
94
94
|
// Assume default branch for simple paths unless we add ref detection here too
|
|
95
|
-
return { owner,
|
|
95
|
+
return { owner, path, ref: DEFAULT_BRANCH, repo };
|
|
96
96
|
}
|
|
97
97
|
// Handle simple template names using DEFAULT_REPO
|
|
98
98
|
return {
|
package/dist/lib/utils/path.js
CHANGED
|
@@ -2,6 +2,6 @@ interface Template {
|
|
|
2
2
|
directoryPath: string;
|
|
3
3
|
templateName: string;
|
|
4
4
|
}
|
|
5
|
-
export declare function readTemplate(directoryPath: string): Promise<
|
|
5
|
+
export declare function readTemplate(directoryPath: string): Promise<null | Template>;
|
|
6
6
|
export declare function readAllTemplates(directoryPath: string): Promise<Template[]>;
|
|
7
7
|
export {};
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
const SENSITIVE_FLAGS = ['
|
|
2
|
-
export const sanitizeFlags = (flags) =>
|
|
3
|
-
return Object.fromEntries(Object.entries(flags).filter(([key]) => !SENSITIVE_FLAGS.includes(key)));
|
|
4
|
-
};
|
|
1
|
+
const SENSITIVE_FLAGS = new Set(['directusToken', 'userEmail', 'userPassword']);
|
|
2
|
+
export const sanitizeFlags = (flags) => Object.fromEntries(Object.entries(flags).filter(([key]) => !SENSITIVE_FLAGS.has(key)));
|
|
@@ -13,4 +13,4 @@ export interface TemplateInfo {
|
|
|
13
13
|
* @returns Template configuration and frontend options
|
|
14
14
|
* @throws Error if package.json is missing or invalid
|
|
15
15
|
*/
|
|
16
|
-
export declare function readTemplateConfig(dir: string):
|
|
16
|
+
export declare function readTemplateConfig(dir: string): null | TemplateInfo;
|
package/dist/services/docker.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { log, spinner } from '@clack/prompts';
|
|
2
|
+
import { ux } from '@oclif/core';
|
|
2
3
|
import { execa } from 'execa';
|
|
3
4
|
import net from 'node:net';
|
|
4
|
-
import { ux } from '@oclif/core';
|
|
5
5
|
import catchError from '../lib/utils/catch-error.js';
|
|
6
6
|
import { waitFor } from '../lib/utils/wait.js';
|
|
7
7
|
/**
|
|
@@ -41,11 +41,11 @@ async function checkPort(port) {
|
|
|
41
41
|
*/
|
|
42
42
|
async function checkRequiredPorts() {
|
|
43
43
|
const portsToCheck = [
|
|
44
|
-
{
|
|
45
|
-
{
|
|
44
|
+
{ name: 'Directus API', port: 8055 },
|
|
45
|
+
{ name: 'PostgreSQL', port: 5432 },
|
|
46
46
|
];
|
|
47
47
|
let hasConflicts = false;
|
|
48
|
-
for (const {
|
|
48
|
+
for (const { name, port } of portsToCheck) {
|
|
49
49
|
const status = await checkPort(port);
|
|
50
50
|
if (status.inUse) {
|
|
51
51
|
hasConflicts = true;
|
|
@@ -63,27 +63,32 @@ async function checkRequiredPorts() {
|
|
|
63
63
|
* @returns {Promise<DockerCheckResult>} Docker installation and running status
|
|
64
64
|
*/
|
|
65
65
|
async function checkDocker() {
|
|
66
|
+
// First check if Docker is installed
|
|
66
67
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
await execa('docker', ['--version']);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Docker is not installed
|
|
72
|
+
return {
|
|
73
|
+
installed: false,
|
|
74
|
+
message: 'Docker is not installed. Please install Docker at https://docs.docker.com/get-started/get-docker/',
|
|
75
|
+
running: false,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// Docker is installed, now check if it's running
|
|
79
|
+
try {
|
|
80
|
+
await execa('docker', ['info']);
|
|
76
81
|
return {
|
|
77
82
|
installed: true,
|
|
78
83
|
message: 'Docker is installed and running.',
|
|
79
|
-
running:
|
|
84
|
+
running: true,
|
|
80
85
|
};
|
|
81
86
|
}
|
|
82
87
|
catch {
|
|
83
|
-
//
|
|
88
|
+
// Docker is installed but not running
|
|
84
89
|
return {
|
|
85
|
-
installed:
|
|
86
|
-
message: 'Docker is not running. Please start Docker
|
|
90
|
+
installed: true,
|
|
91
|
+
message: 'Docker is installed but not running. Please start Docker before running the init command.',
|
|
87
92
|
running: false,
|
|
88
93
|
};
|
|
89
94
|
}
|
|
@@ -129,7 +134,7 @@ async function checkImagesExist(imageNames) {
|
|
|
129
134
|
// This catch block might be redundant due to allSettled, but good for safety
|
|
130
135
|
log.error('Error checking for Docker images.');
|
|
131
136
|
catchError(error, {
|
|
132
|
-
context: {
|
|
137
|
+
context: { function: 'checkImagesExist', imageNames },
|
|
133
138
|
fatal: false,
|
|
134
139
|
logToFile: true,
|
|
135
140
|
});
|
|
@@ -6,9 +6,9 @@ interface GitHubUrlParts {
|
|
|
6
6
|
repo: string;
|
|
7
7
|
}
|
|
8
8
|
export interface TemplateInfo {
|
|
9
|
+
description?: string;
|
|
9
10
|
id: string;
|
|
10
11
|
name: string;
|
|
11
|
-
description?: string;
|
|
12
12
|
}
|
|
13
13
|
export interface GitHubService {
|
|
14
14
|
getTemplateDirectories(template: string, customUrl?: string): Promise<string[]>;
|