directus-template-cli 0.5.0-beta.10 → 0.5.0-beta.11
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/dist/lib/load/load-access.js +39 -37
- package/dist/lib/load/load-dashboards.js +27 -25
- package/dist/lib/load/load-files.js +47 -45
- package/dist/lib/load/load-flows.js +26 -24
- package/dist/lib/load/load-folders.js +32 -30
- package/dist/lib/load/load-permissions.js +14 -12
- package/dist/lib/load/load-policies.js +21 -19
- package/dist/lib/load/load-presets.js +25 -23
- package/dist/lib/load/load-relations.js +17 -15
- package/dist/lib/load/load-roles.js +43 -41
- package/dist/lib/load/load-translations.js +22 -20
- package/dist/lib/load/load-users.js +50 -39
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -9,45 +9,47 @@ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
|
9
9
|
async function loadAccess(dir) {
|
|
10
10
|
const access = (0, read_file_1.default)('access', dir);
|
|
11
11
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${access.length} accesses`));
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
12
|
+
if (access && access.length > 0) {
|
|
13
|
+
// Fetch existing accesses
|
|
14
|
+
const existingAccesses = await sdk_1.api.client.request(() => ({
|
|
15
|
+
method: 'GET',
|
|
16
|
+
params: {
|
|
17
|
+
limit: -1,
|
|
18
|
+
},
|
|
19
|
+
path: '/access',
|
|
20
|
+
}));
|
|
21
|
+
const existingAccessById = new Map(existingAccesses.map(acc => [acc.id, acc]));
|
|
22
|
+
const existingAccessByCompositeKey = new Map(existingAccesses.map(acc => [getCompositeKey(acc), acc]));
|
|
23
|
+
for await (const acc of access) {
|
|
24
|
+
try {
|
|
25
|
+
if (existingAccessById.has(acc.id)) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const compositeKey = getCompositeKey(acc);
|
|
29
|
+
if (existingAccessByCompositeKey.has(compositeKey)) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
// If the role is null, delete the role key to avoid errors
|
|
33
|
+
if (acc.role === null) {
|
|
34
|
+
delete acc.role;
|
|
35
|
+
}
|
|
36
|
+
await sdk_1.api.client.request(() => ({
|
|
37
|
+
body: JSON.stringify(acc),
|
|
38
|
+
method: 'POST',
|
|
39
|
+
path: '/access',
|
|
40
|
+
}));
|
|
41
|
+
// Add the new access to our maps
|
|
42
|
+
existingAccessById.set(acc.id, acc);
|
|
43
|
+
existingAccessByCompositeKey.set(compositeKey, acc);
|
|
26
44
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
45
|
+
catch (error) {
|
|
46
|
+
(0, catch_error_1.default)(error, {
|
|
47
|
+
context: {
|
|
48
|
+
access: acc,
|
|
49
|
+
operation: 'createAccess',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
30
52
|
}
|
|
31
|
-
// If the role is null, delete the role key to avoid errors
|
|
32
|
-
if (acc.role === null) {
|
|
33
|
-
delete acc.role;
|
|
34
|
-
}
|
|
35
|
-
await sdk_1.api.client.request(() => ({
|
|
36
|
-
body: JSON.stringify(acc),
|
|
37
|
-
method: 'POST',
|
|
38
|
-
path: '/access',
|
|
39
|
-
}));
|
|
40
|
-
// Add the new access to our maps
|
|
41
|
-
existingAccessById.set(acc.id, acc);
|
|
42
|
-
existingAccessByCompositeKey.set(compositeKey, acc);
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
(0, catch_error_1.default)(error, {
|
|
46
|
-
context: {
|
|
47
|
-
access: acc,
|
|
48
|
-
operation: 'createAccess',
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
core_1.ux.action.stop();
|
|
@@ -11,31 +11,33 @@ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
|
11
11
|
async function loadDashboards(dir) {
|
|
12
12
|
const dashboards = (0, read_file_1.default)('dashboards', dir);
|
|
13
13
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${dashboards.length} dashboards`));
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
14
|
+
if (dashboards && dashboards.length > 0) {
|
|
15
|
+
// Fetch existing dashboards
|
|
16
|
+
const existingDashboards = await sdk_2.api.client.request((0, sdk_1.readDashboards)({
|
|
17
|
+
limit: -1,
|
|
18
|
+
}));
|
|
19
|
+
const existingDashboardIds = new Set(existingDashboards.map(dashboard => dashboard.id));
|
|
20
|
+
const filteredDashboards = dashboards.filter(dashboard => {
|
|
21
|
+
if (existingDashboardIds.has(dashboard.id)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
}).map(dash => {
|
|
26
|
+
const newDash = { ...dash };
|
|
27
|
+
delete newDash.panels;
|
|
28
|
+
return newDash;
|
|
29
|
+
});
|
|
30
|
+
await Promise.all(filteredDashboards.map(async (dashboard) => {
|
|
31
|
+
try {
|
|
32
|
+
await sdk_2.api.client.request((0, sdk_1.createDashboard)(dashboard));
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
(0, catch_error_1.default)(error);
|
|
36
|
+
}
|
|
37
|
+
}));
|
|
38
|
+
await loadPanels(dir);
|
|
39
|
+
core_1.ux.action.stop();
|
|
40
|
+
}
|
|
39
41
|
}
|
|
40
42
|
exports.default = loadDashboards;
|
|
41
43
|
async function loadPanels(dir) {
|
|
@@ -13,52 +13,54 @@ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
|
13
13
|
async function loadFiles(dir) {
|
|
14
14
|
const files = (0, read_file_1.default)('files', dir);
|
|
15
15
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${files.length} files`));
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
if (files && files.length > 0) {
|
|
17
|
+
try {
|
|
18
|
+
const fileIds = files.map(file => file.id);
|
|
19
|
+
// Fetch only the files we're interested in
|
|
20
|
+
const existingFiles = await sdk_2.api.client.request((0, sdk_1.readFiles)({
|
|
21
|
+
fields: ['id', 'filename_disk'],
|
|
22
|
+
filter: {
|
|
23
|
+
id: {
|
|
24
|
+
_in: fileIds,
|
|
25
|
+
},
|
|
24
26
|
},
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
form.append('
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
27
|
+
limit: -1,
|
|
28
|
+
}));
|
|
29
|
+
const existingFileIds = new Set(existingFiles.map(file => file.id));
|
|
30
|
+
const existingFileNames = new Set(existingFiles.map(file => file.filename_disk));
|
|
31
|
+
const filesToUpload = files.filter(file => {
|
|
32
|
+
if (existingFileIds.has(file.id)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
if (existingFileNames.has(file.filename_disk)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
});
|
|
40
|
+
await Promise.all(filesToUpload.map(async (asset) => {
|
|
41
|
+
const fileName = asset.filename_disk;
|
|
42
|
+
const assetPath = node_path_1.default.resolve(dir, 'assets', fileName);
|
|
43
|
+
const fileStream = new Blob([(0, node_fs_1.readFileSync)(assetPath)], { type: asset.type });
|
|
44
|
+
const form = new formdata_node_1.FormData();
|
|
45
|
+
form.append('id', asset.id);
|
|
46
|
+
if (asset.title)
|
|
47
|
+
form.append('title', asset.title);
|
|
48
|
+
if (asset.description)
|
|
49
|
+
form.append('description', asset.description);
|
|
50
|
+
if (asset.folder)
|
|
51
|
+
form.append('folder', asset.folder);
|
|
52
|
+
form.append('file', fileStream, fileName);
|
|
53
|
+
try {
|
|
54
|
+
await sdk_2.api.client.request((0, sdk_1.uploadFiles)(form));
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
(0, catch_error_1.default)(error);
|
|
58
|
+
}
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
(0, catch_error_1.default)(error);
|
|
63
|
+
}
|
|
62
64
|
}
|
|
63
65
|
core_1.ux.action.stop();
|
|
64
66
|
}
|
|
@@ -12,32 +12,34 @@ async function loadFlows(dir) {
|
|
|
12
12
|
const flows = (0, read_file_1.default)('flows', dir);
|
|
13
13
|
const allOperations = (0, read_file_1.default)('operations', dir);
|
|
14
14
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${flows.length} flows`));
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
15
|
+
if (flows && flows.length > 0) {
|
|
16
|
+
try {
|
|
17
|
+
// Fetch existing flows
|
|
18
|
+
const existingFlows = await sdk_2.api.client.request((0, sdk_1.readFlows)({
|
|
19
|
+
limit: -1,
|
|
20
|
+
}));
|
|
21
|
+
const existingFlowIds = new Set(existingFlows.map(flow => flow.id));
|
|
22
|
+
const newFlows = flows.filter(flow => !existingFlowIds.has(flow.id));
|
|
23
|
+
const results = await Promise.allSettled(newFlows.map(flow => sdk_2.api.client.request((0, sdk_1.createFlow)(flow))));
|
|
24
|
+
const createdFlowIds = new Set();
|
|
25
|
+
for (const [index, result] of results.entries()) {
|
|
26
|
+
if (result.status === 'fulfilled') {
|
|
27
|
+
createdFlowIds.add(newFlows[index].id);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
(0, catch_error_1.default)(result.reason);
|
|
31
|
+
}
|
|
30
32
|
}
|
|
33
|
+
// Filter operations for newly created flows
|
|
34
|
+
const newOperations = allOperations.filter(operation => createdFlowIds.has(operation.flow));
|
|
35
|
+
await loadOperations(newOperations);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
(0, catch_error_1.default)(error);
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
core_1.ux.action.stop();
|
|
31
42
|
}
|
|
32
|
-
// Filter operations for newly created flows
|
|
33
|
-
const newOperations = allOperations.filter(operation => createdFlowIds.has(operation.flow));
|
|
34
|
-
await loadOperations(newOperations);
|
|
35
|
-
}
|
|
36
|
-
catch (error) {
|
|
37
|
-
(0, catch_error_1.default)(error);
|
|
38
|
-
}
|
|
39
|
-
finally {
|
|
40
|
-
core_1.ux.action.stop();
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
exports.default = loadFlows;
|
|
@@ -10,40 +10,42 @@ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
|
10
10
|
async function loadFolders(dir) {
|
|
11
11
|
const folders = (0, read_file_1.default)('folders', dir);
|
|
12
12
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${folders.length} folders`));
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const existingFolderIds = new Set(existingFolders.map(folder => folder.id));
|
|
19
|
-
const foldersToAdd = folders.filter(folder => {
|
|
20
|
-
if (existingFolderIds.has(folder.id)) {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
return true;
|
|
24
|
-
});
|
|
25
|
-
if (foldersToAdd.length > 0) {
|
|
26
|
-
const folderSkeleton = foldersToAdd.map(folder => ({ id: folder.id, name: folder.name }));
|
|
27
|
-
// Create the folders
|
|
28
|
-
await sdk_2.api.client.request((0, sdk_1.createFolders)(folderSkeleton));
|
|
29
|
-
// Update the folders with relationships concurrently
|
|
30
|
-
await Promise.all(foldersToAdd.map(async (folder) => {
|
|
31
|
-
const { id, ...rest } = folder;
|
|
32
|
-
try {
|
|
33
|
-
await sdk_2.api.client.request((0, sdk_1.updateFolder)(id, rest));
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
(0, catch_error_1.default)(error);
|
|
37
|
-
}
|
|
13
|
+
if (folders && folders.length > 0) {
|
|
14
|
+
try {
|
|
15
|
+
// Fetch existing folders
|
|
16
|
+
const existingFolders = await sdk_2.api.client.request((0, sdk_1.readFolders)({
|
|
17
|
+
limit: -1,
|
|
38
18
|
}));
|
|
19
|
+
const existingFolderIds = new Set(existingFolders.map(folder => folder.id));
|
|
20
|
+
const foldersToAdd = folders.filter(folder => {
|
|
21
|
+
if (existingFolderIds.has(folder.id)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
});
|
|
26
|
+
if (foldersToAdd.length > 0) {
|
|
27
|
+
const folderSkeleton = foldersToAdd.map(folder => ({ id: folder.id, name: folder.name }));
|
|
28
|
+
// Create the folders
|
|
29
|
+
await sdk_2.api.client.request((0, sdk_1.createFolders)(folderSkeleton));
|
|
30
|
+
// Update the folders with relationships concurrently
|
|
31
|
+
await Promise.all(foldersToAdd.map(async (folder) => {
|
|
32
|
+
const { id, ...rest } = folder;
|
|
33
|
+
try {
|
|
34
|
+
await sdk_2.api.client.request((0, sdk_1.updateFolder)(id, rest));
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
(0, catch_error_1.default)(error);
|
|
38
|
+
}
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// ux.info('-- No new folders to create')
|
|
43
|
+
}
|
|
39
44
|
}
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
catch (error) {
|
|
46
|
+
(0, catch_error_1.default)(error);
|
|
42
47
|
}
|
|
43
48
|
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
(0, catch_error_1.default)(error);
|
|
46
|
-
}
|
|
47
49
|
core_1.ux.action.stop();
|
|
48
50
|
}
|
|
49
51
|
exports.default = loadFolders;
|
|
@@ -10,19 +10,21 @@ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
|
10
10
|
async function loadPermissions(dir) {
|
|
11
11
|
const permissions = (0, read_file_1.default)('permissions', dir);
|
|
12
12
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${permissions.length} permissions`));
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
if (permissions && permissions.length > 0) {
|
|
14
|
+
try {
|
|
15
|
+
const existingPermissions = await sdk_2.api.client.request((0, sdk_1.readPermissions)({
|
|
16
|
+
limit: -1,
|
|
17
|
+
}));
|
|
18
|
+
const existingPermissionKeys = new Set(existingPermissions.map(p => `${p.collection}:${p.action}:${p.policy}`));
|
|
19
|
+
// Filter out duplicates
|
|
20
|
+
const newPermissions = permissions.filter(newPerm => !existingPermissionKeys.has(`${newPerm.collection}:${newPerm.action}:${newPerm.policy}`));
|
|
21
|
+
if (newPermissions.length > 0) {
|
|
22
|
+
await sdk_2.api.client.request((0, sdk_1.createPermissions)(newPermissions));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
(0, catch_error_1.default)(error);
|
|
22
27
|
}
|
|
23
|
-
}
|
|
24
|
-
catch (error) {
|
|
25
|
-
(0, catch_error_1.default)(error);
|
|
26
28
|
}
|
|
27
29
|
core_1.ux.action.stop();
|
|
28
30
|
}
|
|
@@ -10,26 +10,28 @@ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
|
10
10
|
async function loadPolicies(dir) {
|
|
11
11
|
const policies = (0, read_file_1.default)('policies', dir);
|
|
12
12
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${policies.length} policies`));
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
if (policies && policies.length > 0) {
|
|
14
|
+
// Fetch existing policies
|
|
15
|
+
const existingPolicies = await sdk_2.api.client.request((0, sdk_1.readPolicies)({
|
|
16
|
+
limit: -1,
|
|
17
|
+
}));
|
|
18
|
+
const existingPolicyIds = new Set(existingPolicies.map(policy => policy.id));
|
|
19
|
+
const PUBLIC_POLICY_ID = 'abf8a154-5b1c-4a46-ac9c-7300570f4f17';
|
|
20
|
+
const policiesWithoutPublic = policies.filter(policy => policy.id !== PUBLIC_POLICY_ID);
|
|
21
|
+
for await (const policy of policiesWithoutPublic) {
|
|
22
|
+
try {
|
|
23
|
+
if (existingPolicyIds.has(policy.id)) {
|
|
24
|
+
core_1.ux.action.status = `Skipping existing policy: ${policy.name}`;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
// Create new policy
|
|
28
|
+
await sdk_2.api.client.request((0, sdk_1.createPolicy)(policy));
|
|
29
|
+
// Add the new policy ID to our set of existing policies
|
|
30
|
+
existingPolicyIds.add(policy.id);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
(0, catch_error_1.default)(error);
|
|
25
34
|
}
|
|
26
|
-
// Create new policy
|
|
27
|
-
await sdk_2.api.client.request((0, sdk_1.createPolicy)(policy));
|
|
28
|
-
// Add the new policy ID to our set of existing policies
|
|
29
|
-
existingPolicyIds.add(policy.id);
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
(0, catch_error_1.default)(error);
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
core_1.ux.action.stop();
|
|
@@ -10,31 +10,33 @@ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
|
10
10
|
async function loadPresets(dir) {
|
|
11
11
|
const presets = (0, read_file_1.default)('presets', dir);
|
|
12
12
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${presets.length} presets`));
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
if (presets && presets.length > 0) {
|
|
14
|
+
// Fetch existing presets
|
|
15
|
+
const existingPresets = await sdk_2.api.client.request((0, sdk_1.readPresets)({
|
|
16
|
+
limit: -1,
|
|
17
|
+
}));
|
|
18
|
+
const existingPresetIds = new Set(existingPresets.map(preset => preset.id));
|
|
19
|
+
const presetsToAdd = presets.filter(preset => {
|
|
20
|
+
if (existingPresetIds.has(preset.id)) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
}).map(preset => {
|
|
25
|
+
const cleanPreset = { ...preset };
|
|
26
|
+
cleanPreset.user = null;
|
|
27
|
+
return cleanPreset;
|
|
28
|
+
});
|
|
29
|
+
if (presetsToAdd.length > 0) {
|
|
30
|
+
try {
|
|
31
|
+
await sdk_2.api.client.request((0, sdk_1.createPresets)(presetsToAdd));
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
(0, catch_error_1.default)(error);
|
|
35
|
+
}
|
|
21
36
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const cleanPreset = { ...preset };
|
|
25
|
-
cleanPreset.user = null;
|
|
26
|
-
return cleanPreset;
|
|
27
|
-
});
|
|
28
|
-
if (presetsToAdd.length > 0) {
|
|
29
|
-
try {
|
|
30
|
-
await sdk_2.api.client.request((0, sdk_1.createPresets)(presetsToAdd));
|
|
37
|
+
else {
|
|
38
|
+
// ux.info('-- No new presets to create')
|
|
31
39
|
}
|
|
32
|
-
catch (error) {
|
|
33
|
-
(0, catch_error_1.default)(error);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
// ux.info('-- No new presets to create')
|
|
38
40
|
}
|
|
39
41
|
core_1.ux.action.stop();
|
|
40
42
|
}
|
|
@@ -13,21 +13,23 @@ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
|
13
13
|
async function loadRelations(dir) {
|
|
14
14
|
const relations = (0, read_file_1.default)('relations', dir);
|
|
15
15
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${relations.length} relations`));
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
16
|
+
if (relations && relations.length > 0) {
|
|
17
|
+
// Fetch existing relations
|
|
18
|
+
const existingRelations = await sdk_2.api.client.request((0, sdk_1.readRelations)());
|
|
19
|
+
const existingRelationKeys = new Set(existingRelations.map(relation => `${relation.collection}:${relation.field}:${relation.related_collection}`));
|
|
20
|
+
const relationsToAdd = relations.filter(relation => {
|
|
21
|
+
const key = `${relation.collection}:${relation.field}:${relation.related_collection}`;
|
|
22
|
+
if (existingRelationKeys.has(key)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}).map(relation => {
|
|
27
|
+
const cleanRelation = { ...relation };
|
|
28
|
+
delete cleanRelation.meta.id;
|
|
29
|
+
return cleanRelation;
|
|
30
|
+
});
|
|
31
|
+
await addRelations(relationsToAdd);
|
|
32
|
+
}
|
|
31
33
|
core_1.ux.action.stop();
|
|
32
34
|
}
|
|
33
35
|
exports.default = loadRelations;
|
|
@@ -11,50 +11,52 @@ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
|
11
11
|
async function loadRoles(dir) {
|
|
12
12
|
const roles = (0, read_file_1.default)('roles', dir);
|
|
13
13
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${roles.length} roles`));
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
14
|
+
if (roles && roles.length > 0) {
|
|
15
|
+
const { legacyAdminRoleId, newAdminRoleId } = await (0, get_role_ids_1.default)(dir);
|
|
16
|
+
// Fetch existing roles
|
|
17
|
+
const existingRoles = await sdk_2.api.client.request((0, sdk_1.readRoles)({
|
|
18
|
+
limit: -1,
|
|
19
|
+
}));
|
|
20
|
+
const existingRoleIds = new Set(existingRoles.map(role => role.id));
|
|
21
|
+
const existingRoleNames = new Set(existingRoles.map(role => role.name.toLowerCase()));
|
|
22
|
+
const cleanedUpRoles = roles
|
|
23
|
+
.filter(role => role.name !== 'Administrator') // Don't load legacy admin role
|
|
24
|
+
.filter(role => !existingRoleNames.has(role.name.toLowerCase())) // Filter out roles with existing names
|
|
25
|
+
.map(role => {
|
|
26
|
+
const r = { ...role };
|
|
27
|
+
delete r.users; // Alias field. User roles will be applied when the users are loaded.
|
|
28
|
+
delete r.parent; // We need to load all roles first
|
|
29
|
+
return r;
|
|
30
|
+
});
|
|
31
|
+
for await (const role of cleanedUpRoles) {
|
|
32
|
+
try {
|
|
33
|
+
if (existingRoleIds.has(role.id)) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
// Create new role
|
|
37
|
+
await sdk_2.api.client.request((0, sdk_1.createRole)(role));
|
|
38
|
+
// Add the new role ID and name to our sets of existing roles
|
|
39
|
+
existingRoleIds.add(role.id);
|
|
40
|
+
existingRoleNames.add(role.name.toLowerCase());
|
|
34
41
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
// Add the new role ID and name to our sets of existing roles
|
|
38
|
-
existingRoleIds.add(role.id);
|
|
39
|
-
existingRoleNames.add(role.name.toLowerCase());
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
(0, catch_error_1.default)(error);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
// Now add in any parent fields
|
|
46
|
-
const rolesWithParents = roles.filter(role => role.parent !== null);
|
|
47
|
-
for await (const role of rolesWithParents) {
|
|
48
|
-
try {
|
|
49
|
-
// Remap any roles where the parent ID is the default admin role
|
|
50
|
-
if (role.parent === legacyAdminRoleId) {
|
|
51
|
-
role.parent = newAdminRoleId;
|
|
42
|
+
catch (error) {
|
|
43
|
+
(0, catch_error_1.default)(error);
|
|
52
44
|
}
|
|
53
|
-
const simplifiedRole = { parent: role.parent };
|
|
54
|
-
await sdk_2.api.client.request((0, sdk_1.updateRole)(role.id, simplifiedRole));
|
|
55
45
|
}
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
// Now add in any parent fields
|
|
47
|
+
const rolesWithParents = roles.filter(role => role.parent !== null);
|
|
48
|
+
for await (const role of rolesWithParents) {
|
|
49
|
+
try {
|
|
50
|
+
// Remap any roles where the parent ID is the default admin role
|
|
51
|
+
if (role.parent === legacyAdminRoleId) {
|
|
52
|
+
role.parent = newAdminRoleId;
|
|
53
|
+
}
|
|
54
|
+
const simplifiedRole = { parent: role.parent };
|
|
55
|
+
await sdk_2.api.client.request((0, sdk_1.updateRole)(role.id, simplifiedRole));
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
(0, catch_error_1.default)(error);
|
|
59
|
+
}
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
core_1.ux.action.stop();
|
|
@@ -10,28 +10,30 @@ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
|
10
10
|
async function loadTranslations(dir) {
|
|
11
11
|
const translations = (0, read_file_1.default)('translations', dir);
|
|
12
12
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${translations.length} translations`));
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
if (translations && translations.length > 0) {
|
|
14
|
+
// Fetch existing translations
|
|
15
|
+
const existingTranslations = await sdk_2.api.client.request((0, sdk_1.readTranslations)({
|
|
16
|
+
limit: -1,
|
|
17
|
+
}));
|
|
18
|
+
const existingTranslationKeys = new Set(existingTranslations.map(t => `${t.language}_${t.key}`));
|
|
19
|
+
const newTranslations = translations.filter(t => {
|
|
20
|
+
const key = `${t.language}_${t.key}`;
|
|
21
|
+
if (existingTranslationKeys.has(key)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
});
|
|
26
|
+
if (newTranslations.length > 0) {
|
|
27
|
+
try {
|
|
28
|
+
await sdk_2.api.client.request((0, sdk_1.createTranslations)(newTranslations));
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
(0, catch_error_1.default)(error);
|
|
32
|
+
}
|
|
22
33
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (newTranslations.length > 0) {
|
|
26
|
-
try {
|
|
27
|
-
await sdk_2.api.client.request((0, sdk_1.createTranslations)(newTranslations));
|
|
34
|
+
else {
|
|
35
|
+
// ux.info('-- No new translations to create')
|
|
28
36
|
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
(0, catch_error_1.default)(error);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
// ux.info('-- No new translations to create')
|
|
35
37
|
}
|
|
36
38
|
core_1.ux.action.stop();
|
|
37
39
|
}
|
|
@@ -11,45 +11,56 @@ const read_file_1 = tslib_1.__importDefault(require("../utils/read-file"));
|
|
|
11
11
|
async function loadUsers(dir) {
|
|
12
12
|
const users = (0, read_file_1.default)('users', dir);
|
|
13
13
|
core_1.ux.action.start(core_1.ux.colorize(constants_1.DIRECTUS_PINK, `Loading ${users.length} users`));
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
14
|
+
if (users && users.length > 0) {
|
|
15
|
+
const { legacyAdminRoleId, newAdminRoleId } = await (0, get_role_ids_1.default)(dir);
|
|
16
|
+
const incomingUserEmails = users.map(user => user.email);
|
|
17
|
+
const incomingUserIds = users.map(user => user.id).filter(Boolean);
|
|
18
|
+
const existingUsers = await sdk_2.api.client.request((0, sdk_1.readUsers)({
|
|
19
|
+
filter: {
|
|
20
|
+
_or: [
|
|
21
|
+
{ email: { _in: incomingUserEmails } },
|
|
22
|
+
{ id: { _in: incomingUserIds } },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
limit: -1,
|
|
26
|
+
}));
|
|
27
|
+
const filteredUsers = users.map(user => {
|
|
28
|
+
// If the user is an admin, we need to change their role to the new admin role
|
|
29
|
+
const isAdmin = user.role === legacyAdminRoleId;
|
|
30
|
+
user.role = isAdmin ? newAdminRoleId : user.role;
|
|
31
|
+
// Delete the unneeded fields
|
|
32
|
+
delete user.last_page;
|
|
33
|
+
delete user.token;
|
|
34
|
+
delete user.policies;
|
|
35
|
+
// Delete passwords to prevent setting to *******
|
|
36
|
+
delete user.password;
|
|
37
|
+
return user;
|
|
38
|
+
});
|
|
39
|
+
for await (const user of filteredUsers) {
|
|
40
|
+
const existingUserWithSameId = existingUsers && Array.isArray(existingUsers)
|
|
41
|
+
? existingUsers.find(existing => existing.id === user.id)
|
|
42
|
+
: undefined;
|
|
43
|
+
const existingUserWithSameEmail = existingUsers && Array.isArray(existingUsers)
|
|
44
|
+
? existingUsers.find(existing => existing.email === user.email)
|
|
45
|
+
: undefined;
|
|
46
|
+
if (existingUserWithSameId) {
|
|
47
|
+
// Skip if there's an existing user with the same id
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (existingUserWithSameEmail) {
|
|
51
|
+
// Delete email if there's an existing user with the same email but different id
|
|
52
|
+
delete user.email;
|
|
53
|
+
}
|
|
54
|
+
if (user.email === null) {
|
|
55
|
+
// Delete email if it's null
|
|
56
|
+
delete user.email;
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
await sdk_2.api.client.request((0, sdk_1.createUser)(user));
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
(0, catch_error_1.default)(error);
|
|
63
|
+
}
|
|
53
64
|
}
|
|
54
65
|
}
|
|
55
66
|
core_1.ux.action.stop();
|
package/oclif.manifest.json
CHANGED