directus-template-cli 0.7.6 → 0.8.0-partials.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.
- package/README.md +134 -37
- package/dist/commands/apply.d.ts +5 -0
- package/dist/commands/apply.js +32 -68
- package/dist/commands/extract.d.ts +30 -0
- package/dist/commands/extract.js +14 -5
- package/dist/lib/extract/expand-deep-plan.d.ts +2 -0
- package/dist/lib/extract/expand-deep-plan.js +54 -0
- package/dist/lib/extract/expand-schema-plan.d.ts +2 -0
- package/dist/lib/extract/expand-schema-plan.js +55 -0
- package/dist/lib/extract/extract-assets.js +19 -6
- package/dist/lib/extract/extract-collections.d.ts +2 -1
- package/dist/lib/extract/extract-collections.js +5 -2
- package/dist/lib/extract/extract-content.d.ts +2 -1
- package/dist/lib/extract/extract-content.js +105 -12
- package/dist/lib/extract/extract-fields.d.ts +2 -1
- package/dist/lib/extract/extract-fields.js +5 -5
- package/dist/lib/extract/extract-relations.d.ts +2 -1
- package/dist/lib/extract/extract-relations.js +6 -4
- package/dist/lib/extract/index.d.ts +2 -1
- package/dist/lib/extract/index.js +67 -29
- package/dist/lib/load/apply-flags.d.ts +5 -2
- package/dist/lib/load/apply-flags.js +0 -50
- package/dist/lib/load/finalize-collections.d.ts +2 -0
- package/dist/lib/load/finalize-collections.js +28 -0
- package/dist/lib/load/finalize-fields.d.ts +2 -0
- package/dist/lib/load/finalize-fields.js +25 -0
- package/dist/lib/load/index.js +36 -19
- package/dist/lib/load/load-collections.d.ts +2 -1
- package/dist/lib/load/load-collections.js +17 -30
- package/dist/lib/load/load-data.d.ts +2 -1
- package/dist/lib/load/load-data.js +46 -34
- package/dist/lib/load/load-files.js +8 -8
- package/dist/lib/load/load-relations.d.ts +2 -1
- package/dist/lib/load/load-relations.js +17 -7
- package/dist/lib/template-plan/collections.d.ts +4 -0
- package/dist/lib/template-plan/collections.js +26 -0
- package/dist/lib/template-plan/flags.d.ts +18 -0
- package/dist/lib/template-plan/flags.js +61 -0
- package/dist/lib/template-plan/index.d.ts +16 -0
- package/dist/lib/template-plan/index.js +77 -0
- package/dist/lib/template-plan/junctions.d.ts +10 -0
- package/dist/lib/template-plan/junctions.js +19 -0
- package/dist/lib/template-plan/metadata-plan.d.ts +2 -0
- package/dist/lib/template-plan/metadata-plan.js +33 -0
- package/dist/lib/template-plan/metadata.d.ts +5 -0
- package/dist/lib/template-plan/metadata.js +39 -0
- package/dist/lib/template-plan/types.d.ts +34 -0
- package/dist/lib/template-plan/types.js +1 -0
- package/dist/services/github.js +1 -1
- package/oclif.manifest.json +173 -16
- package/package.json +1 -2
- package/dist/lib/load/update-required-fields.d.ts +0 -1
- package/dist/lib/load/update-required-fields.js +0 -20
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import catchError from '../utils/catch-error.js';
|
|
2
|
+
import { componentNames } from './flags.js';
|
|
3
|
+
function parseList(value) {
|
|
4
|
+
if (!value)
|
|
5
|
+
return undefined;
|
|
6
|
+
const raw = Array.isArray(value) ? value.join(',') : value;
|
|
7
|
+
const values = raw
|
|
8
|
+
.split(',')
|
|
9
|
+
.map((item) => item.trim())
|
|
10
|
+
.filter(Boolean);
|
|
11
|
+
return values.length > 0 ? values : undefined;
|
|
12
|
+
}
|
|
13
|
+
function hasPartialOnlyFlags(flags) {
|
|
14
|
+
return Boolean(flags.collections ||
|
|
15
|
+
flags.excludeCollections ||
|
|
16
|
+
flags.noAssets === true ||
|
|
17
|
+
flags.relationStrategy !== undefined ||
|
|
18
|
+
flags.allowBrokenRelations === true);
|
|
19
|
+
}
|
|
20
|
+
function hasScopingFlags(flags) {
|
|
21
|
+
return Boolean(flags.collections || flags.excludeCollections || flags.noAssets === true || hasComponentFlags(flags));
|
|
22
|
+
}
|
|
23
|
+
function hasComponentFlags(flags) {
|
|
24
|
+
return componentNames.some((component) => flags[component] !== undefined);
|
|
25
|
+
}
|
|
26
|
+
function buildComponents(flags, partial) {
|
|
27
|
+
const components = {};
|
|
28
|
+
const enabled = componentNames.filter((component) => flags[component] === true);
|
|
29
|
+
const disabled = componentNames.filter((component) => flags[component] === false);
|
|
30
|
+
if (!partial) {
|
|
31
|
+
for (const component of componentNames)
|
|
32
|
+
components[component] = true;
|
|
33
|
+
return components;
|
|
34
|
+
}
|
|
35
|
+
if (enabled.length > 0) {
|
|
36
|
+
for (const component of componentNames)
|
|
37
|
+
components[component] = enabled.includes(component);
|
|
38
|
+
}
|
|
39
|
+
else if (disabled.length > 0) {
|
|
40
|
+
for (const component of componentNames)
|
|
41
|
+
components[component] = !disabled.includes(component);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
for (const component of componentNames)
|
|
45
|
+
components[component] = true;
|
|
46
|
+
}
|
|
47
|
+
if (flags.noAssets)
|
|
48
|
+
components.files = false;
|
|
49
|
+
return components;
|
|
50
|
+
}
|
|
51
|
+
export function buildTemplatePlan(flags = {}) {
|
|
52
|
+
const collections = parseList(flags.collections);
|
|
53
|
+
const excludeCollections = parseList(flags.excludeCollections) || (flags.noAssets ? [] : undefined);
|
|
54
|
+
if (flags.noAssets && !excludeCollections?.includes('directus_files')) {
|
|
55
|
+
excludeCollections?.push('directus_files');
|
|
56
|
+
}
|
|
57
|
+
const partial = Boolean(flags.partial || hasComponentFlags(flags) || hasPartialOnlyFlags(flags));
|
|
58
|
+
const components = buildComponents(flags, partial);
|
|
59
|
+
if (!componentNames.some((component) => components[component])) {
|
|
60
|
+
catchError(new Error('At least one template component must be enabled.'), { fatal: true });
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
allowBrokenRelations: Boolean(flags.allowBrokenRelations),
|
|
64
|
+
collections,
|
|
65
|
+
components,
|
|
66
|
+
excludeCollections,
|
|
67
|
+
partial,
|
|
68
|
+
relationStrategy: (flags.relationStrategy ||
|
|
69
|
+
(partial ? (hasScopingFlags(flags) ? 'empty' : 'preserve') : 'deep')),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export * from './collections.js';
|
|
73
|
+
export * from './flags.js';
|
|
74
|
+
export * from './junctions.js';
|
|
75
|
+
export * from './metadata-plan.js';
|
|
76
|
+
export * from './metadata.js';
|
|
77
|
+
export * from './types.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TemplatePlan } from './types.js';
|
|
2
|
+
interface JunctionRelation {
|
|
3
|
+
collection: string;
|
|
4
|
+
meta?: {
|
|
5
|
+
junction_field?: null | string;
|
|
6
|
+
};
|
|
7
|
+
related_collection?: null | string;
|
|
8
|
+
}
|
|
9
|
+
export declare function getBrokenJunctionCollections(relations: JunctionRelation[], plan?: TemplatePlan): Set<string>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { includesCollection } from './collections.js';
|
|
2
|
+
// Directus sets meta.junction_field on both FK legs of an M2M to point to the other FK.
|
|
3
|
+
// Any collection appearing as `collection` on such a relation is a junction table.
|
|
4
|
+
// System collections (directus_*) always exist on every instance — never treat them as broken FK targets.
|
|
5
|
+
export function getBrokenJunctionCollections(relations, plan) {
|
|
6
|
+
if (!plan?.partial)
|
|
7
|
+
return new Set();
|
|
8
|
+
const junctionCollections = new Set(relations.filter((r) => r.meta?.junction_field).map((r) => r.collection));
|
|
9
|
+
const broken = new Set();
|
|
10
|
+
for (const junction of junctionCollections) {
|
|
11
|
+
const targets = relations
|
|
12
|
+
.filter((r) => r.collection === junction && r.related_collection)
|
|
13
|
+
.map((r) => r.related_collection);
|
|
14
|
+
if (targets.some((target) => !target.startsWith('directus_') && !includesCollection(target, plan))) {
|
|
15
|
+
broken.add(junction);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return broken;
|
|
19
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import catchError from '../utils/catch-error.js';
|
|
2
|
+
import { componentNames } from './flags.js';
|
|
3
|
+
function intersectCollections(scope, requested, available) {
|
|
4
|
+
if (requested && available) {
|
|
5
|
+
const collections = requested.filter((collection) => available.includes(collection));
|
|
6
|
+
if (collections.length === 0) {
|
|
7
|
+
catchError(new Error(`No requested ${scope} match this template`), { fatal: true });
|
|
8
|
+
}
|
|
9
|
+
return collections;
|
|
10
|
+
}
|
|
11
|
+
return requested || available;
|
|
12
|
+
}
|
|
13
|
+
function mergeExcludedCollections(requested, available) {
|
|
14
|
+
const values = [...(requested || []), ...(available || [])];
|
|
15
|
+
return values.length > 0 ? [...new Set(values)] : undefined;
|
|
16
|
+
}
|
|
17
|
+
export function applyMetadataToPlan(plan, metadata) {
|
|
18
|
+
if (!metadata)
|
|
19
|
+
return plan;
|
|
20
|
+
const components = { ...plan.components };
|
|
21
|
+
for (const component of componentNames) {
|
|
22
|
+
components[component] = components[component] && metadata.components[component];
|
|
23
|
+
}
|
|
24
|
+
const partial = metadata.partial || componentNames.some((component) => components[component] !== plan.components[component]);
|
|
25
|
+
return {
|
|
26
|
+
...plan,
|
|
27
|
+
collections: intersectCollections('collections', plan.collections, metadata.collections),
|
|
28
|
+
components,
|
|
29
|
+
excludeCollections: mergeExcludedCollections(plan.excludeCollections, metadata.excludedCollections),
|
|
30
|
+
partial,
|
|
31
|
+
schemaCollections: intersectCollections('schema collections', plan.schemaCollections, metadata.schemaCollections),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TemplateMetadata, TemplatePlan, TemplateWarning } from './types.js';
|
|
2
|
+
export declare function createTemplateMetadata(plan: TemplatePlan, warnings?: TemplateWarning[]): TemplateMetadata;
|
|
3
|
+
export declare function getTemplateMetadataPath(dir: string): string;
|
|
4
|
+
export declare function readTemplateMetadata(dir: string): TemplateMetadata | undefined;
|
|
5
|
+
export declare function writeTemplateMetadata(dir: string, plan: TemplatePlan, warnings?: TemplateWarning[]): Promise<void>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'pathe';
|
|
3
|
+
import catchError from '../utils/catch-error.js';
|
|
4
|
+
const META_FILE = 'template-meta.json';
|
|
5
|
+
export function createTemplateMetadata(plan, warnings = []) {
|
|
6
|
+
return {
|
|
7
|
+
allowBrokenRelations: plan.allowBrokenRelations,
|
|
8
|
+
collections: plan.collections,
|
|
9
|
+
components: plan.components,
|
|
10
|
+
excludedCollections: plan.excludeCollections,
|
|
11
|
+
partial: plan.partial,
|
|
12
|
+
relationStrategy: plan.relationStrategy,
|
|
13
|
+
schemaCollections: plan.schemaCollections,
|
|
14
|
+
version: 2,
|
|
15
|
+
warnings,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function getTemplateMetadataPath(dir) {
|
|
19
|
+
return path.join(dir, META_FILE);
|
|
20
|
+
}
|
|
21
|
+
export function readTemplateMetadata(dir) {
|
|
22
|
+
const filePath = getTemplateMetadataPath(dir);
|
|
23
|
+
if (!fs.existsSync(filePath))
|
|
24
|
+
return undefined;
|
|
25
|
+
try {
|
|
26
|
+
const metadata = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
27
|
+
if (metadata.version !== 2) {
|
|
28
|
+
catchError(new Error(`Unsupported template metadata version: ${metadata.version}`), { fatal: true });
|
|
29
|
+
}
|
|
30
|
+
return metadata;
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
catchError(error, { fatal: true });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export async function writeTemplateMetadata(dir, plan, warnings = []) {
|
|
37
|
+
const filePath = getTemplateMetadataPath(dir);
|
|
38
|
+
await fs.promises.writeFile(filePath, JSON.stringify(createTemplateMetadata(plan, warnings), null, 2));
|
|
39
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type RelationStrategy = 'deep' | 'empty' | 'preserve';
|
|
2
|
+
export interface TemplateComponents {
|
|
3
|
+
content: boolean;
|
|
4
|
+
dashboards: boolean;
|
|
5
|
+
extensions: boolean;
|
|
6
|
+
files: boolean;
|
|
7
|
+
flows: boolean;
|
|
8
|
+
permissions: boolean;
|
|
9
|
+
schema: boolean;
|
|
10
|
+
settings: boolean;
|
|
11
|
+
users: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface TemplatePlan {
|
|
14
|
+
allowBrokenRelations: boolean;
|
|
15
|
+
collections?: string[];
|
|
16
|
+
components: TemplateComponents;
|
|
17
|
+
excludeCollections?: string[];
|
|
18
|
+
partial: boolean;
|
|
19
|
+
relationStrategy: RelationStrategy;
|
|
20
|
+
schemaCollections?: string[];
|
|
21
|
+
}
|
|
22
|
+
export type TemplateWarning = {
|
|
23
|
+
collection: string;
|
|
24
|
+
count: number;
|
|
25
|
+
field: string;
|
|
26
|
+
relatedCollection: string;
|
|
27
|
+
type: 'excluded_relation';
|
|
28
|
+
};
|
|
29
|
+
export interface TemplateMetadata extends Omit<TemplatePlan, 'excludeCollections'> {
|
|
30
|
+
excludedCollections?: string[];
|
|
31
|
+
version: 2;
|
|
32
|
+
warnings: TemplateWarning[];
|
|
33
|
+
}
|
|
34
|
+
export type TemplateComponent = keyof TemplateComponents;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/services/github.js
CHANGED
|
@@ -114,7 +114,7 @@ export function createGitHub(token) {
|
|
|
114
114
|
});
|
|
115
115
|
if (!Array.isArray(rootContent))
|
|
116
116
|
return [];
|
|
117
|
-
const directories = rootContent.filter(item => item.type === 'dir');
|
|
117
|
+
const directories = rootContent.filter(item => item.type === 'dir' && !item.name.startsWith('.') && !item.name.startsWith('_'));
|
|
118
118
|
// Fetch package.json for each directory concurrently
|
|
119
119
|
const templateInfos = await Promise.all(directories.map(async (dir) => {
|
|
120
120
|
const packageJsonPath = joinPath(repo.path || '', dir.path, 'package.json');
|
package/oclif.manifest.json
CHANGED
|
@@ -10,14 +10,30 @@
|
|
|
10
10
|
"$ directus-template-cli@beta apply -p --directusUrl=\"http://localhost:8055\" --directusToken=\"admin-token-here\" --templateLocation=\"./my-template\" --templateType=\"local\" --partial --no-content --no-users"
|
|
11
11
|
],
|
|
12
12
|
"flags": {
|
|
13
|
+
"allowBrokenRelations": {
|
|
14
|
+
"aliases": [
|
|
15
|
+
"allow-broken-relations"
|
|
16
|
+
],
|
|
17
|
+
"description": "Allow intentionally incomplete relation references",
|
|
18
|
+
"name": "allowBrokenRelations",
|
|
19
|
+
"allowNo": false,
|
|
20
|
+
"type": "boolean"
|
|
21
|
+
},
|
|
22
|
+
"collections": {
|
|
23
|
+
"description": "Only include these comma-separated collections",
|
|
24
|
+
"name": "collections",
|
|
25
|
+
"hasDynamicHelp": false,
|
|
26
|
+
"multiple": false,
|
|
27
|
+
"type": "option"
|
|
28
|
+
},
|
|
13
29
|
"content": {
|
|
14
|
-
"description": "
|
|
30
|
+
"description": "Include content/data",
|
|
15
31
|
"name": "content",
|
|
16
32
|
"allowNo": true,
|
|
17
33
|
"type": "boolean"
|
|
18
34
|
},
|
|
19
35
|
"dashboards": {
|
|
20
|
-
"description": "
|
|
36
|
+
"description": "Include dashboards and panels",
|
|
21
37
|
"name": "dashboards",
|
|
22
38
|
"allowNo": true,
|
|
23
39
|
"type": "boolean"
|
|
@@ -49,24 +65,43 @@
|
|
|
49
65
|
"allowNo": false,
|
|
50
66
|
"type": "boolean"
|
|
51
67
|
},
|
|
68
|
+
"excludeCollections": {
|
|
69
|
+
"aliases": [
|
|
70
|
+
"exclude-collections"
|
|
71
|
+
],
|
|
72
|
+
"description": "Exclude these comma-separated collections",
|
|
73
|
+
"name": "excludeCollections",
|
|
74
|
+
"hasDynamicHelp": false,
|
|
75
|
+
"multiple": false,
|
|
76
|
+
"type": "option"
|
|
77
|
+
},
|
|
52
78
|
"extensions": {
|
|
53
|
-
"description": "
|
|
79
|
+
"description": "Include extensions",
|
|
54
80
|
"name": "extensions",
|
|
55
81
|
"allowNo": true,
|
|
56
82
|
"type": "boolean"
|
|
57
83
|
},
|
|
58
84
|
"files": {
|
|
59
|
-
"description": "
|
|
85
|
+
"description": "Include files, folders, and assets",
|
|
60
86
|
"name": "files",
|
|
61
87
|
"allowNo": true,
|
|
62
88
|
"type": "boolean"
|
|
63
89
|
},
|
|
64
90
|
"flows": {
|
|
65
|
-
"description": "
|
|
91
|
+
"description": "Include flows and operations",
|
|
66
92
|
"name": "flows",
|
|
67
93
|
"allowNo": true,
|
|
68
94
|
"type": "boolean"
|
|
69
95
|
},
|
|
96
|
+
"noAssets": {
|
|
97
|
+
"aliases": [
|
|
98
|
+
"no-assets"
|
|
99
|
+
],
|
|
100
|
+
"description": "Shorthand for --no-files and --exclude-collections directus_files",
|
|
101
|
+
"name": "noAssets",
|
|
102
|
+
"allowNo": false,
|
|
103
|
+
"type": "boolean"
|
|
104
|
+
},
|
|
70
105
|
"noExit": {
|
|
71
106
|
"hidden": true,
|
|
72
107
|
"name": "noExit",
|
|
@@ -74,19 +109,15 @@
|
|
|
74
109
|
"type": "boolean"
|
|
75
110
|
},
|
|
76
111
|
"partial": {
|
|
77
|
-
"
|
|
78
|
-
"programmatic"
|
|
79
|
-
],
|
|
80
|
-
"description": "Enable partial template application (all components enabled by default)",
|
|
112
|
+
"description": "Enable partial template mode",
|
|
81
113
|
"name": "partial",
|
|
82
|
-
"summary": "Enable partial template
|
|
114
|
+
"summary": "Enable partial template mode",
|
|
83
115
|
"allowNo": false,
|
|
84
116
|
"type": "boolean"
|
|
85
117
|
},
|
|
86
118
|
"permissions": {
|
|
87
|
-
"description": "
|
|
119
|
+
"description": "Include permissions, roles, policies, and access",
|
|
88
120
|
"name": "permissions",
|
|
89
|
-
"summary": "Load permissions (roles, policies, access, permissions)",
|
|
90
121
|
"allowNo": true,
|
|
91
122
|
"type": "boolean"
|
|
92
123
|
},
|
|
@@ -98,14 +129,29 @@
|
|
|
98
129
|
"allowNo": false,
|
|
99
130
|
"type": "boolean"
|
|
100
131
|
},
|
|
132
|
+
"relationStrategy": {
|
|
133
|
+
"aliases": [
|
|
134
|
+
"relation-strategy"
|
|
135
|
+
],
|
|
136
|
+
"description": "How to handle relations to omitted data",
|
|
137
|
+
"name": "relationStrategy",
|
|
138
|
+
"hasDynamicHelp": false,
|
|
139
|
+
"multiple": false,
|
|
140
|
+
"options": [
|
|
141
|
+
"empty",
|
|
142
|
+
"preserve",
|
|
143
|
+
"deep"
|
|
144
|
+
],
|
|
145
|
+
"type": "option"
|
|
146
|
+
},
|
|
101
147
|
"schema": {
|
|
102
|
-
"description": "
|
|
148
|
+
"description": "Include schema, collections, fields, and relations",
|
|
103
149
|
"name": "schema",
|
|
104
150
|
"allowNo": true,
|
|
105
151
|
"type": "boolean"
|
|
106
152
|
},
|
|
107
153
|
"settings": {
|
|
108
|
-
"description": "
|
|
154
|
+
"description": "Include settings, translations, and presets",
|
|
109
155
|
"name": "settings",
|
|
110
156
|
"allowNo": true,
|
|
111
157
|
"type": "boolean"
|
|
@@ -168,7 +214,7 @@
|
|
|
168
214
|
"type": "option"
|
|
169
215
|
},
|
|
170
216
|
"users": {
|
|
171
|
-
"description": "
|
|
217
|
+
"description": "Include users",
|
|
172
218
|
"name": "users",
|
|
173
219
|
"allowNo": true,
|
|
174
220
|
"type": "boolean"
|
|
@@ -244,6 +290,13 @@
|
|
|
244
290
|
"allowNo": false,
|
|
245
291
|
"type": "boolean"
|
|
246
292
|
},
|
|
293
|
+
"partial": {
|
|
294
|
+
"description": "Enable partial template mode",
|
|
295
|
+
"name": "partial",
|
|
296
|
+
"summary": "Enable partial template mode",
|
|
297
|
+
"allowNo": false,
|
|
298
|
+
"type": "boolean"
|
|
299
|
+
},
|
|
247
300
|
"programmatic": {
|
|
248
301
|
"char": "p",
|
|
249
302
|
"description": "Run in programmatic mode (non-interactive) for use cases such as CI/CD pipelines.",
|
|
@@ -301,6 +354,110 @@
|
|
|
301
354
|
"hasDynamicHelp": false,
|
|
302
355
|
"multiple": false,
|
|
303
356
|
"type": "option"
|
|
357
|
+
},
|
|
358
|
+
"content": {
|
|
359
|
+
"description": "Include content/data",
|
|
360
|
+
"name": "content",
|
|
361
|
+
"allowNo": true,
|
|
362
|
+
"type": "boolean"
|
|
363
|
+
},
|
|
364
|
+
"dashboards": {
|
|
365
|
+
"description": "Include dashboards and panels",
|
|
366
|
+
"name": "dashboards",
|
|
367
|
+
"allowNo": true,
|
|
368
|
+
"type": "boolean"
|
|
369
|
+
},
|
|
370
|
+
"extensions": {
|
|
371
|
+
"description": "Include extensions",
|
|
372
|
+
"name": "extensions",
|
|
373
|
+
"allowNo": true,
|
|
374
|
+
"type": "boolean"
|
|
375
|
+
},
|
|
376
|
+
"files": {
|
|
377
|
+
"description": "Include files, folders, and assets",
|
|
378
|
+
"name": "files",
|
|
379
|
+
"allowNo": true,
|
|
380
|
+
"type": "boolean"
|
|
381
|
+
},
|
|
382
|
+
"flows": {
|
|
383
|
+
"description": "Include flows and operations",
|
|
384
|
+
"name": "flows",
|
|
385
|
+
"allowNo": true,
|
|
386
|
+
"type": "boolean"
|
|
387
|
+
},
|
|
388
|
+
"permissions": {
|
|
389
|
+
"description": "Include permissions, roles, policies, and access",
|
|
390
|
+
"name": "permissions",
|
|
391
|
+
"allowNo": true,
|
|
392
|
+
"type": "boolean"
|
|
393
|
+
},
|
|
394
|
+
"schema": {
|
|
395
|
+
"description": "Include schema, collections, fields, and relations",
|
|
396
|
+
"name": "schema",
|
|
397
|
+
"allowNo": true,
|
|
398
|
+
"type": "boolean"
|
|
399
|
+
},
|
|
400
|
+
"settings": {
|
|
401
|
+
"description": "Include settings, translations, and presets",
|
|
402
|
+
"name": "settings",
|
|
403
|
+
"allowNo": true,
|
|
404
|
+
"type": "boolean"
|
|
405
|
+
},
|
|
406
|
+
"users": {
|
|
407
|
+
"description": "Include users",
|
|
408
|
+
"name": "users",
|
|
409
|
+
"allowNo": true,
|
|
410
|
+
"type": "boolean"
|
|
411
|
+
},
|
|
412
|
+
"allowBrokenRelations": {
|
|
413
|
+
"aliases": [
|
|
414
|
+
"allow-broken-relations"
|
|
415
|
+
],
|
|
416
|
+
"description": "Allow intentionally incomplete relation references",
|
|
417
|
+
"name": "allowBrokenRelations",
|
|
418
|
+
"allowNo": false,
|
|
419
|
+
"type": "boolean"
|
|
420
|
+
},
|
|
421
|
+
"collections": {
|
|
422
|
+
"description": "Only include these comma-separated collections",
|
|
423
|
+
"name": "collections",
|
|
424
|
+
"hasDynamicHelp": false,
|
|
425
|
+
"multiple": false,
|
|
426
|
+
"type": "option"
|
|
427
|
+
},
|
|
428
|
+
"excludeCollections": {
|
|
429
|
+
"aliases": [
|
|
430
|
+
"exclude-collections"
|
|
431
|
+
],
|
|
432
|
+
"description": "Exclude these comma-separated collections",
|
|
433
|
+
"name": "excludeCollections",
|
|
434
|
+
"hasDynamicHelp": false,
|
|
435
|
+
"multiple": false,
|
|
436
|
+
"type": "option"
|
|
437
|
+
},
|
|
438
|
+
"noAssets": {
|
|
439
|
+
"aliases": [
|
|
440
|
+
"no-assets"
|
|
441
|
+
],
|
|
442
|
+
"description": "Shorthand for --no-files and --exclude-collections directus_files",
|
|
443
|
+
"name": "noAssets",
|
|
444
|
+
"allowNo": false,
|
|
445
|
+
"type": "boolean"
|
|
446
|
+
},
|
|
447
|
+
"relationStrategy": {
|
|
448
|
+
"aliases": [
|
|
449
|
+
"relation-strategy"
|
|
450
|
+
],
|
|
451
|
+
"description": "How to handle relations to omitted data",
|
|
452
|
+
"name": "relationStrategy",
|
|
453
|
+
"hasDynamicHelp": false,
|
|
454
|
+
"multiple": false,
|
|
455
|
+
"options": [
|
|
456
|
+
"empty",
|
|
457
|
+
"preserve",
|
|
458
|
+
"deep"
|
|
459
|
+
],
|
|
460
|
+
"type": "option"
|
|
304
461
|
}
|
|
305
462
|
},
|
|
306
463
|
"hasDynamicHelp": false,
|
|
@@ -401,5 +558,5 @@
|
|
|
401
558
|
]
|
|
402
559
|
}
|
|
403
560
|
},
|
|
404
|
-
"version": "0.
|
|
561
|
+
"version": "0.8.0-partials.0"
|
|
405
562
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "directus-template-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0-partials.0",
|
|
4
4
|
"description": "CLI Utility for applying templates to a Directus instance.",
|
|
5
5
|
"author": "bryantgillespie @bryantgillespie",
|
|
6
6
|
"type": "module",
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"defu": "^6.1.4",
|
|
33
33
|
"dotenv": "^16.4.7",
|
|
34
34
|
"execa": "9.5.2",
|
|
35
|
-
"formdata-node": "^6.0.3",
|
|
36
35
|
"giget": "^2.0.0",
|
|
37
36
|
"glob": "^11.0.1",
|
|
38
37
|
"log-update": "^6.1.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function updateRequiredFields(dir: string): Promise<void>;
|
|
@@ -1,20 +0,0 @@
|
|
|
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`));
|
|
11
|
-
for await (const field of fieldsToUpdate) {
|
|
12
|
-
try {
|
|
13
|
-
await api.client.request(updateField(field.collection, field.field, { meta: { ...field.meta }, schema: { ...field.schema } }));
|
|
14
|
-
}
|
|
15
|
-
catch (error) {
|
|
16
|
-
catchError(error);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
ux.action.stop();
|
|
20
|
-
}
|