directus-template-cli 0.5.1 → 0.6.0-beta.2
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/README.md +14 -0
- package/dist/commands/extract.d.ts +2 -0
- package/dist/commands/extract.js +29 -2
- package/dist/lib/extract/extract-content.d.ts +1 -1
- package/dist/lib/extract/extract-content.js +9 -5
- package/dist/lib/extract/index.d.ts +6 -1
- package/dist/lib/extract/index.js +12 -5
- package/oclif.manifest.json +21 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -181,6 +181,18 @@ 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
|
+
|
|
184
196
|
Available flags for programmatic mode:
|
|
185
197
|
|
|
186
198
|
- `--directusUrl`: URL of the Directus instance to extract the template from (required)
|
|
@@ -189,6 +201,8 @@ Available flags for programmatic mode:
|
|
|
189
201
|
- `--userPassword`: Password for Directus authentication (required if not using token)
|
|
190
202
|
- `--templateLocation`: Directory to extract the template to (required)
|
|
191
203
|
- `--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
|
|
192
206
|
|
|
193
207
|
#### Using Environment Variables
|
|
194
208
|
|
|
@@ -5,7 +5,9 @@ export default class ExtractCommand extends Command {
|
|
|
5
5
|
static flags: {
|
|
6
6
|
directusToken: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
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>;
|
|
8
9
|
programmatic: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
skipFiles: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
11
|
templateLocation: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
12
|
templateName: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
13
|
userEmail: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
package/dist/commands/extract.js
CHANGED
|
@@ -30,6 +30,7 @@ class ExtractCommand extends core_1.Command {
|
|
|
30
30
|
* @returns {Promise<void>} - Returns nothing
|
|
31
31
|
*/
|
|
32
32
|
async extractTemplate(templateName, directory, flags) {
|
|
33
|
+
var _a;
|
|
33
34
|
try {
|
|
34
35
|
if (!node_fs_1.default.existsSync(directory)) {
|
|
35
36
|
node_fs_1.default.mkdirSync(directory, { recursive: true });
|
|
@@ -49,8 +50,14 @@ class ExtractCommand extends core_1.Command {
|
|
|
49
50
|
});
|
|
50
51
|
}
|
|
51
52
|
core_1.ux.log(constants_1.SEPARATOR);
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
const exclusionMessage = ((_a = flags.excludeCollections) === null || _a === void 0 ? void 0 : _a.length)
|
|
54
|
+
? ` (excluding ${flags.excludeCollections.join(', ')})`
|
|
55
|
+
: '';
|
|
56
|
+
core_1.ux.action.start(`Extracting template - ${core_1.ux.colorize(constants_1.DIRECTUS_PINK, templateName)}${exclusionMessage} from ${core_1.ux.colorize(constants_1.DIRECTUS_PINK, flags.directusUrl)} to ${core_1.ux.colorize(constants_1.DIRECTUS_PINK, directory)}`);
|
|
57
|
+
await (0, extract_1.default)(directory, {
|
|
58
|
+
excludeCollections: flags.excludeCollections,
|
|
59
|
+
skipFiles: flags.skipFiles,
|
|
60
|
+
});
|
|
54
61
|
core_1.ux.action.stop();
|
|
55
62
|
core_1.ux.log(constants_1.SEPARATOR);
|
|
56
63
|
core_1.ux.log('Template extracted successfully.');
|
|
@@ -66,6 +73,12 @@ class ExtractCommand extends core_1.Command {
|
|
|
66
73
|
const templateName = await core_1.ux.prompt('What is the name of the template you would like to extract?');
|
|
67
74
|
const directory = await core_1.ux.prompt("What directory would you like to extract the template to? If it doesn't exist, it will be created.", { default: `templates/${(0, slugify_1.default)(templateName, { lower: true, strict: true })}` });
|
|
68
75
|
core_1.ux.log(`You selected ${core_1.ux.colorize(constants_1.DIRECTUS_PINK, directory)}`);
|
|
76
|
+
const excludeCollectionsInput = await core_1.ux.prompt('Enter collection names to exclude (comma-separated) or press enter to skip', { required: false });
|
|
77
|
+
if (excludeCollectionsInput) {
|
|
78
|
+
flags.excludeCollections = excludeCollectionsInput.split(',').map(name => name.trim());
|
|
79
|
+
}
|
|
80
|
+
const skipFiles = await core_1.ux.confirm('Skip extracting files and assets? (y/N)');
|
|
81
|
+
flags.skipFiles = skipFiles;
|
|
69
82
|
core_1.ux.log(constants_1.SEPARATOR);
|
|
70
83
|
// Get Directus URL
|
|
71
84
|
const directusUrl = await (0, auth_1.getDirectusUrl)();
|
|
@@ -126,11 +139,25 @@ ExtractCommand.description = 'Extract a template from a Directus instance.';
|
|
|
126
139
|
ExtractCommand.examples = [
|
|
127
140
|
'$ directus-template-cli extract',
|
|
128
141
|
'$ directus-template-cli extract -p --templateName="My Template" --templateLocation="./my-template" --directusToken="admin-token-here" --directusUrl="http://localhost:8055"',
|
|
142
|
+
'$ directus-template-cli extract -p --templateName="My Template" --templateLocation="./my-template" --directusToken="admin-token-here" --directusUrl="http://localhost:8055" --excludeCollections=collection1,collection2',
|
|
129
143
|
];
|
|
130
144
|
ExtractCommand.flags = {
|
|
131
145
|
directusToken: customFlags.directusToken,
|
|
132
146
|
directusUrl: customFlags.directusUrl,
|
|
147
|
+
excludeCollections: core_1.Flags.string({
|
|
148
|
+
char: 'e',
|
|
149
|
+
delimiter: ',', // Will split on commas and return an array
|
|
150
|
+
description: 'Comma-separated list of collection names to exclude from extraction',
|
|
151
|
+
multiple: true,
|
|
152
|
+
required: false,
|
|
153
|
+
}),
|
|
133
154
|
programmatic: customFlags.programmatic,
|
|
155
|
+
skipFiles: core_1.Flags.boolean({
|
|
156
|
+
char: 'f',
|
|
157
|
+
default: false,
|
|
158
|
+
description: 'Skip extracting files and assets',
|
|
159
|
+
required: false,
|
|
160
|
+
}),
|
|
134
161
|
templateLocation: customFlags.templateLocation,
|
|
135
162
|
templateName: customFlags.templateName,
|
|
136
163
|
userEmail: customFlags.userEmail,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function extractContent(dir: string): Promise<void>;
|
|
1
|
+
export declare function extractContent(dir: string, excludeCollections?: string[]): Promise<void>;
|
|
@@ -8,11 +8,12 @@ const constants_1 = require("../constants");
|
|
|
8
8
|
const sdk_2 = require("../sdk");
|
|
9
9
|
const catch_error_1 = tslib_1.__importDefault(require("../utils/catch-error"));
|
|
10
10
|
const write_to_file_1 = tslib_1.__importDefault(require("../utils/write-to-file"));
|
|
11
|
-
async function getCollections() {
|
|
11
|
+
async function getCollections(excludeCollections) {
|
|
12
12
|
const response = await sdk_2.api.client.request((0, sdk_1.readCollections)());
|
|
13
13
|
return response
|
|
14
14
|
.filter(item => !item.collection.startsWith('directus_', 0))
|
|
15
|
-
.filter(item => item.schema
|
|
15
|
+
.filter(item => item.schema !== null)
|
|
16
|
+
.filter(item => !(excludeCollections === null || excludeCollections === void 0 ? void 0 : excludeCollections.includes(item.collection)))
|
|
16
17
|
.map(i => i.collection);
|
|
17
18
|
}
|
|
18
19
|
async function getDataFromCollection(collection, dir) {
|
|
@@ -24,10 +25,13 @@ async function getDataFromCollection(collection, dir) {
|
|
|
24
25
|
(0, catch_error_1.default)(error);
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
|
-
async function extractContent(dir) {
|
|
28
|
-
|
|
28
|
+
async function extractContent(dir, excludeCollections) {
|
|
29
|
+
const exclusionMessage = (excludeCollections === null || excludeCollections === void 0 ? void 0 : excludeCollections.length)
|
|
30
|
+
? ` (excluding ${excludeCollections.join(', ')})`
|
|
31
|
+
: '';
|
|
32
|
+
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Extracting content${exclusionMessage}`));
|
|
29
33
|
try {
|
|
30
|
-
const collections = await getCollections();
|
|
34
|
+
const collections = await getCollections(excludeCollections);
|
|
31
35
|
await Promise.all(collections.map(collection => getDataFromCollection(collection, dir)));
|
|
32
36
|
}
|
|
33
37
|
catch (error) {
|
|
@@ -22,7 +22,8 @@ const extract_schema_1 = tslib_1.__importDefault(require("./extract-schema"));
|
|
|
22
22
|
const extract_settings_1 = tslib_1.__importDefault(require("./extract-settings"));
|
|
23
23
|
const extract_translations_1 = tslib_1.__importDefault(require("./extract-translations"));
|
|
24
24
|
const extract_users_1 = tslib_1.__importDefault(require("./extract-users"));
|
|
25
|
-
async function extract(dir) {
|
|
25
|
+
async function extract(dir, options = {}) {
|
|
26
|
+
const { excludeCollections, skipFiles = false } = options;
|
|
26
27
|
// Get the destination directory for the actual files
|
|
27
28
|
const destination = dir + '/src';
|
|
28
29
|
// Check if directory exists, if not, then create it.
|
|
@@ -34,8 +35,11 @@ async function extract(dir) {
|
|
|
34
35
|
await (0, extract_collections_1.default)(destination);
|
|
35
36
|
await (0, extract_fields_1.default)(destination);
|
|
36
37
|
await (0, extract_relations_1.default)(destination);
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
// Only extract files and folders if skipFiles is false
|
|
39
|
+
if (!skipFiles) {
|
|
40
|
+
await (0, extract_folders_1.default)(destination);
|
|
41
|
+
await (0, extract_files_1.default)(destination);
|
|
42
|
+
}
|
|
39
43
|
await (0, extract_users_1.default)(destination);
|
|
40
44
|
await (0, extract_roles_1.default)(destination);
|
|
41
45
|
await (0, extract_permissions_1.default)(destination);
|
|
@@ -49,8 +53,11 @@ async function extract(dir) {
|
|
|
49
53
|
await (0, extract_dashboards_1.extractPanels)(destination);
|
|
50
54
|
await (0, extract_settings_1.default)(destination);
|
|
51
55
|
await (0, extract_extensions_1.default)(destination);
|
|
52
|
-
await (0, extract_content_1.extractContent)(destination);
|
|
53
|
-
|
|
56
|
+
await (0, extract_content_1.extractContent)(destination, excludeCollections);
|
|
57
|
+
// Only download files if skipFiles is false
|
|
58
|
+
if (!skipFiles) {
|
|
59
|
+
await (0, extract_assets_1.downloadAllFiles)(destination);
|
|
60
|
+
}
|
|
54
61
|
return {};
|
|
55
62
|
}
|
|
56
63
|
exports.default = extract;
|
package/oclif.manifest.json
CHANGED
|
@@ -182,7 +182,8 @@
|
|
|
182
182
|
"description": "Extract a template from a Directus instance.",
|
|
183
183
|
"examples": [
|
|
184
184
|
"$ directus-template-cli extract",
|
|
185
|
-
"$ directus-template-cli extract -p --templateName=\"My Template\" --templateLocation=\"./my-template\" --directusToken=\"admin-token-here\" --directusUrl=\"http://localhost:8055\""
|
|
185
|
+
"$ directus-template-cli extract -p --templateName=\"My Template\" --templateLocation=\"./my-template\" --directusToken=\"admin-token-here\" --directusUrl=\"http://localhost:8055\"",
|
|
186
|
+
"$ directus-template-cli extract -p --templateName=\"My Template\" --templateLocation=\"./my-template\" --directusToken=\"admin-token-here\" --directusUrl=\"http://localhost:8055\" --excludeCollections=collection1,collection2"
|
|
186
187
|
],
|
|
187
188
|
"flags": {
|
|
188
189
|
"directusToken": {
|
|
@@ -205,6 +206,16 @@
|
|
|
205
206
|
"multiple": false,
|
|
206
207
|
"type": "option"
|
|
207
208
|
},
|
|
209
|
+
"excludeCollections": {
|
|
210
|
+
"char": "e",
|
|
211
|
+
"description": "Comma-separated list of collection names to exclude from extraction",
|
|
212
|
+
"name": "excludeCollections",
|
|
213
|
+
"required": false,
|
|
214
|
+
"delimiter": ",",
|
|
215
|
+
"hasDynamicHelp": false,
|
|
216
|
+
"multiple": true,
|
|
217
|
+
"type": "option"
|
|
218
|
+
},
|
|
208
219
|
"programmatic": {
|
|
209
220
|
"char": "p",
|
|
210
221
|
"description": "Run in programmatic mode (non-interactive) for use cases such as CI/CD pipelines.",
|
|
@@ -213,6 +224,14 @@
|
|
|
213
224
|
"allowNo": false,
|
|
214
225
|
"type": "boolean"
|
|
215
226
|
},
|
|
227
|
+
"skipFiles": {
|
|
228
|
+
"char": "f",
|
|
229
|
+
"description": "Skip extracting files and assets",
|
|
230
|
+
"name": "skipFiles",
|
|
231
|
+
"required": false,
|
|
232
|
+
"allowNo": false,
|
|
233
|
+
"type": "boolean"
|
|
234
|
+
},
|
|
216
235
|
"templateLocation": {
|
|
217
236
|
"dependsOn": [
|
|
218
237
|
"programmatic"
|
|
@@ -280,5 +299,5 @@
|
|
|
280
299
|
]
|
|
281
300
|
}
|
|
282
301
|
},
|
|
283
|
-
"version": "0.
|
|
302
|
+
"version": "0.6.0-beta.2"
|
|
284
303
|
}
|