directus-template-cli 0.1.0

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 (55) hide show
  1. package/README.md +314 -0
  2. package/bin/dev +17 -0
  3. package/bin/dev.cmd +3 -0
  4. package/bin/run +5 -0
  5. package/bin/run.cmd +3 -0
  6. package/dist/commands/apply.d.ts +7 -0
  7. package/dist/commands/apply.js +84 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +5 -0
  10. package/dist/lib/api.d.ts +14 -0
  11. package/dist/lib/api.js +32 -0
  12. package/dist/lib/interfaces.d.ts +8 -0
  13. package/dist/lib/interfaces.js +2 -0
  14. package/dist/lib/load/index.d.ts +1 -0
  15. package/dist/lib/load/index.js +49 -0
  16. package/dist/lib/load/load-dashboards.d.ts +1 -0
  17. package/dist/lib/load/load-dashboards.js +13 -0
  18. package/dist/lib/load/load-data.d.ts +1 -0
  19. package/dist/lib/load/load-data.js +84 -0
  20. package/dist/lib/load/load-files.d.ts +2 -0
  21. package/dist/lib/load/load-files.js +42 -0
  22. package/dist/lib/load/load-flows.d.ts +2 -0
  23. package/dist/lib/load/load-flows.js +18 -0
  24. package/dist/lib/load/load-folders.d.ts +1 -0
  25. package/dist/lib/load/load-folders.js +16 -0
  26. package/dist/lib/load/load-operations.d.ts +1 -0
  27. package/dist/lib/load/load-operations.js +29 -0
  28. package/dist/lib/load/load-panels.d.ts +0 -0
  29. package/dist/lib/load/load-panels.js +0 -0
  30. package/dist/lib/load/load-presets.d.ts +2 -0
  31. package/dist/lib/load/load-presets.js +17 -0
  32. package/dist/lib/load/load-public-permissions.d.ts +1 -0
  33. package/dist/lib/load/load-public-permissions.js +19 -0
  34. package/dist/lib/load/load-roles.d.ts +1 -0
  35. package/dist/lib/load/load-roles.js +21 -0
  36. package/dist/lib/load/load-schema.d.ts +2 -0
  37. package/dist/lib/load/load-schema.js +20 -0
  38. package/dist/lib/load/load-settings.d.ts +1 -0
  39. package/dist/lib/load/load-settings.js +12 -0
  40. package/dist/lib/load/load-users.d.ts +2 -0
  41. package/dist/lib/load/load-users.js +31 -0
  42. package/dist/lib/utils/delete-items.d.ts +1 -0
  43. package/dist/lib/utils/delete-items.js +15 -0
  44. package/dist/lib/utils/load-to-destination.d.ts +1 -0
  45. package/dist/lib/utils/load-to-destination.js +14 -0
  46. package/dist/lib/utils/read-file.d.ts +2 -0
  47. package/dist/lib/utils/read-file.js +17 -0
  48. package/dist/lib/utils/read-templates.d.ts +6 -0
  49. package/dist/lib/utils/read-templates.js +36 -0
  50. package/dist/lib/utils/validate-url.d.ts +1 -0
  51. package/dist/lib/utils/validate-url.js +12 -0
  52. package/dist/lib/utils/write-to-file.d.ts +2 -0
  53. package/dist/lib/utils/write-to-file.js +22 -0
  54. package/oclif.manifest.json +19 -0
  55. package/package.json +78 -0
package/README.md ADDED
@@ -0,0 +1,314 @@
1
+ ⚠️ WARNING: DO NOT USE ⚠️
2
+ Very Very Alpha State
3
+ =================
4
+
5
+ oclif example Hello World CLI
6
+
7
+ [![oclif](https://img.shields.io/badge/cli-oclif-brightgreen.svg)](https://oclif.io)
8
+ [![Version](https://img.shields.io/npm/v/oclif-hello-world.svg)](https://npmjs.org/package/oclif-hello-world)
9
+ [![CircleCI](https://circleci.com/gh/oclif/hello-world/tree/main.svg?style=shield)](https://circleci.com/gh/oclif/hello-world/tree/main)
10
+ [![Downloads/week](https://img.shields.io/npm/dw/oclif-hello-world.svg)](https://npmjs.org/package/oclif-hello-world)
11
+ [![License](https://img.shields.io/npm/l/oclif-hello-world.svg)](https://github.com/oclif/hello-world/blob/main/package.json)
12
+
13
+ <!-- toc -->
14
+ * [Usage](#usage)
15
+ * [Commands](#commands)
16
+ <!-- tocstop -->
17
+ # Usage
18
+ <!-- usage -->
19
+ ```sh-session
20
+ $ npm install -g directus-template-cli
21
+ $ directus-template-cli COMMAND
22
+ running command...
23
+ $ directus-template-cli (--version)
24
+ directus-template-cli/0.1.0 darwin-x64 node-v18.12.1
25
+ $ directus-template-cli --help [COMMAND]
26
+ USAGE
27
+ $ directus-template-cli COMMAND
28
+ ...
29
+ ```
30
+ <!-- usagestop -->
31
+ # Commands
32
+ <!-- commands -->
33
+ * [`directus-template-cli apply`](#directus-template-cli-apply)
34
+ * [`directus-template-cli help [COMMANDS]`](#directus-template-cli-help-commands)
35
+ * [`directus-template-cli plugins`](#directus-template-cli-plugins)
36
+ * [`directus-template-cli plugins:install PLUGIN...`](#directus-template-cli-pluginsinstall-plugin)
37
+ * [`directus-template-cli plugins:inspect PLUGIN...`](#directus-template-cli-pluginsinspect-plugin)
38
+ * [`directus-template-cli plugins:install PLUGIN...`](#directus-template-cli-pluginsinstall-plugin-1)
39
+ * [`directus-template-cli plugins:link PLUGIN`](#directus-template-cli-pluginslink-plugin)
40
+ * [`directus-template-cli plugins:uninstall PLUGIN...`](#directus-template-cli-pluginsuninstall-plugin)
41
+ * [`directus-template-cli plugins:uninstall PLUGIN...`](#directus-template-cli-pluginsuninstall-plugin-1)
42
+ * [`directus-template-cli plugins:uninstall PLUGIN...`](#directus-template-cli-pluginsuninstall-plugin-2)
43
+ * [`directus-template-cli plugins update`](#directus-template-cli-plugins-update)
44
+
45
+ ## `directus-template-cli apply`
46
+
47
+ Apply a template to a blank Directus instance.
48
+
49
+ ```
50
+ USAGE
51
+ $ directus-template-cli apply
52
+
53
+ DESCRIPTION
54
+ Apply a template to a blank Directus instance.
55
+
56
+ EXAMPLES
57
+ $ directus-template-cli apply
58
+ ```
59
+
60
+ _See code: [dist/commands/apply.ts](https://github.com/bryantgillespie/directus-template-cli/blob/v0.1.0/dist/commands/apply.ts)_
61
+
62
+ ## `directus-template-cli help [COMMANDS]`
63
+
64
+ Display help for directus-template-cli.
65
+
66
+ ```
67
+ USAGE
68
+ $ directus-template-cli help [COMMANDS] [-n]
69
+
70
+ ARGUMENTS
71
+ COMMANDS Command to show help for.
72
+
73
+ FLAGS
74
+ -n, --nested-commands Include all nested commands in the output.
75
+
76
+ DESCRIPTION
77
+ Display help for directus-template-cli.
78
+ ```
79
+
80
+ _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v5.2.9/src/commands/help.ts)_
81
+
82
+ ## `directus-template-cli plugins`
83
+
84
+ List installed plugins.
85
+
86
+ ```
87
+ USAGE
88
+ $ directus-template-cli plugins [--core]
89
+
90
+ FLAGS
91
+ --core Show core plugins.
92
+
93
+ DESCRIPTION
94
+ List installed plugins.
95
+
96
+ EXAMPLES
97
+ $ directus-template-cli plugins
98
+ ```
99
+
100
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v2.4.7/src/commands/plugins/index.ts)_
101
+
102
+ ## `directus-template-cli plugins:install PLUGIN...`
103
+
104
+ Installs a plugin into the CLI.
105
+
106
+ ```
107
+ USAGE
108
+ $ directus-template-cli plugins:install PLUGIN...
109
+
110
+ ARGUMENTS
111
+ PLUGIN Plugin to install.
112
+
113
+ FLAGS
114
+ -f, --force Run yarn install with force flag.
115
+ -h, --help Show CLI help.
116
+ -v, --verbose
117
+
118
+ DESCRIPTION
119
+ Installs a plugin into the CLI.
120
+ Can be installed from npm or a git url.
121
+
122
+ Installation of a user-installed plugin will override a core plugin.
123
+
124
+ e.g. If you have a core plugin that has a 'hello' command, installing a user-installed plugin with a 'hello' command
125
+ will override the core plugin implementation. This is useful if a user needs to update core plugin functionality in
126
+ the CLI without the need to patch and update the whole CLI.
127
+
128
+
129
+ ALIASES
130
+ $ directus-template-cli plugins add
131
+
132
+ EXAMPLES
133
+ $ directus-template-cli plugins:install myplugin
134
+
135
+ $ directus-template-cli plugins:install https://github.com/someuser/someplugin
136
+
137
+ $ directus-template-cli plugins:install someuser/someplugin
138
+ ```
139
+
140
+ ## `directus-template-cli plugins:inspect PLUGIN...`
141
+
142
+ Displays installation properties of a plugin.
143
+
144
+ ```
145
+ USAGE
146
+ $ directus-template-cli plugins:inspect PLUGIN...
147
+
148
+ ARGUMENTS
149
+ PLUGIN [default: .] Plugin to inspect.
150
+
151
+ FLAGS
152
+ -h, --help Show CLI help.
153
+ -v, --verbose
154
+
155
+ GLOBAL FLAGS
156
+ --json Format output as json.
157
+
158
+ DESCRIPTION
159
+ Displays installation properties of a plugin.
160
+
161
+ EXAMPLES
162
+ $ directus-template-cli plugins:inspect myplugin
163
+ ```
164
+
165
+ ## `directus-template-cli plugins:install PLUGIN...`
166
+
167
+ Installs a plugin into the CLI.
168
+
169
+ ```
170
+ USAGE
171
+ $ directus-template-cli plugins:install PLUGIN...
172
+
173
+ ARGUMENTS
174
+ PLUGIN Plugin to install.
175
+
176
+ FLAGS
177
+ -f, --force Run yarn install with force flag.
178
+ -h, --help Show CLI help.
179
+ -v, --verbose
180
+
181
+ DESCRIPTION
182
+ Installs a plugin into the CLI.
183
+ Can be installed from npm or a git url.
184
+
185
+ Installation of a user-installed plugin will override a core plugin.
186
+
187
+ e.g. If you have a core plugin that has a 'hello' command, installing a user-installed plugin with a 'hello' command
188
+ will override the core plugin implementation. This is useful if a user needs to update core plugin functionality in
189
+ the CLI without the need to patch and update the whole CLI.
190
+
191
+
192
+ ALIASES
193
+ $ directus-template-cli plugins add
194
+
195
+ EXAMPLES
196
+ $ directus-template-cli plugins:install myplugin
197
+
198
+ $ directus-template-cli plugins:install https://github.com/someuser/someplugin
199
+
200
+ $ directus-template-cli plugins:install someuser/someplugin
201
+ ```
202
+
203
+ ## `directus-template-cli plugins:link PLUGIN`
204
+
205
+ Links a plugin into the CLI for development.
206
+
207
+ ```
208
+ USAGE
209
+ $ directus-template-cli plugins:link PLUGIN
210
+
211
+ ARGUMENTS
212
+ PATH [default: .] path to plugin
213
+
214
+ FLAGS
215
+ -h, --help Show CLI help.
216
+ -v, --verbose
217
+
218
+ DESCRIPTION
219
+ Links a plugin into the CLI for development.
220
+ Installation of a linked plugin will override a user-installed or core plugin.
221
+
222
+ e.g. If you have a user-installed or core plugin that has a 'hello' command, installing a linked plugin with a 'hello'
223
+ command will override the user-installed or core plugin implementation. This is useful for development work.
224
+
225
+
226
+ EXAMPLES
227
+ $ directus-template-cli plugins:link myplugin
228
+ ```
229
+
230
+ ## `directus-template-cli plugins:uninstall PLUGIN...`
231
+
232
+ Removes a plugin from the CLI.
233
+
234
+ ```
235
+ USAGE
236
+ $ directus-template-cli plugins:uninstall PLUGIN...
237
+
238
+ ARGUMENTS
239
+ PLUGIN plugin to uninstall
240
+
241
+ FLAGS
242
+ -h, --help Show CLI help.
243
+ -v, --verbose
244
+
245
+ DESCRIPTION
246
+ Removes a plugin from the CLI.
247
+
248
+ ALIASES
249
+ $ directus-template-cli plugins unlink
250
+ $ directus-template-cli plugins remove
251
+ ```
252
+
253
+ ## `directus-template-cli plugins:uninstall PLUGIN...`
254
+
255
+ Removes a plugin from the CLI.
256
+
257
+ ```
258
+ USAGE
259
+ $ directus-template-cli plugins:uninstall PLUGIN...
260
+
261
+ ARGUMENTS
262
+ PLUGIN plugin to uninstall
263
+
264
+ FLAGS
265
+ -h, --help Show CLI help.
266
+ -v, --verbose
267
+
268
+ DESCRIPTION
269
+ Removes a plugin from the CLI.
270
+
271
+ ALIASES
272
+ $ directus-template-cli plugins unlink
273
+ $ directus-template-cli plugins remove
274
+ ```
275
+
276
+ ## `directus-template-cli plugins:uninstall PLUGIN...`
277
+
278
+ Removes a plugin from the CLI.
279
+
280
+ ```
281
+ USAGE
282
+ $ directus-template-cli plugins:uninstall PLUGIN...
283
+
284
+ ARGUMENTS
285
+ PLUGIN plugin to uninstall
286
+
287
+ FLAGS
288
+ -h, --help Show CLI help.
289
+ -v, --verbose
290
+
291
+ DESCRIPTION
292
+ Removes a plugin from the CLI.
293
+
294
+ ALIASES
295
+ $ directus-template-cli plugins unlink
296
+ $ directus-template-cli plugins remove
297
+ ```
298
+
299
+ ## `directus-template-cli plugins update`
300
+
301
+ Update installed plugins.
302
+
303
+ ```
304
+ USAGE
305
+ $ directus-template-cli plugins update [-h] [-v]
306
+
307
+ FLAGS
308
+ -h, --help Show CLI help.
309
+ -v, --verbose
310
+
311
+ DESCRIPTION
312
+ Update installed plugins.
313
+ ```
314
+ <!-- commandsstop -->
package/bin/dev ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ const oclif = require('@oclif/core')
4
+
5
+ const path = require('path')
6
+ const project = path.join(__dirname, '..', 'tsconfig.json')
7
+
8
+ // In dev mode -> use ts-node and dev plugins
9
+ process.env.NODE_ENV = 'development'
10
+
11
+ require('ts-node').register({project})
12
+
13
+ // In dev mode, always show stack traces
14
+ oclif.settings.debug = true;
15
+
16
+ // Start the CLI
17
+ oclif.run().then(oclif.flush).catch(oclif.Errors.handle)
package/bin/dev.cmd ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+
3
+ node "%~dp0\dev" %*
package/bin/run ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ const oclif = require('@oclif/core')
4
+
5
+ oclif.run().then(require('@oclif/core/flush')).catch(require('@oclif/core/handle'))
package/bin/run.cmd ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+
3
+ node "%~dp0\run" %*
@@ -0,0 +1,7 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class ApplyCommand extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {};
6
+ run(): Promise<void>;
7
+ }
@@ -0,0 +1,84 @@
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 core_2 = require("@oclif/core");
6
+ const inquirer = tslib_1.__importStar(require("inquirer"));
7
+ const read_templates_1 = tslib_1.__importDefault(require("../lib/utils/read-templates"));
8
+ const validate_url_1 = tslib_1.__importDefault(require("../lib/utils/validate-url"));
9
+ const api_1 = require("../lib/api");
10
+ const load_1 = tslib_1.__importDefault(require("../lib/load/"));
11
+ const separator = '------------------';
12
+ async function getTemplate() {
13
+ const templates = await (0, read_templates_1.default)('./src/templates/');
14
+ const templateChoices = templates.map((template) => {
15
+ return { name: template.templateName, value: template };
16
+ });
17
+ const template = await inquirer.prompt([{
18
+ name: 'template',
19
+ message: 'Select a template.',
20
+ type: 'list',
21
+ choices: templateChoices,
22
+ }]);
23
+ return template;
24
+ }
25
+ async function getDirectusUrl() {
26
+ const directusUrl = await core_2.ux.prompt('What is your Directus URL?');
27
+ // Validate URL
28
+ if (!(0, validate_url_1.default)(directusUrl)) {
29
+ core_2.ux.warn('Invalid URL');
30
+ return getDirectusUrl();
31
+ }
32
+ return directusUrl;
33
+ }
34
+ async function getDirectusToken(directusUrl) {
35
+ const directusToken = await core_2.ux.prompt('What is your Directus Admin Token?');
36
+ // Validate token
37
+ try {
38
+ await api_1.api.get('/users/me', {
39
+ headers: {
40
+ Authorization: `Bearer ${directusToken}`,
41
+ },
42
+ });
43
+ return directusToken;
44
+ }
45
+ catch {
46
+ core_2.ux.warn('Invalid token');
47
+ return getDirectusToken(directusUrl);
48
+ }
49
+ }
50
+ class ApplyCommand extends core_1.Command {
51
+ async run() {
52
+ const { flags } = await this.parse(ApplyCommand);
53
+ const chosenTemplate = await getTemplate();
54
+ this.log(`You selected ${chosenTemplate.template.templateName}`);
55
+ this.log(separator);
56
+ const directusUrl = await getDirectusUrl();
57
+ api_1.api.setBaseUrl(directusUrl);
58
+ const directusToken = await getDirectusToken(directusUrl);
59
+ api_1.api.setAuthToken(directusToken);
60
+ this.log(separator);
61
+ // Check if Directus instance is empty, if not, throw error
62
+ const { data } = await api_1.api.get('/collections');
63
+ // Look for collections that don't start with directus_
64
+ const collections = data.data.filter((collection) => {
65
+ return !collection.collection.startsWith('directus_');
66
+ });
67
+ if (collections.length > 0) {
68
+ core_2.ux.error('Directus instance is not empty. Please use a blank instance. Copying a template into an existing instance is not supported at this time.');
69
+ }
70
+ // Run load script
71
+ core_2.ux.action.start(`Applying template - ${chosenTemplate.template.templateName}`);
72
+ await (0, load_1.default)(chosenTemplate.template.directoryPath, this);
73
+ core_2.ux.action.stop();
74
+ this.log(separator);
75
+ this.log('Template applied successfully.');
76
+ this.exit;
77
+ }
78
+ }
79
+ exports.default = ApplyCommand;
80
+ ApplyCommand.description = 'Apply a template to a blank Directus instance.';
81
+ ApplyCommand.examples = [
82
+ '$ directus-template-cli apply',
83
+ ];
84
+ ApplyCommand.flags = {};
@@ -0,0 +1 @@
1
+ export { run } from '@oclif/core';
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.run = void 0;
4
+ var core_1 = require("@oclif/core");
5
+ Object.defineProperty(exports, "run", { enumerable: true, get: function () { return core_1.run; } });
@@ -0,0 +1,14 @@
1
+ import { AxiosRequestConfig, AxiosResponse } from 'axios';
2
+ declare class Api {
3
+ private instance;
4
+ constructor();
5
+ setBaseUrl(url: string): void;
6
+ setAuthToken(token: string): void;
7
+ get<T>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
8
+ post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
9
+ put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
10
+ patch<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>;
11
+ delete(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse>;
12
+ }
13
+ export declare const api: Api;
14
+ export {};
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.api = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const axios_1 = tslib_1.__importDefault(require("axios"));
6
+ class Api {
7
+ constructor() {
8
+ this.instance = axios_1.default.create();
9
+ }
10
+ setBaseUrl(url) {
11
+ this.instance.defaults.baseURL = url;
12
+ }
13
+ setAuthToken(token) {
14
+ this.instance.defaults.headers.common.Authorization = `Bearer ${token}`;
15
+ }
16
+ get(url, config) {
17
+ return this.instance.get(url, config);
18
+ }
19
+ post(url, data, config) {
20
+ return this.instance.post(url, data, config);
21
+ }
22
+ put(url, data, config) {
23
+ return this.instance.put(url, data, config);
24
+ }
25
+ patch(url, data, config) {
26
+ return this.instance.patch(url, data, config);
27
+ }
28
+ delete(url, config) {
29
+ return this.instance.delete(url, config);
30
+ }
31
+ }
32
+ exports.api = new Api();
@@ -0,0 +1,8 @@
1
+ export interface Diff {
2
+ hash: string;
3
+ diff: {
4
+ collections: any[];
5
+ fields: any[];
6
+ relations: any[];
7
+ };
8
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export default function apply(dir: string, cli: any): Promise<{}>;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
5
+ const load_to_destination_1 = tslib_1.__importDefault(require("../utils/load-to-destination"));
6
+ const load_schema_1 = tslib_1.__importDefault(require("./load-schema"));
7
+ const load_roles_1 = tslib_1.__importDefault(require("./load-roles"));
8
+ const load_dashboards_1 = tslib_1.__importDefault(require("./load-dashboards"));
9
+ const load_files_1 = tslib_1.__importDefault(require("./load-files"));
10
+ const load_users_1 = tslib_1.__importDefault(require("./load-users"));
11
+ const load_flows_1 = tslib_1.__importDefault(require("./load-flows"));
12
+ const load_operations_1 = tslib_1.__importDefault(require("./load-operations"));
13
+ const load_data_1 = tslib_1.__importDefault(require("./load-data"));
14
+ const load_presets_1 = tslib_1.__importDefault(require("./load-presets"));
15
+ const load_settings_1 = tslib_1.__importDefault(require("./load-settings"));
16
+ const load_public_permissions_1 = tslib_1.__importDefault(require("./load-public-permissions"));
17
+ async function apply(dir, cli) {
18
+ // Get the source directory for the actual files
19
+ const source = dir + '/src';
20
+ // Load the template files into the destination
21
+ await (0, load_schema_1.default)(source + '/schema');
22
+ cli.log('Loaded Schema');
23
+ await (0, load_roles_1.default)((0, read_file_1.default)('roles', source));
24
+ cli.log('Loaded Roles');
25
+ await (0, load_to_destination_1.default)('folders', (0, read_file_1.default)('folders', source));
26
+ cli.log('Loaded Folders');
27
+ await (0, load_dashboards_1.default)((0, read_file_1.default)('dashboards', source));
28
+ cli.log('Loaded Dashboards');
29
+ await (0, load_to_destination_1.default)('panels', (0, read_file_1.default)('panels', source)); // Comes after dashboards
30
+ cli.log('Loaded Panels');
31
+ await (0, load_files_1.default)((0, read_file_1.default)('files', source), source); // Comes after folders
32
+ cli.log('Loaded Files');
33
+ await (0, load_users_1.default)((0, read_file_1.default)('users', source)); // Comes after roles, files
34
+ cli.log('Loaded Users');
35
+ await (0, load_flows_1.default)((0, read_file_1.default)('flows', source));
36
+ cli.log('Loaded Flows');
37
+ await (0, load_operations_1.default)((0, read_file_1.default)('operations', source)); // Comes after flows
38
+ cli.log('Loaded Operations');
39
+ await (0, load_data_1.default)((0, read_file_1.default)('collections', source), source);
40
+ cli.log('Loaded Data');
41
+ await (0, load_presets_1.default)((0, read_file_1.default)('presets', source));
42
+ cli.log('Loaded Presets');
43
+ await (0, load_settings_1.default)((0, read_file_1.default)('settings', source));
44
+ cli.log('Loaded Settings');
45
+ await (0, load_public_permissions_1.default)((0, read_file_1.default)('public-permissions', source));
46
+ cli.log('Loaded Public Permissions');
47
+ return {};
48
+ }
49
+ exports.default = apply;
@@ -0,0 +1 @@
1
+ export default function loadDashboards(dashboards: any): Promise<void>;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const load_to_destination_1 = tslib_1.__importDefault(require("../utils/load-to-destination"));
5
+ async function loadDashboards(dashboards) {
6
+ const filteredDashboards = dashboards.map(dash => {
7
+ const newDash = { ...dash };
8
+ delete newDash.panels;
9
+ return newDash;
10
+ });
11
+ await (0, load_to_destination_1.default)('dashboards', filteredDashboards);
12
+ }
13
+ exports.default = loadDashboards;
@@ -0,0 +1 @@
1
+ export default function loadData(collections: any, dir: string): Promise<void>;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const api_1 = require("../api");
5
+ const node_path_1 = tslib_1.__importDefault(require("node:path"));
6
+ async function loadData(collections, dir) {
7
+ const userCollections = collections
8
+ .filter(item => !item.collection.startsWith('directus_', 0))
9
+ .filter(item => item.schema !== null); // Filter our any "folders"
10
+ await loadSkeletonRecords(userCollections, dir); // Empty Records with IDs only
11
+ await loadFullData(userCollections, dir); // Updates all skeleton records with their other values
12
+ await loadSingletons(userCollections, dir);
13
+ }
14
+ exports.default = loadData;
15
+ // Handle mandatory fields properly
16
+ // Upload record id.
17
+ // SQL reset indexes once everything is loaded. - This is required for
18
+ // Project Settings - ?
19
+ const loadSkeletonRecords = async (userCollections, dir) => {
20
+ var _a;
21
+ for (const collection of userCollections) {
22
+ const name = collection.collection;
23
+ const url = node_path_1.default.resolve(dir, 'content', `${name}.json`);
24
+ try {
25
+ const sourceData = (await (_a = url, Promise.resolve().then(() => tslib_1.__importStar(require(_a))))).default;
26
+ if (!collection.meta.singleton) {
27
+ for (const entry of sourceData) {
28
+ try {
29
+ const { data } = await api_1.api.post(`items/${name}`, {
30
+ id: entry.id,
31
+ });
32
+ }
33
+ catch (error) {
34
+ if (error.response.data.errors[0].extensions.code !==
35
+ 'RECORD_NOT_UNIQUE') {
36
+ console.log('error creating skeleton record', error.response.data.errors);
37
+ }
38
+ }
39
+ }
40
+ }
41
+ }
42
+ catch (error) {
43
+ console.log(error.response.data.errors);
44
+ }
45
+ }
46
+ };
47
+ const loadFullData = async (userCollections, dir) => {
48
+ var _a;
49
+ for (const collection of userCollections) {
50
+ const name = collection.collection;
51
+ const url = node_path_1.default.resolve(dir, 'content', `${name}.json`);
52
+ try {
53
+ const sourceData = (await (_a = url, Promise.resolve().then(() => tslib_1.__importStar(require(_a))))).default;
54
+ if (!collection.meta.singleton) {
55
+ for (const row of sourceData) {
56
+ delete row.user_created;
57
+ delete row.user_updated;
58
+ const { data } = await api_1.api.patch(`items/${name}/${row.id}`, row);
59
+ }
60
+ }
61
+ }
62
+ catch (error) {
63
+ console.log(`Error updating ${name}`, error.response.data.errors);
64
+ }
65
+ }
66
+ };
67
+ const loadSingletons = async (userCollections, dir) => {
68
+ var _a;
69
+ for (const collection of userCollections) {
70
+ if (collection.meta.singleton) {
71
+ const name = collection.collection;
72
+ const url = node_path_1.default.resolve(dir, 'content', `${name}.json`);
73
+ try {
74
+ const sourceData = (await (_a = url, Promise.resolve().then(() => tslib_1.__importStar(require(_a))))).default;
75
+ delete sourceData.user_created;
76
+ delete sourceData.user_updated;
77
+ const { data } = await api_1.api.patch(`items/${name}`, sourceData);
78
+ }
79
+ catch (error) {
80
+ console.log(`Error loading singleton ${name}`, error.response.data.errors);
81
+ }
82
+ }
83
+ }
84
+ };
@@ -0,0 +1,2 @@
1
+ declare const _default: (assets: any, dir: string) => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const form_data_1 = tslib_1.__importDefault(require("form-data"));
5
+ const api_1 = require("../api");
6
+ const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
7
+ const node_path_1 = tslib_1.__importDefault(require("node:path"));
8
+ exports.default = async (assets, dir) => {
9
+ for (const asset of assets) {
10
+ const fileName = asset.filename_disk;
11
+ const assetPath = node_path_1.default.resolve(dir, 'assets', fileName);
12
+ const fileStream = node_fs_1.default.createReadStream(assetPath);
13
+ const form = new form_data_1.default();
14
+ form.append('id', asset.id);
15
+ form.append('file', fileStream);
16
+ if (asset.title)
17
+ form.append('title', asset.title);
18
+ if (asset.description)
19
+ form.append('description', asset.description);
20
+ if (asset.folder)
21
+ form.append('folder', asset.folder);
22
+ // form.append;
23
+ try {
24
+ const { data } = await api_1.api.post('files', form, {
25
+ headers: {
26
+ 'Content-Type': 'multipart/form-data',
27
+ },
28
+ });
29
+ // await api.patch(`files/${asset.id}`, {
30
+ // // Add to form
31
+ // title: asset.title,
32
+ // description: asset.description,
33
+ // folder: asset.folder,
34
+ // })
35
+ // console.log(`Uploaded ${asset.id}`)
36
+ }
37
+ catch (error) {
38
+ console.log(error.response.data.errors);
39
+ }
40
+ }
41
+ // console.log('file', file);
42
+ };
@@ -0,0 +1,2 @@
1
+ declare const _default: (flows: any[]) => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const api_1 = require("../api");
4
+ exports.default = async (flows) => {
5
+ const removeOps = flows.map(flow => {
6
+ delete flow.operations;
7
+ return flow;
8
+ });
9
+ for (const flow of removeOps) {
10
+ try {
11
+ await api_1.api.post('flows', flow);
12
+ console.log('Uploaded Flow');
13
+ }
14
+ catch (error) {
15
+ console.log('Error uploading flow.', error.response.data.errors);
16
+ }
17
+ }
18
+ };
@@ -0,0 +1 @@
1
+ export default function loadFolders(dir: string): Promise<void>;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const api_1 = require("../api");
5
+ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
6
+ async function loadFolders(dir) {
7
+ try {
8
+ const folders = await (0, read_file_1.default)('folders', dir);
9
+ const { data } = await api_1.api.post('/folders', folders);
10
+ console.log('Folder creation', data);
11
+ }
12
+ catch (error) {
13
+ console.log('Error loading Folders', error.response.data.errors);
14
+ }
15
+ }
16
+ exports.default = loadFolders;
@@ -0,0 +1 @@
1
+ export default function loadOperations(ops: any): Promise<void>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const delete_items_1 = tslib_1.__importDefault(require("../utils/delete-items"));
5
+ const api_1 = require("../api");
6
+ async function loadOperations(ops) {
7
+ await (0, delete_items_1.default)('operations');
8
+ const opsIds = ops.map(i => {
9
+ const del = { ...i };
10
+ delete del.resolve;
11
+ delete del.reject;
12
+ return del;
13
+ });
14
+ try {
15
+ await api_1.api.post('operations', opsIds);
16
+ for (const op of ops) {
17
+ const pl = {
18
+ resolve: op.resolve,
19
+ reject: op.reject,
20
+ };
21
+ // console.log(`Updating ${op.id} with`, pl)
22
+ await api_1.api.patch(`operations/${op.id}`, pl);
23
+ }
24
+ }
25
+ catch (error) {
26
+ console.log(error.response.data.errors);
27
+ }
28
+ }
29
+ exports.default = loadOperations;
File without changes
File without changes
@@ -0,0 +1,2 @@
1
+ declare const _default: (presets: any[]) => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const api_1 = require("../api");
4
+ exports.default = async (presets) => {
5
+ const cleanPresets = presets.map(preset => {
6
+ preset.user = null;
7
+ return preset;
8
+ });
9
+ for (const preset of cleanPresets) {
10
+ try {
11
+ await api_1.api.post('presets', preset);
12
+ }
13
+ catch (error) {
14
+ console.log('Error uploading preset', error.response.data.errors);
15
+ }
16
+ }
17
+ };
@@ -0,0 +1 @@
1
+ export default function loadPublicPermissions(roles: any): Promise<void>;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const api_1 = require("../api");
5
+ const load_to_destination_1 = tslib_1.__importDefault(require("../utils/load-to-destination"));
6
+ async function removeallPublicPermissions() {
7
+ const { data } = await api_1.api.get('permissions?filter[role][_null]=true&limit=-1');
8
+ const ids = data.data.map(i => i.id);
9
+ if (!ids)
10
+ return;
11
+ await api_1.api.delete('permissions', {
12
+ data: ids,
13
+ });
14
+ }
15
+ async function loadPublicPermissions(roles) {
16
+ await removeallPublicPermissions();
17
+ await (0, load_to_destination_1.default)('permissions', roles);
18
+ }
19
+ exports.default = loadPublicPermissions;
@@ -0,0 +1 @@
1
+ export default function loadRoles(roles: any): Promise<void>;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const api_1 = require("../api");
4
+ async function loadRoles(roles) {
5
+ const cleanedUpRoles = roles.map(role => {
6
+ delete role.users;
7
+ return role;
8
+ });
9
+ const adminRole = cleanedUpRoles.find(role => role.name === 'Administrator');
10
+ // Admin role isn't touched.
11
+ const customRoles = cleanedUpRoles.filter(role => role.name !== 'Administrator');
12
+ try {
13
+ const { data } = await api_1.api.post('roles', customRoles);
14
+ }
15
+ catch {
16
+ // maybe the roles already exist
17
+ }
18
+ const adminUpdate = await api_1.api.patch(`roles/${adminRole.id}`, adminRole);
19
+ console.log('Seeded Roles');
20
+ }
21
+ exports.default = loadRoles;
@@ -0,0 +1,2 @@
1
+ declare const _default: (dir: string) => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const api_1 = require("../api");
5
+ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
6
+ exports.default = async (dir) => {
7
+ const schema = (0, read_file_1.default)('snapshot', dir);
8
+ const { data } = await api_1.api.post('schema/diff?force', schema);
9
+ if (!data.data) {
10
+ console.log('No schema changes to apply');
11
+ return;
12
+ }
13
+ try {
14
+ await api_1.api.post('schema/apply', data.data);
15
+ console.log('Schema Loaded');
16
+ }
17
+ catch (error) {
18
+ console.log('Error Applying schema', error.response.data.errors);
19
+ }
20
+ };
@@ -0,0 +1 @@
1
+ export default function loadSettings(settingsObj: any): Promise<void>;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const api_1 = require("../api");
4
+ async function loadSettings(settingsObj) {
5
+ try {
6
+ const { data } = await api_1.api.patch('settings', settingsObj);
7
+ }
8
+ catch (error) {
9
+ console.log('Error loading settings', error.response.data.errors);
10
+ }
11
+ }
12
+ exports.default = loadSettings;
@@ -0,0 +1,2 @@
1
+ declare const _default: (users: any[]) => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const api_1 = require("../api");
5
+ const generate_password_1 = tslib_1.__importDefault(require("generate-password"));
6
+ exports.default = async (users) => {
7
+ const cleanedUpUsers = users.map(user => {
8
+ // TODO: Find user role by id in the saved roles.json file. If it's the Directus boostrapped admin role, replace it with the Administrator role id from the new Directus instance.
9
+ delete user.role;
10
+ //
11
+ delete user.last_page;
12
+ delete user.token;
13
+ // user.password = getNewPassword()
14
+ return user;
15
+ });
16
+ for (const user of cleanedUpUsers) {
17
+ try {
18
+ await api_1.api.post('users', user);
19
+ // console.log('Uploaded User' + user.email)
20
+ }
21
+ catch (error) {
22
+ console.log('Error uploading user.', error.response.data.errors);
23
+ }
24
+ }
25
+ };
26
+ const getNewPassword = () => {
27
+ return generate_password_1.default.generate({
28
+ length: 12,
29
+ numbers: true,
30
+ });
31
+ };
@@ -0,0 +1 @@
1
+ export default function deleteItems(collection: string): Promise<void>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const api_1 = require("../api");
4
+ async function deleteItems(collection) {
5
+ const { data } = await api_1.api.get(collection, {
6
+ params: {
7
+ limit: -1,
8
+ },
9
+ });
10
+ const ids = data.data.map(i => i.id);
11
+ await api_1.api.delete(collection, {
12
+ data: ids,
13
+ });
14
+ }
15
+ exports.default = deleteItems;
@@ -0,0 +1 @@
1
+ export default function loadToDestination(entity: string, rawData: any[]): Promise<void>;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const api_1 = require("../api");
4
+ async function loadToDestination(entity, rawData) {
5
+ for (const row of rawData) {
6
+ try {
7
+ const { data } = await api_1.api.post(entity, row);
8
+ }
9
+ catch (error) {
10
+ console.log(`error with ${entity} - ${row.id}`, error.response.data.errors);
11
+ }
12
+ }
13
+ }
14
+ exports.default = loadToDestination;
@@ -0,0 +1,2 @@
1
+ export default function readFile(file: string, dir: string): any[];
2
+ export declare function readJsonFile(path: string): any[];
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readJsonFile = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
6
+ function readFile(file, dir) {
7
+ const f = node_fs_1.default.readFileSync(`${dir}/${file}.json`, 'utf8');
8
+ const obj = JSON.parse(f);
9
+ return obj;
10
+ }
11
+ exports.default = readFile;
12
+ function readJsonFile(path) {
13
+ const f = node_fs_1.default.readFileSync(`${path}.json`, 'utf8');
14
+ const obj = JSON.parse(f);
15
+ return obj;
16
+ }
17
+ exports.readJsonFile = readJsonFile;
@@ -0,0 +1,6 @@
1
+ interface Template {
2
+ directoryPath: string;
3
+ templateName: string;
4
+ }
5
+ export default function readTemplates(directoryPath: string): Promise<Template[]>;
6
+ export {};
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
5
+ const node_path_1 = tslib_1.__importDefault(require("node:path"));
6
+ async function readTemplates(directoryPath) {
7
+ const templates = [];
8
+ // Read the contents of the directory
9
+ const files = await node_fs_1.default.promises.readdir(directoryPath);
10
+ // Loop through each file in the directory
11
+ for (const file of files) {
12
+ // Check if the file is a directory
13
+ const filePath = node_path_1.default.join(directoryPath, file);
14
+ const stats = await node_fs_1.default.promises.stat(filePath);
15
+ if (stats.isDirectory()) {
16
+ // Read the contents of the package.json file in the directory
17
+ const packageFilePath = node_path_1.default.join(filePath, 'package.json');
18
+ try {
19
+ const packageData = await node_fs_1.default.promises.readFile(packageFilePath, 'utf-8');
20
+ const packageJson = JSON.parse(packageData);
21
+ if (packageJson.templateName) {
22
+ const template = {
23
+ directoryPath: filePath,
24
+ templateName: packageJson.templateName,
25
+ };
26
+ templates.push(template);
27
+ }
28
+ }
29
+ catch (error) {
30
+ console.error(`Failed to read package.json file in directory ${filePath}: ${error}`);
31
+ }
32
+ }
33
+ }
34
+ return templates;
35
+ }
36
+ exports.default = readTemplates;
@@ -0,0 +1 @@
1
+ export default function validateUrl(url: string): boolean;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function validateUrl(url) {
4
+ try {
5
+ new URL(url);
6
+ return true;
7
+ }
8
+ catch (err) {
9
+ return false;
10
+ }
11
+ }
12
+ exports.default = validateUrl;
@@ -0,0 +1,2 @@
1
+ declare const _default: (fileName: string, data: any) => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const node_path_1 = tslib_1.__importDefault(require("node:path"));
5
+ const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
6
+ const dir = node_path_1.default.join(__dirname, '..', 'source');
7
+ exports.default = async (fileName, data) => {
8
+ const folders = fileName.split('/');
9
+ const endFileName = folders.pop();
10
+ const folderPath = folders.join('/');
11
+ const fullPath = node_path_1.default.join(dir, folderPath);
12
+ if (node_path_1.default && !node_fs_1.default.existsSync(fullPath)) {
13
+ node_fs_1.default.mkdirSync(fullPath);
14
+ }
15
+ try {
16
+ await node_fs_1.default.promises.writeFile(`${dir}/${fileName}.json`, JSON.stringify(data, null, 2));
17
+ console.log(`Wrote ${fileName}`);
18
+ }
19
+ catch (error) {
20
+ console.log('error writing to file', error);
21
+ }
22
+ };
@@ -0,0 +1,19 @@
1
+ {
2
+ "version": "0.1.0",
3
+ "commands": {
4
+ "apply": {
5
+ "id": "apply",
6
+ "description": "Apply a template to a blank Directus instance.",
7
+ "strict": true,
8
+ "pluginName": "directus-template-cli",
9
+ "pluginAlias": "directus-template-cli",
10
+ "pluginType": "core",
11
+ "aliases": [],
12
+ "examples": [
13
+ "$ directus-template-cli apply"
14
+ ],
15
+ "flags": {},
16
+ "args": {}
17
+ }
18
+ }
19
+ }
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "directus-template-cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI Utility for applying templates to a Directus instance.",
5
+ "author": "bryantgillespie @bryantgillespie",
6
+ "bin": {
7
+ "directus-template-util": "./bin/run"
8
+ },
9
+ "homepage": "https://github.com/bryantgillespie/directus-template-cli",
10
+ "license": "MIT",
11
+ "main": "dist/index.js",
12
+ "repository": "bryantgillespie/directus-template-cli",
13
+ "files": [
14
+ "/bin",
15
+ "/templates",
16
+ "/dist",
17
+ "/npm-shrinkwrap.json",
18
+ "/oclif.manifest.json"
19
+ ],
20
+ "dependencies": {
21
+ "@oclif/core": "^2",
22
+ "@oclif/plugin-help": "^5",
23
+ "@oclif/plugin-plugins": "^2.4.6",
24
+ "inquirer": "^8.2.5",
25
+ "axios": "^1.3.4",
26
+ "dotenv": "^16.0.3",
27
+ "formdata-node": "^5.0.0",
28
+ "generate-password": "^1.7.0"
29
+ },
30
+ "devDependencies": {
31
+ "@oclif/test": "^2.3.16",
32
+ "@types/chai": "^4",
33
+ "@types/mocha": "^9.0.0",
34
+ "@types/node": "^16.18.24",
35
+ "chai": "^4",
36
+ "eslint": "^7.32.0",
37
+ "eslint-config-oclif": "^4",
38
+ "eslint-config-oclif-typescript": "^1.0.3",
39
+ "mocha": "^9",
40
+ "oclif": "^3",
41
+ "shx": "^0.3.3",
42
+ "ts-node": "^10.9.1",
43
+ "tslib": "^2.5.0",
44
+ "typescript": "^4.9.5"
45
+ },
46
+ "oclif": {
47
+ "bin": "directus-template-cli",
48
+ "dirname": "directus-template-cli",
49
+ "commands": "./dist/commands",
50
+ "plugins": [
51
+ "@oclif/plugin-help",
52
+ "@oclif/plugin-plugins"
53
+ ],
54
+ "topicSeparator": " ",
55
+ "topics": {
56
+ "hello": {
57
+ "description": "Say hello to the world and others"
58
+ }
59
+ }
60
+ },
61
+ "scripts": {
62
+ "build": "shx rm -rf dist && tsc -b",
63
+ "lint": "eslint . --ext .ts --config .eslintrc",
64
+ "postpack": "shx rm -f oclif.manifest.json",
65
+ "posttest": "yarn lint",
66
+ "prepack": "yarn build && oclif manifest && oclif readme",
67
+ "test": "mocha --forbid-only \"test/**/*.test.ts\"",
68
+ "version": "oclif readme && git add README.md"
69
+ },
70
+ "engines": {
71
+ "node": ">=12.0.0"
72
+ },
73
+ "bugs": "https://github.com/bryantgillespie/directus-template-cli/issues",
74
+ "keywords": [
75
+ "oclif"
76
+ ],
77
+ "types": "dist/index.d.ts"
78
+ }