directus-template-cli 0.6.0-beta.2 → 0.7.0-beta.10

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.
Files changed (114) hide show
  1. package/README.md +0 -14
  2. package/bin/dev.js +6 -0
  3. package/bin/run.js +5 -0
  4. package/dist/commands/apply.d.ts +17 -17
  5. package/dist/commands/apply.js +166 -174
  6. package/dist/commands/base.d.ts +15 -0
  7. package/dist/commands/base.js +45 -0
  8. package/dist/commands/extract.d.ts +16 -9
  9. package/dist/commands/extract.js +81 -100
  10. package/dist/commands/init.d.ts +42 -0
  11. package/dist/commands/init.js +241 -0
  12. package/dist/flags/common.d.ts +8 -7
  13. package/dist/flags/common.js +13 -11
  14. package/dist/index.js +1 -5
  15. package/dist/lib/constants.d.ts +18 -0
  16. package/dist/lib/constants.js +25 -6
  17. package/dist/lib/extract/extract-access.js +11 -15
  18. package/dist/lib/extract/extract-assets.js +20 -25
  19. package/dist/lib/extract/extract-collections.js +12 -16
  20. package/dist/lib/extract/extract-content.d.ts +1 -1
  21. package/dist/lib/extract/extract-content.js +17 -26
  22. package/dist/lib/extract/extract-dashboards.js +22 -28
  23. package/dist/lib/extract/extract-extensions.js +12 -16
  24. package/dist/lib/extract/extract-fields.js +12 -16
  25. package/dist/lib/extract/extract-files.js +15 -19
  26. package/dist/lib/extract/extract-flows.js +22 -28
  27. package/dist/lib/extract/extract-folders.js +15 -19
  28. package/dist/lib/extract/extract-permissions.js +12 -16
  29. package/dist/lib/extract/extract-policies.js +12 -16
  30. package/dist/lib/extract/extract-presets.js +12 -16
  31. package/dist/lib/extract/extract-relations.js +14 -18
  32. package/dist/lib/extract/extract-roles.js +15 -19
  33. package/dist/lib/extract/extract-schema.js +17 -21
  34. package/dist/lib/extract/extract-settings.js +12 -16
  35. package/dist/lib/extract/extract-translations.js +12 -16
  36. package/dist/lib/extract/extract-users.js +15 -19
  37. package/dist/lib/extract/index.d.ts +1 -6
  38. package/dist/lib/extract/index.js +47 -58
  39. package/dist/lib/init/config.d.ts +3 -0
  40. package/dist/lib/init/config.js +12 -0
  41. package/dist/lib/init/index.d.ts +10 -0
  42. package/dist/lib/init/index.js +192 -0
  43. package/dist/lib/init/types.d.ts +30 -0
  44. package/dist/lib/init/types.js +1 -0
  45. package/dist/lib/load/apply-flags.js +17 -23
  46. package/dist/lib/load/index.d.ts +1 -12
  47. package/dist/lib/load/index.js +40 -44
  48. package/dist/lib/load/load-access.js +15 -20
  49. package/dist/lib/load/load-collections.d.ts +2 -0
  50. package/dist/lib/load/load-collections.js +29 -32
  51. package/dist/lib/load/load-dashboards.js +19 -25
  52. package/dist/lib/load/load-data.js +43 -49
  53. package/dist/lib/load/load-extensions.js +30 -38
  54. package/dist/lib/load/load-files.js +20 -24
  55. package/dist/lib/load/load-flows.js +23 -29
  56. package/dist/lib/load/load-folders.js +16 -20
  57. package/dist/lib/load/load-permissions.js +13 -17
  58. package/dist/lib/load/load-policies.js +14 -18
  59. package/dist/lib/load/load-presets.js +14 -18
  60. package/dist/lib/load/load-relations.d.ts +2 -0
  61. package/dist/lib/load/load-relations.js +16 -18
  62. package/dist/lib/load/load-roles.js +19 -23
  63. package/dist/lib/load/load-settings.js +18 -21
  64. package/dist/lib/load/load-translations.js +14 -18
  65. package/dist/lib/load/load-users.js +21 -25
  66. package/dist/lib/load/update-required-fields.js +13 -17
  67. package/dist/lib/sdk.d.ts +1 -2
  68. package/dist/lib/sdk.js +27 -27
  69. package/dist/lib/types/extension.js +1 -2
  70. package/dist/lib/types.d.ts +18 -0
  71. package/dist/lib/types.js +1 -0
  72. package/dist/lib/utils/animated-bunny.d.ts +2 -0
  73. package/dist/lib/utils/animated-bunny.js +62 -0
  74. package/dist/lib/utils/auth.d.ts +8 -6
  75. package/dist/lib/utils/auth.js +48 -39
  76. package/dist/lib/utils/catch-error.js +8 -11
  77. package/dist/lib/utils/check-template.js +4 -8
  78. package/dist/lib/utils/chunk-array.js +1 -5
  79. package/dist/lib/utils/ensure-dir.d.ts +2 -0
  80. package/dist/lib/utils/ensure-dir.js +11 -0
  81. package/dist/lib/utils/filter-fields.js +1 -4
  82. package/dist/lib/utils/get-role-ids.d.ts +1 -1
  83. package/dist/lib/utils/get-role-ids.js +7 -12
  84. package/dist/lib/utils/get-template.js +33 -36
  85. package/dist/lib/utils/logger.js +11 -13
  86. package/dist/lib/utils/open-url.js +5 -8
  87. package/dist/lib/utils/parse-github-url.d.ts +19 -0
  88. package/dist/lib/utils/parse-github-url.js +89 -0
  89. package/dist/lib/utils/path.js +6 -10
  90. package/dist/lib/utils/protected-domains.js +1 -4
  91. package/dist/lib/utils/read-file.js +8 -12
  92. package/dist/lib/utils/read-templates.js +9 -15
  93. package/dist/lib/utils/sanitize-flags.d.ts +3 -0
  94. package/dist/lib/utils/sanitize-flags.js +4 -0
  95. package/dist/lib/utils/system-fields.js +19 -22
  96. package/dist/lib/utils/template-config.d.ts +16 -0
  97. package/dist/lib/utils/template-config.js +34 -0
  98. package/dist/lib/utils/template-defaults.d.ts +1 -1
  99. package/dist/lib/utils/template-defaults.js +5 -14
  100. package/dist/lib/utils/transform-github-url.js +1 -5
  101. package/dist/lib/utils/validate-url.js +3 -6
  102. package/dist/lib/utils/wait.d.ts +7 -0
  103. package/dist/lib/utils/wait.js +9 -0
  104. package/dist/lib/utils/write-to-file.js +8 -11
  105. package/dist/services/docker.d.ts +23 -0
  106. package/dist/services/docker.js +187 -0
  107. package/dist/services/github.d.ts +18 -0
  108. package/dist/services/github.js +88 -0
  109. package/dist/services/posthog.d.ts +37 -0
  110. package/dist/services/posthog.js +104 -0
  111. package/oclif.manifest.json +102 -23
  112. package/package.json +46 -29
  113. package/bin/dev +0 -17
  114. package/bin/run +0 -5
package/README.md CHANGED
@@ -181,18 +181,6 @@ Using email/password:
181
181
  npx directus-template-cli@latest extract -p --templateName="My Template" --templateLocation="./my-template" --userEmail="admin@example.com" --userPassword="admin" --directusUrl="http://localhost:8055"
182
182
  ```
183
183
 
184
- Skipping extracting content from sensitive or large collections:
185
-
186
- ```
187
- npx directus-template-cli@latest extract -p --templateName="My Template" --templateLocation="./my-template" --directusToken="admin-token-here" --directusUrl="http://localhost:8055" --excludeCollections="posts,globals"
188
- ```
189
-
190
- Skipping extracting files and assets:
191
-
192
- ```
193
- npx directus-template-cli@latest extract -p --templateName="My Template" --templateLocation="./my-template" --directusToken="admin-token-here" --directusUrl="http://localhost:8055" --skipFiles
194
- ```
195
-
196
184
  Available flags for programmatic mode:
197
185
 
198
186
  - `--directusUrl`: URL of the Directus instance to extract the template from (required)
@@ -201,8 +189,6 @@ Available flags for programmatic mode:
201
189
  - `--userPassword`: Password for Directus authentication (required if not using token)
202
190
  - `--templateLocation`: Directory to extract the template to (required)
203
191
  - `--templateName`: Name of the template (required)
204
- - `--excludeCollections`: Comma-separated list of collection names to exclude from extraction
205
- - `--skipFiles`: Skip extracting files and assets
206
192
 
207
193
  #### Using Environment Variables
208
194
 
package/bin/dev.js ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env -S node --loader ts-node/esm --disable-warning=ExperimentalWarning
2
+
3
+ // eslint-disable-next-line n/shebang
4
+ import {execute} from '@oclif/core'
5
+
6
+ await execute({development: true, dir: import.meta.url})
package/bin/run.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {execute} from '@oclif/core'
4
+
5
+ await execute({dir: import.meta.url})
@@ -3,23 +3,23 @@ export default class ApplyCommand extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static flags: {
6
- content: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
- dashboards: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
8
- directusToken: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
9
- directusUrl: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
- extensions: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
- files: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
12
- flows: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
13
- partial: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
14
- permissions: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
- programmatic: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
- schema: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
17
- settings: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
18
- templateLocation: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
19
- templateType: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
20
- userEmail: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
21
- userPassword: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
22
- users: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
6
+ content: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ dashboards: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ directusToken: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
+ directusUrl: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ extensions: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ files: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ flows: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ partial: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ permissions: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
+ programmatic: import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
+ schema: import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
+ settings: import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
+ templateLocation: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
19
+ templateType: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
20
+ userEmail: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
21
+ userPassword: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
22
+ users: import("@oclif/core/interfaces").BooleanFlag<boolean>;
23
23
  };
24
24
  /**
25
25
  * MAIN
@@ -1,19 +1,92 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const core_1 = require("@oclif/core");
5
- const inquirer = tslib_1.__importStar(require("inquirer"));
6
- const path = tslib_1.__importStar(require("node:path"));
7
- const customFlags = tslib_1.__importStar(require("../flags/common"));
8
- const constants_1 = require("../lib/constants");
9
- const apply_flags_1 = require("../lib/load/apply-flags");
10
- const index_js_1 = tslib_1.__importDefault(require("../lib/load/index.js"));
11
- const auth_1 = require("../lib/utils/auth");
12
- const catch_error_1 = tslib_1.__importDefault(require("../lib/utils/catch-error"));
13
- const get_template_1 = require("../lib/utils/get-template");
14
- const logger_1 = require("../lib/utils/logger");
15
- const open_url_1 = tslib_1.__importDefault(require("../lib/utils/open-url"));
16
- class ApplyCommand extends core_1.Command {
1
+ import { Command, Flags, ux } from '@oclif/core';
2
+ import { text, select, password, log, intro } from '@clack/prompts';
3
+ import * as path from 'pathe';
4
+ import { animatedBunny } from '../lib/utils/animated-bunny.js';
5
+ import { BSL_LICENSE_TEXT } from '../lib/constants.js';
6
+ import * as customFlags from '../flags/common.js';
7
+ import { DIRECTUS_PINK, DIRECTUS_PURPLE, SEPARATOR } from '../lib/constants.js';
8
+ import { validateInteractiveFlags, validateProgrammaticFlags } from '../lib/load/apply-flags.js';
9
+ import apply from '../lib/load/index.js';
10
+ import { getDirectusToken, getDirectusUrl, initializeDirectusApi } from '../lib/utils/auth.js';
11
+ import catchError from '../lib/utils/catch-error.js';
12
+ import { getCommunityTemplates, getGithubTemplate, getInteractiveLocalTemplate, getLocalTemplate } from '../lib/utils/get-template.js';
13
+ import { logger } from '../lib/utils/logger.js';
14
+ import openUrl from '../lib/utils/open-url.js';
15
+ import chalk from 'chalk';
16
+ export default class ApplyCommand extends Command {
17
+ static description = 'Apply a template to a blank Directus instance.';
18
+ static examples = [
19
+ '$ directus-template-cli apply',
20
+ '$ directus-template-cli apply -p --directusUrl="http://localhost:8055" --directusToken="admin-token-here" --templateLocation="./my-template" --templateType="local"',
21
+ '$ directus-template-cli@beta apply -p --directusUrl="http://localhost:8055" --directusToken="admin-token-here" --templateLocation="./my-template" --templateType="local" --partial --no-content --no-users',
22
+ ];
23
+ static flags = {
24
+ content: Flags.boolean({
25
+ allowNo: true,
26
+ default: undefined,
27
+ description: 'Load Content (data)',
28
+ }),
29
+ dashboards: Flags.boolean({
30
+ allowNo: true,
31
+ default: undefined,
32
+ description: 'Load Dashboards (dashboards, panels)',
33
+ }),
34
+ directusToken: customFlags.directusToken,
35
+ directusUrl: customFlags.directusUrl,
36
+ extensions: Flags.boolean({
37
+ allowNo: true,
38
+ default: undefined,
39
+ description: 'Load Extensions',
40
+ }),
41
+ files: Flags.boolean({
42
+ allowNo: true,
43
+ default: undefined,
44
+ description: 'Load Files (files, folders)',
45
+ }),
46
+ flows: Flags.boolean({
47
+ allowNo: true,
48
+ default: undefined,
49
+ description: 'Load Flows (operations, flows)',
50
+ }),
51
+ partial: Flags.boolean({
52
+ dependsOn: ['programmatic'],
53
+ description: 'Enable partial template application (all components enabled by default)',
54
+ summary: 'Enable partial template application',
55
+ }),
56
+ permissions: Flags.boolean({
57
+ allowNo: true,
58
+ default: undefined,
59
+ description: 'Loads permissions data. Collections include: directus_roles, directus_policies, directus_access, directus_permissions.',
60
+ summary: 'Load permissions (roles, policies, access, permissions)',
61
+ }),
62
+ programmatic: customFlags.programmatic,
63
+ schema: Flags.boolean({
64
+ allowNo: true,
65
+ default: undefined,
66
+ description: 'Load schema (collections, relations)',
67
+ }),
68
+ settings: Flags.boolean({
69
+ allowNo: true,
70
+ default: undefined,
71
+ description: 'Load settings (project settings, translations, presets)',
72
+ }),
73
+ templateLocation: customFlags.templateLocation,
74
+ templateType: Flags.string({
75
+ default: 'local',
76
+ dependsOn: ['programmatic'],
77
+ description: 'Type of template to apply. You can apply templates from our community repo, local directories, or public repositories from Github. Defaults to local. ',
78
+ env: 'TEMPLATE_TYPE',
79
+ options: ['community', 'local', 'github'],
80
+ summary: 'Type of template to apply. Options: community, local, github.',
81
+ }),
82
+ userEmail: customFlags.userEmail,
83
+ userPassword: customFlags.userPassword,
84
+ users: Flags.boolean({
85
+ allowNo: true,
86
+ default: undefined,
87
+ description: 'Load users',
88
+ }),
89
+ };
17
90
  /**
18
91
  * MAIN
19
92
  * Run the command
@@ -31,88 +104,85 @@ class ApplyCommand extends core_1.Command {
31
104
  * @returns {Promise<void>} - Returns nothing
32
105
  */
33
106
  async runInteractive(flags) {
34
- const validatedFlags = (0, apply_flags_1.validateInteractiveFlags)(flags);
35
- core_1.ux.styledHeader(core_1.ux.colorize(constants_1.DIRECTUS_PURPLE, 'Directus Template CLI - Apply'));
36
- const templateType = await inquirer.prompt([
37
- {
38
- choices: [
39
- { name: 'Community templates', value: 'community' },
40
- { name: 'From a local directory', value: 'local' },
41
- { name: 'From a public GitHub repository', value: 'github' },
42
- { name: 'Get premium templates', value: 'directus-plus' },
43
- ],
44
- message: 'What type of template would you like to apply?',
45
- name: 'templateType',
46
- type: 'list',
47
- },
48
- ]);
107
+ const validatedFlags = validateInteractiveFlags(flags);
108
+ // Show animated intro
109
+ await animatedBunny('Let\'s apply a template!');
110
+ intro(`${chalk.bgHex(DIRECTUS_PURPLE).white.bold('Directus Template CLI')} - Apply Template`);
111
+ const templateType = await select({
112
+ options: [
113
+ { label: 'Community templates', value: 'community' },
114
+ { label: 'From a local directory', value: 'local' },
115
+ { label: 'From a public GitHub repository', value: 'github' },
116
+ { label: 'Get premium templates', value: 'directus-plus' },
117
+ ],
118
+ message: 'What type of template would you like to apply?',
119
+ });
49
120
  let template;
50
- switch (templateType.templateType) {
121
+ switch (templateType) {
51
122
  case 'community': {
52
- const templates = await (0, get_template_1.getCommunityTemplates)();
53
- const { selectedTemplate } = await inquirer.prompt([
54
- {
55
- choices: templates.map(t => ({ name: t.templateName, value: t })),
56
- message: 'Select a template.',
57
- name: 'selectedTemplate',
58
- type: 'list',
59
- },
60
- ]);
123
+ const templates = await getCommunityTemplates();
124
+ const selectedTemplate = await select({
125
+ options: templates.map(t => ({ label: t.templateName, value: t })),
126
+ message: 'Select a template.',
127
+ });
61
128
  template = selectedTemplate;
62
129
  break;
63
130
  }
64
131
  case 'local': {
65
- const localTemplateDir = await core_1.ux.prompt('What is the local template directory?');
132
+ const localTemplateDir = await text({
133
+ message: 'What is the local template directory?',
134
+ });
66
135
  template = await this.selectLocalTemplate(localTemplateDir);
67
136
  break;
68
137
  }
69
138
  case 'github': {
70
- const ghTemplateUrl = await core_1.ux.prompt('What is the public GitHub repository URL?');
71
- template = await (0, get_template_1.getGithubTemplate)(ghTemplateUrl);
139
+ const ghTemplateUrl = await text({
140
+ message: 'What is the public GitHub repository URL?',
141
+ });
142
+ template = await getGithubTemplate(ghTemplateUrl);
72
143
  break;
73
144
  }
74
145
  case 'directus-plus': {
75
- (0, open_url_1.default)('https://directus.io/plus?utm_source=directus-template-cli&utm_content=apply-command');
76
- core_1.ux.log('Redirecting to Directus website.');
77
- core_1.ux.exit(0);
146
+ openUrl('https://directus.io/plus?utm_source=directus-template-cli&utm_content=apply-command');
147
+ log.info('Redirecting to Directus website.');
148
+ ux.exit(0);
78
149
  }
79
150
  }
80
- core_1.ux.log(`You selected ${core_1.ux.colorize(constants_1.DIRECTUS_PINK, template.templateName)}`);
81
- core_1.ux.log(constants_1.SEPARATOR);
151
+ log.info(`You selected ${ux.colorize(DIRECTUS_PINK, template.templateName)}`);
82
152
  // Get Directus URL
83
- const directusUrl = await (0, auth_1.getDirectusUrl)();
153
+ const directusUrl = await getDirectusUrl();
84
154
  validatedFlags.directusUrl = directusUrl;
85
155
  // Prompt for login method
86
- const loginMethod = await inquirer.prompt([
87
- {
88
- choices: [
89
- { name: 'Directus Access Token', value: 'token' },
90
- { name: 'Email and Password', value: 'email' },
91
- ],
92
- default: 'token',
93
- message: 'How do you want to log in?',
94
- name: 'loginMethod',
95
- type: 'list',
96
- },
97
- ]);
98
- if (loginMethod.loginMethod === 'token') {
99
- const directusToken = await (0, auth_1.getDirectusToken)(directusUrl);
156
+ const loginMethod = await select({
157
+ options: [
158
+ { label: 'Directus Access Token', value: 'token' },
159
+ { label: 'Email and Password', value: 'email' },
160
+ ],
161
+ message: 'How do you want to log in?',
162
+ });
163
+ if (loginMethod === 'token') {
164
+ const directusToken = await getDirectusToken(directusUrl);
100
165
  validatedFlags.directusToken = directusToken;
101
166
  }
102
167
  else {
103
- const userEmail = await core_1.ux.prompt('What is your email?');
168
+ const userEmail = await text({
169
+ message: 'What is your email?',
170
+ });
104
171
  validatedFlags.userEmail = userEmail;
105
- const userPassword = await core_1.ux.prompt('What is your password?', { type: 'hide' });
172
+ const userPassword = await password({
173
+ message: 'What is your password?',
174
+ });
106
175
  validatedFlags.userPassword = userPassword;
107
176
  }
108
- await (0, auth_1.initializeDirectusApi)(validatedFlags);
177
+ await initializeDirectusApi(validatedFlags);
109
178
  if (template) {
110
- core_1.ux.styledHeader(core_1.ux.colorize(constants_1.DIRECTUS_PURPLE, `Applying template - ${template.templateName} to ${directusUrl}`));
111
- await (0, index_js_1.default)(template.directoryPath, validatedFlags);
112
- core_1.ux.action.stop();
113
- core_1.ux.log(constants_1.SEPARATOR);
114
- core_1.ux.info('Template applied successfully.');
115
- core_1.ux.exit(0);
179
+ // /* TODO: Replace with custom styledHeader function */ ux.styledHeader(ux.colorize(DIRECTUS_PURPLE, `Applying template - ${template.templateName} to ${directusUrl}`))
180
+ await apply(template.directoryPath, validatedFlags);
181
+ ux.action.stop();
182
+ ux.stdout(SEPARATOR);
183
+ log.warn(BSL_LICENSE_TEXT);
184
+ ux.stdout('Template applied successfully.');
185
+ ux.exit(0);
116
186
  }
117
187
  }
118
188
  /**
@@ -122,37 +192,37 @@ class ApplyCommand extends core_1.Command {
122
192
  * @returns {Promise<void>} - Returns nothing
123
193
  */
124
194
  async runProgrammatic(flags) {
125
- const validatedFlags = (0, apply_flags_1.validateProgrammaticFlags)(flags);
195
+ const validatedFlags = validateProgrammaticFlags(flags);
126
196
  let template;
127
197
  switch (validatedFlags.templateType) {
128
198
  case 'community': {
129
- const templates = await (0, get_template_1.getCommunityTemplates)();
199
+ const templates = await getCommunityTemplates();
130
200
  template = templates.find(t => t.templateName === validatedFlags.templateLocation) || templates[0];
131
201
  break;
132
202
  }
133
203
  case 'local': {
134
- template = await (0, get_template_1.getLocalTemplate)(validatedFlags.templateLocation);
204
+ template = await getLocalTemplate(validatedFlags.templateLocation);
135
205
  break;
136
206
  }
137
207
  case 'github': {
138
- template = await (0, get_template_1.getGithubTemplate)(validatedFlags.templateLocation);
208
+ template = await getGithubTemplate(validatedFlags.templateLocation);
139
209
  break;
140
210
  }
141
211
  default: {
142
- (0, catch_error_1.default)('Invalid template type. Please check your template type.', {
212
+ catchError('Invalid template type. Please check your template type.', {
143
213
  fatal: true,
144
214
  });
145
215
  }
146
216
  }
147
- await (0, auth_1.initializeDirectusApi)(validatedFlags);
217
+ await initializeDirectusApi(validatedFlags);
148
218
  const logMessage = `Applying template - ${template.templateName} to ${validatedFlags.directusUrl}`;
149
- core_1.ux.styledHeader(logMessage);
150
- logger_1.logger.log('info', logMessage);
151
- await (0, index_js_1.default)(template.directoryPath, validatedFlags);
152
- core_1.ux.action.stop();
153
- core_1.ux.log(constants_1.SEPARATOR);
154
- core_1.ux.info('Template applied successfully.');
155
- core_1.ux.exit(0);
219
+ // /* TODO: Replace with custom styledHeader function */ ux.styledHeader(logMessage)
220
+ logger.log('info', logMessage);
221
+ await apply(template.directoryPath, validatedFlags);
222
+ ux.action.stop();
223
+ ux.stdout(SEPARATOR);
224
+ ux.stdout('Template applied successfully.');
225
+ // ux.exit(0)
156
226
  }
157
227
  /**
158
228
  * INTERACTIVE
@@ -162,104 +232,26 @@ class ApplyCommand extends core_1.Command {
162
232
  */
163
233
  async selectLocalTemplate(localTemplateDir) {
164
234
  try {
165
- const templates = await (0, get_template_1.getInteractiveLocalTemplate)(localTemplateDir);
235
+ const templates = await getInteractiveLocalTemplate(localTemplateDir);
166
236
  if (templates.length === 1) {
167
237
  return templates[0];
168
238
  }
169
- const { selectedTemplate } = await inquirer.prompt([
170
- {
171
- choices: templates.map(t => ({
172
- name: `${t.templateName} (${path.basename(t.directoryPath)})`,
173
- value: t,
174
- })),
175
- message: 'Multiple templates found. Please select one:',
176
- name: 'selectedTemplate',
177
- type: 'list',
178
- },
179
- ]);
239
+ const selectedTemplate = await select({
240
+ options: templates.map(t => ({
241
+ label: `${t.templateName} (${path.basename(t.directoryPath)})`,
242
+ value: t,
243
+ })),
244
+ message: 'Multiple templates found. Please select one:',
245
+ });
180
246
  return selectedTemplate;
181
247
  }
182
248
  catch (error) {
183
249
  if (error instanceof Error) {
184
- core_1.ux.error(error.message);
250
+ ux.error(error.message);
185
251
  }
186
252
  else {
187
- core_1.ux.error('An unknown error occurred while getting the local template.');
253
+ ux.error('An unknown error occurred while getting the local template.');
188
254
  }
189
255
  }
190
256
  }
191
257
  }
192
- ApplyCommand.description = 'Apply a template to a blank Directus instance.';
193
- ApplyCommand.examples = [
194
- '$ directus-template-cli apply',
195
- '$ directus-template-cli apply -p --directusUrl="http://localhost:8055" --directusToken="admin-token-here" --templateLocation="./my-template" --templateType="local"',
196
- '$ directus-template-cli@beta apply -p --directusUrl="http://localhost:8055" --directusToken="admin-token-here" --templateLocation="./my-template" --templateType="local" --partial --no-content --no-users',
197
- ];
198
- ApplyCommand.flags = {
199
- content: core_1.Flags.boolean({
200
- allowNo: true,
201
- default: undefined,
202
- description: 'Load Content (data)',
203
- }),
204
- dashboards: core_1.Flags.boolean({
205
- allowNo: true,
206
- default: undefined,
207
- description: 'Load Dashboards (dashboards, panels)',
208
- }),
209
- directusToken: customFlags.directusToken,
210
- directusUrl: customFlags.directusUrl,
211
- extensions: core_1.Flags.boolean({
212
- allowNo: true,
213
- default: undefined,
214
- description: 'Load Extensions',
215
- }),
216
- files: core_1.Flags.boolean({
217
- allowNo: true,
218
- default: undefined,
219
- description: 'Load Files (files, folders)',
220
- }),
221
- flows: core_1.Flags.boolean({
222
- allowNo: true,
223
- default: undefined,
224
- description: 'Load Flows (operations, flows)',
225
- }),
226
- partial: core_1.Flags.boolean({
227
- dependsOn: ['programmatic'],
228
- description: 'Enable partial template application (all components enabled by default)',
229
- summary: 'Enable partial template application',
230
- }),
231
- permissions: core_1.Flags.boolean({
232
- allowNo: true,
233
- default: undefined,
234
- description: 'Loads permissions data. Collections include: directus_roles, directus_policies, directus_access, directus_permissions.',
235
- summary: 'Load permissions (roles, policies, access, permissions)',
236
- }),
237
- programmatic: customFlags.programmatic,
238
- schema: core_1.Flags.boolean({
239
- allowNo: true,
240
- default: undefined,
241
- description: 'Load schema (collections, relations)',
242
- }),
243
- settings: core_1.Flags.boolean({
244
- allowNo: true,
245
- default: undefined,
246
- description: 'Load settings (project settings, translations, presets)',
247
- }),
248
- templateLocation: customFlags.templateLocation,
249
- templateType: core_1.Flags.string({
250
- default: 'local',
251
- dependsOn: ['programmatic'],
252
- description: 'Type of template to apply. You can apply templates from our community repo, local directories, or public repositories from Github. Defaults to local. ',
253
- env: 'TEMPLATE_TYPE',
254
- options: ['community', 'local', 'github'],
255
- summary: 'Type of template to apply. Options: community, local, github.',
256
- }),
257
- userEmail: customFlags.userEmail,
258
- userPassword: customFlags.userPassword,
259
- users: core_1.Flags.boolean({
260
- allowNo: true,
261
- default: undefined,
262
- description: 'Load users',
263
- }),
264
- };
265
- exports.default = ApplyCommand;
@@ -0,0 +1,15 @@
1
+ import { Command, type Config } from '@oclif/core';
2
+ interface UserConfig {
3
+ distinctId?: string | null;
4
+ }
5
+ export declare abstract class BaseCommand extends Command {
6
+ runId: string;
7
+ userConfig: UserConfig;
8
+ constructor(argv: string[], config: Config);
9
+ private loadUserConfig;
10
+ /**
11
+ * Save the current user configuration to disk
12
+ */
13
+ protected saveUserConfig(): void;
14
+ }
15
+ export {};
@@ -0,0 +1,45 @@
1
+ import { Command } from '@oclif/core';
2
+ import { randomUUID } from 'node:crypto';
3
+ import fs from 'node:fs';
4
+ import path from 'pathe';
5
+ export class BaseCommand extends Command {
6
+ runId;
7
+ userConfig = {};
8
+ constructor(argv, config) {
9
+ super(argv, config);
10
+ this.runId = randomUUID();
11
+ this.loadUserConfig();
12
+ }
13
+ loadUserConfig() {
14
+ try {
15
+ const configPath = path.join(this.config.configDir, 'config.json');
16
+ if (fs.existsSync(configPath)) {
17
+ this.userConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
18
+ }
19
+ else {
20
+ // Create default config if it doesn't exist
21
+ const defaultConfig = {
22
+ distinctId: randomUUID(),
23
+ };
24
+ fs.mkdirSync(this.config.configDir, { recursive: true });
25
+ fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
26
+ this.userConfig = defaultConfig;
27
+ }
28
+ }
29
+ catch (error) {
30
+ this.warn(`Failed to load user config: ${error}`);
31
+ }
32
+ }
33
+ /**
34
+ * Save the current user configuration to disk
35
+ */
36
+ saveUserConfig() {
37
+ try {
38
+ const configPath = path.join(this.config.configDir, 'config.json');
39
+ fs.writeFileSync(configPath, JSON.stringify(this.userConfig, null, 2));
40
+ }
41
+ catch (error) {
42
+ this.warn(`Failed to save user config: ${error}`);
43
+ }
44
+ }
45
+ }
@@ -1,17 +1,24 @@
1
1
  import { Command } from '@oclif/core';
2
+ export interface ExtractFlags {
3
+ directusToken: string;
4
+ directusUrl: string;
5
+ programmatic: boolean;
6
+ templateLocation: string;
7
+ templateName: string;
8
+ userEmail: string;
9
+ userPassword: string;
10
+ }
2
11
  export default class ExtractCommand extends Command {
3
12
  static description: string;
4
13
  static examples: string[];
5
14
  static flags: {
6
- directusToken: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
7
- directusUrl: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
8
- excludeCollections: import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
9
- programmatic: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
- skipFiles: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
- templateLocation: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
12
- templateName: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
13
- userEmail: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
14
- userPassword: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
15
+ directusToken: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
16
+ directusUrl: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
17
+ programmatic: import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
+ templateLocation: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
19
+ templateName: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
20
+ userEmail: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
21
+ userPassword: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
22
  };
16
23
  /**
17
24
  * Main run method for the ExtractCommand