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.
- package/README.md +0 -14
- package/bin/dev.js +6 -0
- package/bin/run.js +5 -0
- package/dist/commands/apply.d.ts +17 -17
- package/dist/commands/apply.js +166 -174
- package/dist/commands/base.d.ts +15 -0
- package/dist/commands/base.js +45 -0
- package/dist/commands/extract.d.ts +16 -9
- package/dist/commands/extract.js +81 -100
- package/dist/commands/init.d.ts +42 -0
- package/dist/commands/init.js +241 -0
- package/dist/flags/common.d.ts +8 -7
- package/dist/flags/common.js +13 -11
- package/dist/index.js +1 -5
- package/dist/lib/constants.d.ts +18 -0
- package/dist/lib/constants.js +25 -6
- package/dist/lib/extract/extract-access.js +11 -15
- package/dist/lib/extract/extract-assets.js +20 -25
- package/dist/lib/extract/extract-collections.js +12 -16
- package/dist/lib/extract/extract-content.d.ts +1 -1
- package/dist/lib/extract/extract-content.js +17 -26
- package/dist/lib/extract/extract-dashboards.js +22 -28
- package/dist/lib/extract/extract-extensions.js +12 -16
- package/dist/lib/extract/extract-fields.js +12 -16
- package/dist/lib/extract/extract-files.js +15 -19
- package/dist/lib/extract/extract-flows.js +22 -28
- package/dist/lib/extract/extract-folders.js +15 -19
- package/dist/lib/extract/extract-permissions.js +12 -16
- package/dist/lib/extract/extract-policies.js +12 -16
- package/dist/lib/extract/extract-presets.js +12 -16
- package/dist/lib/extract/extract-relations.js +14 -18
- package/dist/lib/extract/extract-roles.js +15 -19
- package/dist/lib/extract/extract-schema.js +17 -21
- package/dist/lib/extract/extract-settings.js +12 -16
- package/dist/lib/extract/extract-translations.js +12 -16
- package/dist/lib/extract/extract-users.js +15 -19
- package/dist/lib/extract/index.d.ts +1 -6
- package/dist/lib/extract/index.js +47 -58
- package/dist/lib/init/config.d.ts +3 -0
- package/dist/lib/init/config.js +12 -0
- package/dist/lib/init/index.d.ts +10 -0
- package/dist/lib/init/index.js +192 -0
- package/dist/lib/init/types.d.ts +30 -0
- package/dist/lib/init/types.js +1 -0
- package/dist/lib/load/apply-flags.js +17 -23
- package/dist/lib/load/index.d.ts +1 -12
- package/dist/lib/load/index.js +40 -44
- package/dist/lib/load/load-access.js +15 -20
- package/dist/lib/load/load-collections.d.ts +2 -0
- package/dist/lib/load/load-collections.js +29 -32
- package/dist/lib/load/load-dashboards.js +19 -25
- package/dist/lib/load/load-data.js +43 -49
- package/dist/lib/load/load-extensions.js +30 -38
- package/dist/lib/load/load-files.js +20 -24
- package/dist/lib/load/load-flows.js +23 -29
- package/dist/lib/load/load-folders.js +16 -20
- package/dist/lib/load/load-permissions.js +13 -17
- package/dist/lib/load/load-policies.js +14 -18
- package/dist/lib/load/load-presets.js +14 -18
- package/dist/lib/load/load-relations.d.ts +2 -0
- package/dist/lib/load/load-relations.js +16 -18
- package/dist/lib/load/load-roles.js +19 -23
- package/dist/lib/load/load-settings.js +18 -21
- package/dist/lib/load/load-translations.js +14 -18
- package/dist/lib/load/load-users.js +21 -25
- package/dist/lib/load/update-required-fields.js +13 -17
- package/dist/lib/sdk.d.ts +1 -2
- package/dist/lib/sdk.js +27 -27
- package/dist/lib/types/extension.js +1 -2
- package/dist/lib/types.d.ts +18 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/utils/animated-bunny.d.ts +2 -0
- package/dist/lib/utils/animated-bunny.js +62 -0
- package/dist/lib/utils/auth.d.ts +8 -6
- package/dist/lib/utils/auth.js +48 -39
- package/dist/lib/utils/catch-error.js +8 -11
- package/dist/lib/utils/check-template.js +4 -8
- package/dist/lib/utils/chunk-array.js +1 -5
- package/dist/lib/utils/ensure-dir.d.ts +2 -0
- package/dist/lib/utils/ensure-dir.js +11 -0
- package/dist/lib/utils/filter-fields.js +1 -4
- package/dist/lib/utils/get-role-ids.d.ts +1 -1
- package/dist/lib/utils/get-role-ids.js +7 -12
- package/dist/lib/utils/get-template.js +33 -36
- package/dist/lib/utils/logger.js +11 -13
- package/dist/lib/utils/open-url.js +5 -8
- package/dist/lib/utils/parse-github-url.d.ts +19 -0
- package/dist/lib/utils/parse-github-url.js +89 -0
- package/dist/lib/utils/path.js +6 -10
- package/dist/lib/utils/protected-domains.js +1 -4
- package/dist/lib/utils/read-file.js +8 -12
- package/dist/lib/utils/read-templates.js +9 -15
- package/dist/lib/utils/sanitize-flags.d.ts +3 -0
- package/dist/lib/utils/sanitize-flags.js +4 -0
- package/dist/lib/utils/system-fields.js +19 -22
- package/dist/lib/utils/template-config.d.ts +16 -0
- package/dist/lib/utils/template-config.js +34 -0
- package/dist/lib/utils/template-defaults.d.ts +1 -1
- package/dist/lib/utils/template-defaults.js +5 -14
- package/dist/lib/utils/transform-github-url.js +1 -5
- package/dist/lib/utils/validate-url.js +3 -6
- package/dist/lib/utils/wait.d.ts +7 -0
- package/dist/lib/utils/wait.js +9 -0
- package/dist/lib/utils/write-to-file.js +8 -11
- package/dist/services/docker.d.ts +23 -0
- package/dist/services/docker.js +187 -0
- package/dist/services/github.d.ts +18 -0
- package/dist/services/github.js +88 -0
- package/dist/services/posthog.d.ts +37 -0
- package/dist/services/posthog.js +104 -0
- package/oclif.manifest.json +102 -23
- package/package.json +46 -29
- package/bin/dev +0 -17
- package/bin/run +0 -5
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
async function loadPolicies(dir) {
|
|
11
|
-
const policies = (0, read_file_1.default)('policies', dir);
|
|
12
|
-
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${policies.length} policies`));
|
|
1
|
+
import { createPolicy, readPolicies } from '@directus/sdk';
|
|
2
|
+
import { ux } from '@oclif/core';
|
|
3
|
+
import { DIRECTUS_PINK } from '../constants.js';
|
|
4
|
+
import { api } from '../sdk.js';
|
|
5
|
+
import catchError from '../utils/catch-error.js';
|
|
6
|
+
import readFile from '../utils/read-file.js';
|
|
7
|
+
export default async function loadPolicies(dir) {
|
|
8
|
+
const policies = readFile('policies', dir);
|
|
9
|
+
ux.action.start(ux.colorize(DIRECTUS_PINK, `Loading ${policies.length} policies`));
|
|
13
10
|
if (policies && policies.length > 0) {
|
|
14
11
|
// Fetch existing policies
|
|
15
|
-
const existingPolicies = await
|
|
12
|
+
const existingPolicies = await api.client.request(readPolicies({
|
|
16
13
|
limit: -1,
|
|
17
14
|
}));
|
|
18
15
|
const existingPolicyIds = new Set(existingPolicies.map(policy => policy.id));
|
|
@@ -21,19 +18,18 @@ async function loadPolicies(dir) {
|
|
|
21
18
|
for await (const policy of policiesWithoutPublic) {
|
|
22
19
|
try {
|
|
23
20
|
if (existingPolicyIds.has(policy.id)) {
|
|
24
|
-
|
|
21
|
+
ux.action.status = `Skipping existing policy: ${policy.name}`;
|
|
25
22
|
continue;
|
|
26
23
|
}
|
|
27
24
|
// Create new policy
|
|
28
|
-
await
|
|
25
|
+
await api.client.request(createPolicy(policy));
|
|
29
26
|
// Add the new policy ID to our set of existing policies
|
|
30
27
|
existingPolicyIds.add(policy.id);
|
|
31
28
|
}
|
|
32
29
|
catch (error) {
|
|
33
|
-
(
|
|
30
|
+
catchError(error);
|
|
34
31
|
}
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
|
-
|
|
34
|
+
ux.action.stop();
|
|
38
35
|
}
|
|
39
|
-
exports.default = loadPolicies;
|
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
async function loadPresets(dir) {
|
|
11
|
-
const presets = (0, read_file_1.default)('presets', dir);
|
|
12
|
-
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${presets.length} presets`));
|
|
1
|
+
import { createPresets, readPresets } from '@directus/sdk';
|
|
2
|
+
import { ux } from '@oclif/core';
|
|
3
|
+
import { DIRECTUS_PINK } from '../constants.js';
|
|
4
|
+
import { api } from '../sdk.js';
|
|
5
|
+
import catchError from '../utils/catch-error.js';
|
|
6
|
+
import readFile from '../utils/read-file.js';
|
|
7
|
+
export default async function loadPresets(dir) {
|
|
8
|
+
const presets = readFile('presets', dir);
|
|
9
|
+
ux.action.start(ux.colorize(DIRECTUS_PINK, `Loading ${presets.length} presets`));
|
|
13
10
|
if (presets && presets.length > 0) {
|
|
14
11
|
// Fetch existing presets
|
|
15
|
-
const existingPresets = await
|
|
12
|
+
const existingPresets = await api.client.request(readPresets({
|
|
16
13
|
limit: -1,
|
|
17
14
|
}));
|
|
18
15
|
const existingPresetIds = new Set(existingPresets.map(preset => preset.id));
|
|
@@ -28,16 +25,15 @@ async function loadPresets(dir) {
|
|
|
28
25
|
});
|
|
29
26
|
if (presetsToAdd.length > 0) {
|
|
30
27
|
try {
|
|
31
|
-
await
|
|
28
|
+
await api.client.request(createPresets(presetsToAdd));
|
|
32
29
|
}
|
|
33
30
|
catch (error) {
|
|
34
|
-
(
|
|
31
|
+
catchError(error);
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
34
|
else {
|
|
38
|
-
// ux.
|
|
35
|
+
// ux.stdout('-- No new presets to create')
|
|
39
36
|
}
|
|
40
37
|
}
|
|
41
|
-
|
|
38
|
+
ux.action.stop();
|
|
42
39
|
}
|
|
43
|
-
exports.default = loadPresets;
|
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const sdk_2 = require("../sdk");
|
|
8
|
-
const catch_error_1 = tslib_1.__importDefault(require("../utils/catch-error"));
|
|
9
|
-
const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
1
|
+
import { createRelation, readRelations } from '@directus/sdk';
|
|
2
|
+
import { ux } from '@oclif/core';
|
|
3
|
+
import { DIRECTUS_PINK } from '../constants.js';
|
|
4
|
+
import { api } from '../sdk.js';
|
|
5
|
+
import catchError from '../utils/catch-error.js';
|
|
6
|
+
import readFile from '../utils/read-file.js';
|
|
10
7
|
/**
|
|
11
8
|
* Load relationships into the Directus instance
|
|
9
|
+
* @param dir - The directory to read the relations from
|
|
10
|
+
* @returns {Promise<void>} - Returns nothing
|
|
12
11
|
*/
|
|
13
|
-
async function loadRelations(dir) {
|
|
14
|
-
const relations = (
|
|
15
|
-
|
|
12
|
+
export default async function loadRelations(dir) {
|
|
13
|
+
const relations = readFile('relations', dir);
|
|
14
|
+
ux.action.start(ux.colorize(DIRECTUS_PINK, `Loading ${relations.length} relations`));
|
|
16
15
|
if (relations && relations.length > 0) {
|
|
17
16
|
// Fetch existing relations
|
|
18
|
-
const existingRelations = await
|
|
17
|
+
const existingRelations = await api.client.request(readRelations());
|
|
19
18
|
const existingRelationKeys = new Set(existingRelations.map(relation => `${relation.collection}:${relation.field}:${relation.related_collection}`));
|
|
20
19
|
const relationsToAdd = relations.filter(relation => {
|
|
21
20
|
const key = `${relation.collection}:${relation.field}:${relation.related_collection}`;
|
|
@@ -25,21 +24,20 @@ async function loadRelations(dir) {
|
|
|
25
24
|
return true;
|
|
26
25
|
}).map(relation => {
|
|
27
26
|
const cleanRelation = { ...relation };
|
|
28
|
-
|
|
27
|
+
cleanRelation.meta.id = undefined;
|
|
29
28
|
return cleanRelation;
|
|
30
29
|
});
|
|
31
30
|
await addRelations(relationsToAdd);
|
|
32
31
|
}
|
|
33
|
-
|
|
32
|
+
ux.action.stop();
|
|
34
33
|
}
|
|
35
|
-
exports.default = loadRelations;
|
|
36
34
|
async function addRelations(relations) {
|
|
37
35
|
for await (const relation of relations) {
|
|
38
36
|
try {
|
|
39
|
-
await
|
|
37
|
+
await api.client.request(createRelation(relation));
|
|
40
38
|
}
|
|
41
39
|
catch (error) {
|
|
42
|
-
(
|
|
40
|
+
catchError(error);
|
|
43
41
|
}
|
|
44
42
|
}
|
|
45
43
|
}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
async function loadRoles(dir) {
|
|
12
|
-
const roles = (0, read_file_1.default)('roles', dir);
|
|
13
|
-
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${roles.length} roles`));
|
|
1
|
+
import { createRole, readRoles, updateRole } from '@directus/sdk';
|
|
2
|
+
import { ux } from '@oclif/core';
|
|
3
|
+
import { DIRECTUS_PINK } from '../constants.js';
|
|
4
|
+
import { api } from '../sdk.js';
|
|
5
|
+
import catchError from '../utils/catch-error.js';
|
|
6
|
+
import getRoleIds from '../utils/get-role-ids.js';
|
|
7
|
+
import readFile from '../utils/read-file.js';
|
|
8
|
+
export default async function loadRoles(dir) {
|
|
9
|
+
const roles = readFile('roles', dir);
|
|
10
|
+
ux.action.start(ux.colorize(DIRECTUS_PINK, `Loading ${roles.length} roles`));
|
|
14
11
|
if (roles && roles.length > 0) {
|
|
15
|
-
const { legacyAdminRoleId, newAdminRoleId } = await (
|
|
12
|
+
const { legacyAdminRoleId, newAdminRoleId } = await getRoleIds(dir);
|
|
16
13
|
// Fetch existing roles
|
|
17
|
-
const existingRoles = await
|
|
14
|
+
const existingRoles = await api.client.request(readRoles({
|
|
18
15
|
limit: -1,
|
|
19
16
|
}));
|
|
20
17
|
const existingRoleIds = new Set(existingRoles.map(role => role.id));
|
|
@@ -24,8 +21,8 @@ async function loadRoles(dir) {
|
|
|
24
21
|
.filter(role => !existingRoleNames.has(role.name.toLowerCase())) // Filter out roles with existing names
|
|
25
22
|
.map(role => {
|
|
26
23
|
const r = { ...role };
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
r.users = undefined; // Alias field. User roles will be applied when the users are loaded.
|
|
25
|
+
r.parent = undefined; // We need to load all roles first
|
|
29
26
|
return r;
|
|
30
27
|
});
|
|
31
28
|
for await (const role of cleanedUpRoles) {
|
|
@@ -34,13 +31,13 @@ async function loadRoles(dir) {
|
|
|
34
31
|
continue;
|
|
35
32
|
}
|
|
36
33
|
// Create new role
|
|
37
|
-
await
|
|
34
|
+
await api.client.request(createRole(role));
|
|
38
35
|
// Add the new role ID and name to our sets of existing roles
|
|
39
36
|
existingRoleIds.add(role.id);
|
|
40
37
|
existingRoleNames.add(role.name.toLowerCase());
|
|
41
38
|
}
|
|
42
39
|
catch (error) {
|
|
43
|
-
(
|
|
40
|
+
catchError(error);
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
// Now add in any parent fields
|
|
@@ -52,13 +49,12 @@ async function loadRoles(dir) {
|
|
|
52
49
|
role.parent = newAdminRoleId;
|
|
53
50
|
}
|
|
54
51
|
const simplifiedRole = { parent: role.parent };
|
|
55
|
-
await
|
|
52
|
+
await api.client.request(updateRole(role.id, simplifiedRole));
|
|
56
53
|
}
|
|
57
54
|
catch (error) {
|
|
58
|
-
(
|
|
55
|
+
catchError(error);
|
|
59
56
|
}
|
|
60
57
|
}
|
|
61
58
|
}
|
|
62
|
-
|
|
59
|
+
ux.action.stop();
|
|
63
60
|
}
|
|
64
|
-
exports.default = loadRoles;
|
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
11
|
-
const customDefu = (0, defu_1.createDefu)((obj, key, value) => {
|
|
1
|
+
import { readSettings, updateSettings } from '@directus/sdk';
|
|
2
|
+
import { ux } from '@oclif/core';
|
|
3
|
+
import { createDefu } from 'defu';
|
|
4
|
+
import { DIRECTUS_PINK } from '../constants.js';
|
|
5
|
+
import { api } from '../sdk.js';
|
|
6
|
+
import catchError from '../utils/catch-error.js';
|
|
7
|
+
import readFile from '../utils/read-file.js';
|
|
8
|
+
// Cast ux to any to bypass type errors
|
|
9
|
+
const customDefu = createDefu((obj, key, value) => {
|
|
12
10
|
if (Array.isArray(obj[key]) && Array.isArray(value)) {
|
|
13
|
-
// @ts-
|
|
11
|
+
// @ts-ignore - ignore
|
|
14
12
|
obj[key] = mergeArrays(key, obj[key], value);
|
|
15
13
|
return true;
|
|
16
14
|
}
|
|
17
15
|
if (typeof obj[key] === 'string' && typeof value === 'string') {
|
|
18
|
-
// @ts-
|
|
16
|
+
// @ts-ignore - ignore
|
|
19
17
|
obj[key] = mergeJsonStrings(obj[key], value);
|
|
20
18
|
return true;
|
|
21
19
|
}
|
|
@@ -42,17 +40,16 @@ function mergeJsonStrings(current, incoming) {
|
|
|
42
40
|
return incoming; // If not valid JSON, return the incoming value
|
|
43
41
|
}
|
|
44
42
|
}
|
|
45
|
-
async function loadSettings(dir) {
|
|
46
|
-
|
|
47
|
-
const settings = (
|
|
43
|
+
export default async function loadSettings(dir) {
|
|
44
|
+
ux.action.start(ux.colorize(DIRECTUS_PINK, 'Loading settings'));
|
|
45
|
+
const settings = readFile('settings', dir);
|
|
48
46
|
try {
|
|
49
|
-
const currentSettings = await
|
|
47
|
+
const currentSettings = await api.client.request(readSettings());
|
|
50
48
|
const mergedSettings = customDefu(currentSettings, settings);
|
|
51
|
-
await
|
|
49
|
+
await api.client.request(updateSettings(mergedSettings));
|
|
52
50
|
}
|
|
53
51
|
catch (error) {
|
|
54
|
-
(
|
|
52
|
+
catchError(error);
|
|
55
53
|
}
|
|
56
|
-
|
|
54
|
+
ux.action.stop();
|
|
57
55
|
}
|
|
58
|
-
exports.default = loadSettings;
|
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
async function loadTranslations(dir) {
|
|
11
|
-
const translations = (0, read_file_1.default)('translations', dir);
|
|
12
|
-
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${translations.length} translations`));
|
|
1
|
+
import { createTranslations, readTranslations } from '@directus/sdk';
|
|
2
|
+
import { ux } from '@oclif/core';
|
|
3
|
+
import { DIRECTUS_PINK } from '../constants.js';
|
|
4
|
+
import { api } from '../sdk.js';
|
|
5
|
+
import catchError from '../utils/catch-error.js';
|
|
6
|
+
import readFile from '../utils/read-file.js';
|
|
7
|
+
export default async function loadTranslations(dir) {
|
|
8
|
+
const translations = readFile('translations', dir);
|
|
9
|
+
ux.action.start(ux.colorize(DIRECTUS_PINK, `Loading ${translations.length} translations`));
|
|
13
10
|
if (translations && translations.length > 0) {
|
|
14
11
|
// Fetch existing translations
|
|
15
|
-
const existingTranslations = await
|
|
12
|
+
const existingTranslations = await api.client.request(readTranslations({
|
|
16
13
|
limit: -1,
|
|
17
14
|
}));
|
|
18
15
|
const existingTranslationKeys = new Set(existingTranslations.map(t => `${t.language}_${t.key}`));
|
|
@@ -25,16 +22,15 @@ async function loadTranslations(dir) {
|
|
|
25
22
|
});
|
|
26
23
|
if (newTranslations.length > 0) {
|
|
27
24
|
try {
|
|
28
|
-
await
|
|
25
|
+
await api.client.request(createTranslations(newTranslations));
|
|
29
26
|
}
|
|
30
27
|
catch (error) {
|
|
31
|
-
(
|
|
28
|
+
catchError(error);
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
31
|
else {
|
|
35
|
-
// ux.
|
|
32
|
+
// ux.stdout('-- No new translations to create')
|
|
36
33
|
}
|
|
37
34
|
}
|
|
38
|
-
|
|
35
|
+
ux.action.stop();
|
|
39
36
|
}
|
|
40
|
-
exports.default = loadTranslations;
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
async function loadUsers(dir) {
|
|
12
|
-
const users = (0, read_file_1.default)('users', dir);
|
|
13
|
-
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${users.length} users`));
|
|
1
|
+
import { createUser, readUsers } from '@directus/sdk';
|
|
2
|
+
import { ux } from '@oclif/core';
|
|
3
|
+
import { DIRECTUS_PINK } from '../constants.js';
|
|
4
|
+
import { api } from '../sdk.js';
|
|
5
|
+
import catchError from '../utils/catch-error.js';
|
|
6
|
+
import getRoleIds from '../utils/get-role-ids.js';
|
|
7
|
+
import readFile from '../utils/read-file.js';
|
|
8
|
+
export default async function loadUsers(dir) {
|
|
9
|
+
const users = readFile('users', dir);
|
|
10
|
+
ux.action.start(ux.colorize(DIRECTUS_PINK, `Loading ${users.length} users`));
|
|
14
11
|
if (users && users.length > 0) {
|
|
15
|
-
const { legacyAdminRoleId, newAdminRoleId } = await (
|
|
16
|
-
const existingUsers = await
|
|
12
|
+
const { legacyAdminRoleId, newAdminRoleId } = await getRoleIds(dir);
|
|
13
|
+
const existingUsers = await api.client.request(readUsers({
|
|
17
14
|
limit: -1,
|
|
18
15
|
}));
|
|
19
16
|
const filteredUsers = users.map(user => {
|
|
@@ -21,11 +18,11 @@ async function loadUsers(dir) {
|
|
|
21
18
|
const isAdmin = user.role === legacyAdminRoleId;
|
|
22
19
|
user.role = isAdmin ? newAdminRoleId : user.role;
|
|
23
20
|
// Delete the unneeded fields
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
user.last_page = undefined;
|
|
22
|
+
user.token = undefined;
|
|
23
|
+
user.policies = undefined;
|
|
27
24
|
// Delete passwords to prevent setting to *******
|
|
28
|
-
|
|
25
|
+
user.password = undefined;
|
|
29
26
|
return user;
|
|
30
27
|
});
|
|
31
28
|
for await (const user of filteredUsers) {
|
|
@@ -41,20 +38,19 @@ async function loadUsers(dir) {
|
|
|
41
38
|
}
|
|
42
39
|
if (existingUserWithSameEmail) {
|
|
43
40
|
// Delete email if there's an existing user with the same email but different id
|
|
44
|
-
|
|
41
|
+
user.email = undefined;
|
|
45
42
|
}
|
|
46
43
|
if (user.email === null) {
|
|
47
44
|
// Delete email if it's null
|
|
48
|
-
|
|
45
|
+
user.email = undefined;
|
|
49
46
|
}
|
|
50
47
|
try {
|
|
51
|
-
await
|
|
48
|
+
await api.client.request(createUser(user));
|
|
52
49
|
}
|
|
53
50
|
catch (error) {
|
|
54
|
-
(
|
|
51
|
+
catchError(error);
|
|
55
52
|
}
|
|
56
53
|
}
|
|
57
54
|
}
|
|
58
|
-
|
|
55
|
+
ux.action.stop();
|
|
59
56
|
}
|
|
60
|
-
exports.default = loadUsers;
|
|
@@ -1,24 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const fieldsToUpdate = (0, read_file_1.default)('fields', dir)
|
|
12
|
-
.filter(field => { var _a, _b; return field.meta.required === true || ((_a = field.schema) === null || _a === void 0 ? void 0 : _a.is_nullable) === false || ((_b = field.schema) === null || _b === void 0 ? void 0 : _b.is_unique) === true; });
|
|
13
|
-
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Updating ${fieldsToUpdate.length} fields to required`));
|
|
1
|
+
import { updateField } from '@directus/sdk';
|
|
2
|
+
import { ux } from '@oclif/core';
|
|
3
|
+
import { DIRECTUS_PINK } from '../constants.js';
|
|
4
|
+
import { api } from '../sdk.js';
|
|
5
|
+
import catchError from '../utils/catch-error.js';
|
|
6
|
+
import readFile from '../utils/read-file.js';
|
|
7
|
+
export default async function updateRequiredFields(dir) {
|
|
8
|
+
const fieldsToUpdate = readFile('fields', dir)
|
|
9
|
+
.filter(field => field.meta.required === true || field.schema?.is_nullable === false || field.schema?.is_unique === true);
|
|
10
|
+
ux.action.start(ux.colorize(DIRECTUS_PINK, `Updating ${fieldsToUpdate.length} fields to required`));
|
|
14
11
|
for await (const field of fieldsToUpdate) {
|
|
15
12
|
try {
|
|
16
|
-
await
|
|
13
|
+
await api.client.request(updateField(field.collection, field.field, { meta: { ...field.meta }, schema: { ...field.schema } }));
|
|
17
14
|
}
|
|
18
15
|
catch (error) {
|
|
19
|
-
(
|
|
16
|
+
catchError(error);
|
|
20
17
|
}
|
|
21
18
|
}
|
|
22
|
-
|
|
19
|
+
ux.action.stop();
|
|
23
20
|
}
|
|
24
|
-
exports.default = updateRequiredFields;
|
package/dist/lib/sdk.d.ts
CHANGED
package/dist/lib/sdk.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { authentication, createDirectus, rest } from '@directus/sdk';
|
|
2
|
+
import { ux } from '@oclif/core';
|
|
3
|
+
import Bottleneck from 'bottleneck';
|
|
4
|
+
export class DirectusError extends Error {
|
|
5
|
+
errors;
|
|
6
|
+
headers;
|
|
7
|
+
message;
|
|
8
|
+
response;
|
|
9
|
+
status;
|
|
9
10
|
constructor(response) {
|
|
10
11
|
super(response.statusText);
|
|
11
12
|
this.name = 'DirectusError';
|
|
@@ -39,11 +40,12 @@ class DirectusError extends Error {
|
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
|
-
exports.DirectusError = DirectusError;
|
|
43
43
|
class Api {
|
|
44
|
+
client;
|
|
45
|
+
authData = null;
|
|
46
|
+
limiter;
|
|
44
47
|
constructor() {
|
|
45
|
-
this.
|
|
46
|
-
this.limiter = new bottleneck_1.default({
|
|
48
|
+
this.limiter = new Bottleneck({
|
|
47
49
|
maxConcurrent: 10,
|
|
48
50
|
minTime: 100, // Ensure at least 100ms between requests
|
|
49
51
|
reservoir: 50, // Reservoir to handle the default rate limiter of 50 requests per second
|
|
@@ -52,18 +54,17 @@ class Api {
|
|
|
52
54
|
retryCount: 3, // Retry a maximum of 3 times
|
|
53
55
|
});
|
|
54
56
|
this.limiter.on('failed', async (error, jobInfo) => {
|
|
55
|
-
var _a;
|
|
56
57
|
if (error instanceof DirectusError) {
|
|
57
|
-
const retryAfter =
|
|
58
|
+
const retryAfter = error.headers?.get('Retry-After');
|
|
58
59
|
const statusCode = error.status;
|
|
59
60
|
if (statusCode === 429) {
|
|
60
|
-
const delay = retryAfter ? Number.parseInt(retryAfter, 10) * 1000 :
|
|
61
|
-
|
|
61
|
+
const delay = retryAfter ? Number.parseInt(retryAfter, 10) * 1000 : 60_000;
|
|
62
|
+
ux.stdout(`${ux.colorize('dim', '--')} Rate limited. Retrying after ${delay}ms`);
|
|
62
63
|
return delay;
|
|
63
64
|
}
|
|
64
65
|
if (statusCode === 503) {
|
|
65
66
|
const delay = retryAfter ? Number.parseInt(retryAfter, 10) * 1000 : 5000;
|
|
66
|
-
|
|
67
|
+
ux.stdout(`${ux.colorize('dim', '--')} Server under pressure. Retrying after ${delay}ms`);
|
|
67
68
|
return delay;
|
|
68
69
|
}
|
|
69
70
|
// If the status code is 400 or 401, we don't want to retry
|
|
@@ -73,33 +74,32 @@ class Api {
|
|
|
73
74
|
}
|
|
74
75
|
// For other errors, use exponential backoff, but only if we haven't exceeded retryCount
|
|
75
76
|
if (jobInfo.retryCount < 3) {
|
|
76
|
-
const delay = Math.min(1000 * 2 ** jobInfo.retryCount,
|
|
77
|
-
|
|
77
|
+
const delay = Math.min(1000 * 2 ** jobInfo.retryCount, 30_000);
|
|
78
|
+
ux.stdout(`${ux.colorize('dim', '--')} Request failed. Retrying after ${delay}ms`);
|
|
78
79
|
return delay;
|
|
79
80
|
}
|
|
80
|
-
|
|
81
|
+
ux.stdout(`${ux.colorize('dim', '--')} Max retries reached, not retrying further`);
|
|
81
82
|
});
|
|
82
83
|
this.limiter.on('retry', (error, jobInfo) => {
|
|
83
|
-
|
|
84
|
+
ux.stdout(`${ux.colorize('dim', '--')} Retrying job (attempt ${jobInfo.retryCount + 1})`);
|
|
84
85
|
});
|
|
85
86
|
this.limiter.on('depleted', empty => {
|
|
86
87
|
if (empty) {
|
|
87
|
-
|
|
88
|
+
ux.stdout(`${ux.colorize('dim', '--')} Rate limit quota depleted. Requests will be queued.`);
|
|
88
89
|
}
|
|
89
90
|
});
|
|
90
91
|
}
|
|
91
92
|
getToken() {
|
|
92
|
-
|
|
93
|
-
return (_b = (_a = this.authData) === null || _a === void 0 ? void 0 : _a.access_token) !== null && _b !== void 0 ? _b : null;
|
|
93
|
+
return this.authData?.access_token ?? null;
|
|
94
94
|
}
|
|
95
95
|
initialize(url) {
|
|
96
|
-
this.client =
|
|
96
|
+
this.client = createDirectus(url, {
|
|
97
97
|
globals: {
|
|
98
98
|
fetch: this.limiter.wrap(this.enhancedFetch),
|
|
99
99
|
},
|
|
100
100
|
})
|
|
101
|
-
.with(
|
|
102
|
-
.with(
|
|
101
|
+
.with(rest())
|
|
102
|
+
.with(authentication('json', {
|
|
103
103
|
autoRefresh: true,
|
|
104
104
|
storage: {
|
|
105
105
|
get: () => this.authData,
|
|
@@ -145,4 +145,4 @@ class Api {
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
const api = new Api();
|
|
148
|
-
|
|
148
|
+
export { api };
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface DirectusTemplateFrontend {
|
|
2
|
+
name: string;
|
|
3
|
+
path: string;
|
|
4
|
+
}
|
|
5
|
+
export interface DirectusTemplateConfig {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
template: string;
|
|
9
|
+
frontends: {
|
|
10
|
+
[key: string]: DirectusTemplateFrontend;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export interface TemplatePackageJson {
|
|
14
|
+
name: string;
|
|
15
|
+
version: string;
|
|
16
|
+
description: string;
|
|
17
|
+
'directus:template'?: DirectusTemplateConfig;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|