@directus/extensions-sdk 9.20.3 → 9.21.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/dist/cjs/cli/commands/add.d.ts +2 -0
- package/dist/cjs/cli/commands/add.js +242 -0
- package/dist/cjs/cli/commands/build.d.ts +1 -1
- package/dist/cjs/cli/commands/build.js +169 -43
- package/dist/cjs/cli/commands/create.d.ts +2 -2
- package/dist/cjs/cli/commands/create.js +66 -47
- package/dist/cjs/cli/commands/helpers/copy-template.d.ts +4 -0
- package/dist/cjs/cli/commands/helpers/copy-template.js +53 -0
- package/dist/cjs/cli/commands/helpers/generate-bundle-entrypoint.d.ts +3 -0
- package/dist/cjs/cli/commands/helpers/generate-bundle-entrypoint.js +24 -0
- package/dist/cjs/cli/commands/helpers/get-extension-dev-deps.d.ts +4 -0
- package/dist/cjs/cli/commands/helpers/get-extension-dev-deps.js +27 -0
- package/dist/cjs/cli/commands/helpers/load-config.d.ts +3 -0
- package/dist/cjs/cli/{utils → commands/helpers}/load-config.js +0 -0
- package/dist/cjs/cli/commands/helpers/validate-cli-options.d.ts +4 -0
- package/dist/cjs/cli/commands/helpers/validate-cli-options.js +39 -0
- package/dist/cjs/cli/run.js +3 -1
- package/dist/cjs/cli/types.d.ts +5 -5
- package/dist/cjs/cli/utils/detect-json-indent.d.ts +2 -0
- package/dist/cjs/cli/utils/detect-json-indent.js +14 -0
- package/dist/cjs/cli/utils/get-package-manager-agent.d.ts +5 -0
- package/dist/cjs/cli/utils/get-package-manager-agent.js +15 -0
- package/dist/cjs/cli/utils/get-package-manager-agent.test.d.ts +2 -0
- package/dist/cjs/cli/utils/get-package-manager-agent.test.js +24 -0
- package/dist/cjs/cli/utils/get-package-manager.d.ts +5 -0
- package/dist/cjs/cli/utils/get-package-manager.js +20 -0
- package/dist/cjs/cli/utils/get-package-manager.test.d.ts +2 -0
- package/dist/cjs/cli/utils/get-package-manager.test.js +42 -0
- package/dist/cjs/cli/utils/get-sdk-version.d.ts +2 -0
- package/dist/cjs/cli/utils/get-sdk-version.js +7 -0
- package/dist/cjs/cli/utils/get-template-path.d.ts +2 -0
- package/dist/cjs/cli/utils/get-template-path.js +10 -0
- package/dist/cjs/cli/utils/try-parse-json.d.ts +3 -0
- package/dist/cjs/cli/utils/try-parse-json.js +11 -0
- package/dist/esm/cli/commands/add.d.ts +2 -0
- package/dist/esm/cli/commands/add.js +236 -0
- package/dist/esm/cli/commands/build.d.ts +1 -1
- package/dist/esm/cli/commands/build.js +167 -41
- package/dist/esm/cli/commands/create.d.ts +2 -2
- package/dist/esm/cli/commands/create.js +66 -47
- package/dist/esm/cli/commands/helpers/copy-template.d.ts +4 -0
- package/dist/esm/cli/commands/helpers/copy-template.js +47 -0
- package/dist/esm/cli/commands/helpers/generate-bundle-entrypoint.d.ts +3 -0
- package/dist/esm/cli/commands/helpers/generate-bundle-entrypoint.js +18 -0
- package/dist/esm/cli/commands/helpers/get-extension-dev-deps.d.ts +4 -0
- package/dist/esm/cli/commands/helpers/get-extension-dev-deps.js +21 -0
- package/dist/esm/cli/commands/helpers/load-config.d.ts +3 -0
- package/dist/esm/cli/{utils → commands/helpers}/load-config.js +0 -0
- package/dist/esm/cli/commands/helpers/validate-cli-options.d.ts +4 -0
- package/dist/esm/cli/commands/helpers/validate-cli-options.js +34 -0
- package/dist/esm/cli/run.js +3 -1
- package/dist/esm/cli/types.d.ts +5 -5
- package/dist/esm/cli/utils/detect-json-indent.d.ts +2 -0
- package/dist/esm/cli/utils/detect-json-indent.js +11 -0
- package/dist/esm/cli/utils/get-package-manager-agent.d.ts +5 -0
- package/dist/esm/cli/utils/get-package-manager-agent.js +12 -0
- package/dist/esm/cli/utils/get-package-manager-agent.test.d.ts +2 -0
- package/dist/esm/cli/utils/get-package-manager-agent.test.js +19 -0
- package/dist/esm/cli/utils/get-package-manager.d.ts +5 -0
- package/dist/esm/cli/utils/get-package-manager.js +14 -0
- package/dist/esm/cli/utils/get-package-manager.test.d.ts +2 -0
- package/dist/esm/cli/utils/get-package-manager.test.js +37 -0
- package/dist/esm/cli/utils/get-sdk-version.d.ts +2 -0
- package/dist/esm/cli/utils/get-sdk-version.js +4 -0
- package/dist/esm/cli/utils/get-template-path.d.ts +2 -0
- package/dist/esm/cli/utils/get-template-path.js +4 -0
- package/dist/esm/cli/utils/try-parse-json.d.ts +3 -0
- package/dist/esm/cli/utils/try-parse-json.js +8 -0
- package/package.json +51 -21
- package/templates/common/{javascript → common/config}/_gitignore +0 -0
- package/templates/common/typescript/{tsconfig.json → config/tsconfig.json} +0 -0
- package/templates/display/javascript/{src → source}/display.vue +0 -0
- package/templates/display/javascript/{src → source}/index.js +0 -0
- package/templates/display/typescript/{src → source}/display.vue +0 -0
- package/templates/display/typescript/{src → source}/index.ts +0 -0
- package/templates/display/typescript/{src → source}/shims.d.ts +0 -0
- package/templates/endpoint/javascript/{src → source}/index.js +0 -0
- package/templates/endpoint/typescript/{src → source}/index.ts +0 -0
- package/templates/hook/javascript/{src → source}/index.js +0 -0
- package/templates/hook/typescript/{src → source}/index.ts +0 -0
- package/templates/interface/javascript/{src → source}/index.js +0 -0
- package/templates/interface/javascript/{src → source}/interface.vue +0 -0
- package/templates/interface/typescript/{src → source}/index.ts +0 -0
- package/templates/interface/typescript/{src → source}/interface.vue +0 -0
- package/templates/interface/typescript/{src → source}/shims.d.ts +0 -0
- package/templates/layout/javascript/{src → source}/index.js +0 -0
- package/templates/layout/javascript/{src → source}/layout.vue +0 -0
- package/templates/layout/typescript/{src → source}/index.ts +0 -0
- package/templates/layout/typescript/{src → source}/layout.vue +0 -0
- package/templates/layout/typescript/{src → source}/shims.d.ts +0 -0
- package/templates/module/javascript/{src → source}/index.js +0 -0
- package/templates/module/javascript/{src → source}/module.vue +0 -0
- package/templates/module/typescript/{src → source}/index.ts +0 -0
- package/templates/module/typescript/{src → source}/module.vue +0 -0
- package/templates/module/typescript/{src → source}/shims.d.ts +0 -0
- package/templates/operation/javascript/{src → source}/api.js +0 -0
- package/templates/operation/javascript/{src → source}/app.js +0 -0
- package/templates/operation/typescript/{src → source}/api.ts +0 -0
- package/templates/operation/typescript/{src → source}/app.ts +0 -0
- package/templates/operation/typescript/{src → source}/shims.d.ts +0 -0
- package/templates/panel/javascript/{src → source}/index.js +0 -0
- package/templates/panel/javascript/{src → source}/panel.vue +0 -0
- package/templates/panel/typescript/{src → source}/index.ts +0 -0
- package/templates/panel/typescript/{src → source}/panel.vue +0 -0
- package/templates/panel/typescript/{src → source}/shims.d.ts +0 -0
- package/.editorconfig +0 -12
- package/cli.d.ts +0 -1
- package/dist/cjs/cli/commands/build.d.ts.map +0 -1
- package/dist/cjs/cli/commands/create.d.ts.map +0 -1
- package/dist/cjs/cli/index.d.ts.map +0 -1
- package/dist/cjs/cli/run.d.ts.map +0 -1
- package/dist/cjs/cli/types.d.ts.map +0 -1
- package/dist/cjs/cli/utils/get-package-version.d.ts.map +0 -1
- package/dist/cjs/cli/utils/languages.d.ts.map +0 -1
- package/dist/cjs/cli/utils/load-config.d.ts +0 -3
- package/dist/cjs/cli/utils/load-config.d.ts.map +0 -1
- package/dist/cjs/cli/utils/logger.d.ts.map +0 -1
- package/dist/cjs/cli/utils/rename-map.d.ts +0 -2
- package/dist/cjs/cli/utils/rename-map.d.ts.map +0 -1
- package/dist/cjs/cli/utils/rename-map.js +0 -23
- package/dist/cjs/cli/utils/to-object.d.ts +0 -2
- package/dist/cjs/cli/utils/to-object.d.ts.map +0 -1
- package/dist/cjs/cli/utils/to-object.js +0 -17
- package/dist/cjs/index.d.ts.map +0 -1
- package/dist/esm/cli/commands/build.d.ts.map +0 -1
- package/dist/esm/cli/commands/create.d.ts.map +0 -1
- package/dist/esm/cli/index.d.ts.map +0 -1
- package/dist/esm/cli/run.d.ts.map +0 -1
- package/dist/esm/cli/types.d.ts.map +0 -1
- package/dist/esm/cli/utils/get-package-version.d.ts.map +0 -1
- package/dist/esm/cli/utils/languages.d.ts.map +0 -1
- package/dist/esm/cli/utils/load-config.d.ts +0 -3
- package/dist/esm/cli/utils/load-config.d.ts.map +0 -1
- package/dist/esm/cli/utils/logger.d.ts.map +0 -1
- package/dist/esm/cli/utils/rename-map.d.ts +0 -2
- package/dist/esm/cli/utils/rename-map.d.ts.map +0 -1
- package/dist/esm/cli/utils/rename-map.js +0 -17
- package/dist/esm/cli/utils/to-object.d.ts +0 -2
- package/dist/esm/cli/utils/to-object.d.ts.map +0 -1
- package/dist/esm/cli/utils/to-object.js +0 -14
- package/dist/esm/index.d.ts.map +0 -1
- package/src/cli/commands/build.ts +0 -493
- package/src/cli/commands/create.ts +0 -135
- package/src/cli/index.ts +0 -4
- package/src/cli/run.ts +0 -32
- package/src/cli/types.ts +0 -12
- package/src/cli/utils/get-package-version.ts +0 -9
- package/src/cli/utils/languages.ts +0 -26
- package/src/cli/utils/load-config.ts +0 -21
- package/src/cli/utils/logger.ts +0 -25
- package/src/cli/utils/rename-map.ts +0 -20
- package/src/cli/utils/to-object.ts +0 -16
- package/src/index.ts +0 -23
- package/templates/common/typescript/_gitignore +0 -3
- package/tsconfig.json +0 -30
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import fse from 'fs-extra';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import { log } from '../utils/logger';
|
|
6
|
+
import { isIn, isTypeIn, validateExtensionManifest } from '@directus/shared/utils';
|
|
7
|
+
import { pathToRelativeUrl } from '@directus/shared/utils/node';
|
|
8
|
+
import { EXTENSION_LANGUAGES, EXTENSION_NAME_REGEX, EXTENSION_PKG_KEY, EXTENSION_TYPES, HYBRID_EXTENSION_TYPES, } from '@directus/shared/constants';
|
|
9
|
+
import { getLanguageFromPath, isLanguage, languageToShort } from '../utils/languages';
|
|
10
|
+
import getExtensionDevDeps from './helpers/get-extension-dev-deps';
|
|
11
|
+
import execa from 'execa';
|
|
12
|
+
import ora from 'ora';
|
|
13
|
+
import copyTemplate from './helpers/copy-template';
|
|
14
|
+
import detectJsonIndent from '../utils/detect-json-indent';
|
|
15
|
+
import getPackageManager from '../utils/get-package-manager';
|
|
16
|
+
export default async function add() {
|
|
17
|
+
var _a, _b;
|
|
18
|
+
const extensionPath = process.cwd();
|
|
19
|
+
const packagePath = path.resolve('package.json');
|
|
20
|
+
if (!(await fse.pathExists(packagePath))) {
|
|
21
|
+
log(`Current directory is not a valid package.`, 'error');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const extensionManifestFile = await fse.readFile(packagePath, 'utf8');
|
|
25
|
+
const extensionManifest = JSON.parse(extensionManifestFile);
|
|
26
|
+
const indent = detectJsonIndent(extensionManifestFile);
|
|
27
|
+
if (!validateExtensionManifest(extensionManifest)) {
|
|
28
|
+
log(`Current directory is not a valid Directus extension.`, 'error');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const extensionOptions = extensionManifest[EXTENSION_PKG_KEY];
|
|
32
|
+
if (extensionOptions.type === 'pack') {
|
|
33
|
+
log(`Adding entries to extensions with type ${chalk.bold('pack')} is not currently supported.`, 'error');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
const sourceExists = await fse.pathExists(path.resolve('src'));
|
|
37
|
+
if (extensionOptions.type === 'bundle') {
|
|
38
|
+
const { type, name, language, alternativeSource } = await inquirer.prompt([
|
|
39
|
+
{
|
|
40
|
+
type: 'list',
|
|
41
|
+
name: 'type',
|
|
42
|
+
message: 'Choose the extension type',
|
|
43
|
+
choices: EXTENSION_TYPES,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
type: 'input',
|
|
47
|
+
name: 'name',
|
|
48
|
+
message: 'Choose a name for the entry',
|
|
49
|
+
validate: (name) => (name.length === 0 ? 'Entry name can not be empty.' : true),
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: 'list',
|
|
53
|
+
name: 'language',
|
|
54
|
+
message: 'Choose the language to use',
|
|
55
|
+
choices: EXTENSION_LANGUAGES,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
type: 'input',
|
|
59
|
+
name: 'alternativeSource',
|
|
60
|
+
message: 'Specify the path to the extension source',
|
|
61
|
+
when: !sourceExists && extensionOptions.entries.length > 0,
|
|
62
|
+
},
|
|
63
|
+
]);
|
|
64
|
+
const spinner = ora(chalk.bold('Modifying Directus extension...')).start();
|
|
65
|
+
const source = alternativeSource !== null && alternativeSource !== void 0 ? alternativeSource : 'src';
|
|
66
|
+
const sourcePath = path.resolve(source, name);
|
|
67
|
+
await fse.ensureDir(sourcePath);
|
|
68
|
+
await copyTemplate(type, extensionPath, sourcePath, language);
|
|
69
|
+
const newEntries = [
|
|
70
|
+
...extensionOptions.entries,
|
|
71
|
+
isIn(type, HYBRID_EXTENSION_TYPES)
|
|
72
|
+
? {
|
|
73
|
+
type,
|
|
74
|
+
name,
|
|
75
|
+
source: {
|
|
76
|
+
app: `${pathToRelativeUrl(source)}/${name}/app.${languageToShort(language)}`,
|
|
77
|
+
api: `${pathToRelativeUrl(source)}/${name}/api.${languageToShort(language)}`,
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
: {
|
|
81
|
+
type,
|
|
82
|
+
name,
|
|
83
|
+
source: `${pathToRelativeUrl(source)}/${name}/index.${languageToShort(language)}`,
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
const newExtensionOptions = { ...extensionOptions, entries: newEntries };
|
|
87
|
+
const newExtensionManifest = {
|
|
88
|
+
...extensionManifest,
|
|
89
|
+
[EXTENSION_PKG_KEY]: newExtensionOptions,
|
|
90
|
+
devDependencies: await getExtensionDevDeps(newEntries.map((entry) => entry.type), getLanguageFromEntries(newEntries)),
|
|
91
|
+
};
|
|
92
|
+
await fse.writeJSON(packagePath, newExtensionManifest, { spaces: indent !== null && indent !== void 0 ? indent : '\t' });
|
|
93
|
+
const packageManager = getPackageManager();
|
|
94
|
+
await execa(packageManager, ['install'], { cwd: extensionPath });
|
|
95
|
+
spinner.succeed(chalk.bold('Done'));
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
const { proceed } = await inquirer.prompt([
|
|
99
|
+
{
|
|
100
|
+
type: 'confirm',
|
|
101
|
+
name: 'proceed',
|
|
102
|
+
message: 'This will convert your extension to a bundle. Do you want to proceed?',
|
|
103
|
+
},
|
|
104
|
+
]);
|
|
105
|
+
if (!proceed) {
|
|
106
|
+
log(`Extension has not been modified.`, 'info');
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
const oldName = (_b = (_a = extensionManifest.name.match(EXTENSION_NAME_REGEX)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : extensionManifest.name;
|
|
110
|
+
const { type, name, language, convertName, extensionName, alternativeSource } = await inquirer.prompt([
|
|
111
|
+
{
|
|
112
|
+
type: 'list',
|
|
113
|
+
name: 'type',
|
|
114
|
+
message: 'Choose the extension type',
|
|
115
|
+
choices: EXTENSION_TYPES,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: 'input',
|
|
119
|
+
name: 'name',
|
|
120
|
+
message: 'Choose a name for the entry',
|
|
121
|
+
validate: (name) => (name.length === 0 ? 'Entry name can not be empty.' : true),
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
type: 'list',
|
|
125
|
+
name: 'language',
|
|
126
|
+
message: 'Choose the language to use',
|
|
127
|
+
choices: EXTENSION_LANGUAGES,
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
type: 'input',
|
|
131
|
+
name: 'convertName',
|
|
132
|
+
message: 'Choose a name for the extension that is converted to an entry',
|
|
133
|
+
default: oldName,
|
|
134
|
+
validate: (name) => (name.length === 0 ? 'Entry name can not be empty.' : true),
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
type: 'input',
|
|
138
|
+
name: 'extensionName',
|
|
139
|
+
message: 'Choose a name for the extension',
|
|
140
|
+
default: ({ convertName }) => (convertName !== oldName ? oldName : null),
|
|
141
|
+
validate: (name) => (name.length === 0 ? 'Extension name can not be empty.' : true),
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
type: 'input',
|
|
145
|
+
name: 'alternativeSource',
|
|
146
|
+
message: 'Specify the path to the extension source',
|
|
147
|
+
when: !sourceExists,
|
|
148
|
+
},
|
|
149
|
+
]);
|
|
150
|
+
const spinner = ora(chalk.bold('Modifying Directus extension...')).start();
|
|
151
|
+
const source = alternativeSource !== null && alternativeSource !== void 0 ? alternativeSource : 'src';
|
|
152
|
+
const convertSourcePath = path.resolve(source, convertName);
|
|
153
|
+
const entrySourcePath = path.resolve(source, name);
|
|
154
|
+
const convertFiles = await fse.readdir(source);
|
|
155
|
+
await Promise.all(convertFiles.map((file) => fse.move(path.resolve(source, file), path.join(convertSourcePath, file))));
|
|
156
|
+
await fse.ensureDir(entrySourcePath);
|
|
157
|
+
await copyTemplate(type, extensionPath, entrySourcePath, language);
|
|
158
|
+
const toConvertSourceUrl = (entrypoint) => path.posix.join(pathToRelativeUrl(source), convertName, path.posix.relative(source, entrypoint));
|
|
159
|
+
const entries = [
|
|
160
|
+
isTypeIn(extensionOptions, HYBRID_EXTENSION_TYPES)
|
|
161
|
+
? {
|
|
162
|
+
type: extensionOptions.type,
|
|
163
|
+
name: convertName,
|
|
164
|
+
source: {
|
|
165
|
+
app: toConvertSourceUrl(extensionOptions.source.app),
|
|
166
|
+
api: toConvertSourceUrl(extensionOptions.source.api),
|
|
167
|
+
},
|
|
168
|
+
}
|
|
169
|
+
: {
|
|
170
|
+
type: extensionOptions.type,
|
|
171
|
+
name: convertName,
|
|
172
|
+
source: toConvertSourceUrl(extensionOptions.source),
|
|
173
|
+
},
|
|
174
|
+
isIn(type, HYBRID_EXTENSION_TYPES)
|
|
175
|
+
? {
|
|
176
|
+
type,
|
|
177
|
+
name,
|
|
178
|
+
source: {
|
|
179
|
+
app: `${pathToRelativeUrl(source)}/${name}/app.${languageToShort(language)}`,
|
|
180
|
+
api: `${pathToRelativeUrl(source)}/${name}/api.${languageToShort(language)}`,
|
|
181
|
+
},
|
|
182
|
+
}
|
|
183
|
+
: {
|
|
184
|
+
type,
|
|
185
|
+
name,
|
|
186
|
+
source: `${pathToRelativeUrl(source)}/${name}/index.${languageToShort(language)}`,
|
|
187
|
+
},
|
|
188
|
+
];
|
|
189
|
+
const newExtensionOptions = {
|
|
190
|
+
type: 'bundle',
|
|
191
|
+
path: { app: 'dist/app.js', api: 'dist/api.js' },
|
|
192
|
+
entries,
|
|
193
|
+
host: extensionOptions.host,
|
|
194
|
+
hidden: extensionOptions.hidden,
|
|
195
|
+
};
|
|
196
|
+
const newExtensionManifest = {
|
|
197
|
+
...extensionManifest,
|
|
198
|
+
name: EXTENSION_NAME_REGEX.test(extensionName) ? extensionName : `directus-extension-${extensionName}`,
|
|
199
|
+
keywords: ['directus', 'directus-extension', `directus-custom-bundle`],
|
|
200
|
+
[EXTENSION_PKG_KEY]: newExtensionOptions,
|
|
201
|
+
devDependencies: await getExtensionDevDeps(entries.map((entry) => entry.type), getLanguageFromEntries(entries)),
|
|
202
|
+
};
|
|
203
|
+
await fse.writeJSON(packagePath, newExtensionManifest, { spaces: indent !== null && indent !== void 0 ? indent : '\t' });
|
|
204
|
+
const packageManager = getPackageManager();
|
|
205
|
+
await execa(packageManager, ['install'], { cwd: extensionPath });
|
|
206
|
+
spinner.succeed(chalk.bold('Done'));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function getLanguageFromEntries(entries) {
|
|
210
|
+
const languages = new Set();
|
|
211
|
+
for (const entry of entries) {
|
|
212
|
+
if (isTypeIn(entry, HYBRID_EXTENSION_TYPES)) {
|
|
213
|
+
const languageApp = getLanguageFromPath(entry.source.app);
|
|
214
|
+
const languageApi = getLanguageFromPath(entry.source.api);
|
|
215
|
+
if (!isLanguage(languageApp)) {
|
|
216
|
+
log(`App language ${chalk.bold(languageApp)} is not supported.`, 'error');
|
|
217
|
+
process.exit(1);
|
|
218
|
+
}
|
|
219
|
+
if (!isLanguage(languageApi)) {
|
|
220
|
+
log(`API language ${chalk.bold(languageApi)} is not supported.`, 'error');
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
languages.add(languageApp);
|
|
224
|
+
languages.add(languageApi);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
const language = getLanguageFromPath(entry.source);
|
|
228
|
+
if (!isLanguage(language)) {
|
|
229
|
+
log(`Language ${chalk.bold(language)} is not supported.`, 'error');
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
languages.add(language);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return Array.from(languages);
|
|
236
|
+
}
|
|
@@ -1,22 +1,25 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { API_SHARED_DEPS, APP_EXTENSION_TYPES, APP_SHARED_DEPS, EXTENSION_PACKAGE_TYPES, EXTENSION_PKG_KEY, HYBRID_EXTENSION_TYPES, } from '@directus/shared/constants';
|
|
2
|
+
import { isIn, isTypeIn, validateExtensionManifest } from '@directus/shared/utils';
|
|
3
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
4
|
+
import json from '@rollup/plugin-json';
|
|
5
|
+
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
6
|
+
import replace from '@rollup/plugin-replace';
|
|
7
|
+
import terser from '@rollup/plugin-terser';
|
|
8
|
+
import virtual from '@rollup/plugin-virtual';
|
|
2
9
|
import chalk from 'chalk';
|
|
3
10
|
import fse from 'fs-extra';
|
|
4
11
|
import ora from 'ora';
|
|
12
|
+
import path from 'path';
|
|
5
13
|
import { rollup, watch as rollupWatch, } from 'rollup';
|
|
6
|
-
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
7
|
-
import commonjs from '@rollup/plugin-commonjs';
|
|
8
|
-
import json from '@rollup/plugin-json';
|
|
9
|
-
import replace from '@rollup/plugin-replace';
|
|
10
|
-
import typescript from 'rollup-plugin-typescript2';
|
|
11
|
-
import { terser } from 'rollup-plugin-terser';
|
|
12
14
|
import styles from 'rollup-plugin-styles';
|
|
15
|
+
import typescript from 'rollup-plugin-typescript2';
|
|
13
16
|
import vue from 'rollup-plugin-vue';
|
|
14
|
-
import { EXTENSION_PKG_KEY, EXTENSION_TYPES, APP_SHARED_DEPS, API_SHARED_DEPS, APP_EXTENSION_TYPES, HYBRID_EXTENSION_TYPES, } from '@directus/shared/constants';
|
|
15
|
-
import { isIn, isTypeIn, validateExtensionManifest } from '@directus/shared/utils';
|
|
16
|
-
import { log, clear } from '../utils/logger';
|
|
17
17
|
import { getLanguageFromPath, isLanguage } from '../utils/languages';
|
|
18
|
-
import
|
|
19
|
-
import
|
|
18
|
+
import { clear, log } from '../utils/logger';
|
|
19
|
+
import tryParseJson from '../utils/try-parse-json';
|
|
20
|
+
import generateBundleEntrypoint from './helpers/generate-bundle-entrypoint';
|
|
21
|
+
import loadConfig from './helpers/load-config';
|
|
22
|
+
import { validateBundleEntriesOption, validateSplitEntrypointOption } from './helpers/validate-cli-options';
|
|
20
23
|
export default async function build(options) {
|
|
21
24
|
var _a, _b, _c;
|
|
22
25
|
const watch = (_a = options.watch) !== null && _a !== void 0 ? _a : false;
|
|
@@ -24,24 +27,31 @@ export default async function build(options) {
|
|
|
24
27
|
const minify = (_c = options.minify) !== null && _c !== void 0 ? _c : false;
|
|
25
28
|
if (!options.type && !options.input && !options.output) {
|
|
26
29
|
const packagePath = path.resolve('package.json');
|
|
27
|
-
let extensionManifest = {};
|
|
28
30
|
if (!(await fse.pathExists(packagePath))) {
|
|
29
31
|
log(`Current directory is not a valid package.`, 'error');
|
|
30
32
|
process.exit(1);
|
|
31
33
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
34
|
+
const extensionManifest = await fse.readJSON(packagePath);
|
|
35
|
+
if (!validateExtensionManifest(extensionManifest)) {
|
|
36
|
+
log(`Current directory is not a valid Directus extension.`, 'error');
|
|
37
|
+
process.exit(1);
|
|
38
38
|
}
|
|
39
39
|
const extensionOptions = extensionManifest[EXTENSION_PKG_KEY];
|
|
40
|
-
if (
|
|
41
|
-
log(`
|
|
40
|
+
if (extensionOptions.type === 'pack') {
|
|
41
|
+
log(`Building extension type ${chalk.bold('pack')} is not currently supported.`, 'error');
|
|
42
42
|
process.exit(1);
|
|
43
43
|
}
|
|
44
|
-
if (
|
|
44
|
+
if (extensionOptions.type === 'bundle') {
|
|
45
|
+
await buildBundleExtension({
|
|
46
|
+
entries: extensionOptions.entries,
|
|
47
|
+
outputApp: extensionOptions.path.app,
|
|
48
|
+
outputApi: extensionOptions.path.api,
|
|
49
|
+
watch,
|
|
50
|
+
sourcemap,
|
|
51
|
+
minify,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else if (isTypeIn(extensionOptions, HYBRID_EXTENSION_TYPES)) {
|
|
45
55
|
await buildHybridExtension({
|
|
46
56
|
inputApp: extensionOptions.source.app,
|
|
47
57
|
inputApi: extensionOptions.source.api,
|
|
@@ -71,8 +81,12 @@ export default async function build(options) {
|
|
|
71
81
|
log(`Extension type has to be specified using the ${chalk.blue('[-t, --type <type>]')} option.`, 'error');
|
|
72
82
|
process.exit(1);
|
|
73
83
|
}
|
|
74
|
-
|
|
75
|
-
log(`Extension type ${chalk.bold(type)} is not supported. Available extension types: ${
|
|
84
|
+
if (!isIn(type, EXTENSION_PACKAGE_TYPES)) {
|
|
85
|
+
log(`Extension type ${chalk.bold(type)} is not supported. Available extension types: ${EXTENSION_PACKAGE_TYPES.map((t) => chalk.bold.magenta(t)).join(', ')}.`, 'error');
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
if (type === 'pack') {
|
|
89
|
+
log(`Building extension type ${chalk.bold('pack')} is not currently supported.`, 'error');
|
|
76
90
|
process.exit(1);
|
|
77
91
|
}
|
|
78
92
|
if (!input) {
|
|
@@ -83,22 +97,42 @@ export default async function build(options) {
|
|
|
83
97
|
log(`Extension output file has to be specified using the ${chalk.blue('[-o, --output <file>]')} option.`, 'error');
|
|
84
98
|
process.exit(1);
|
|
85
99
|
}
|
|
86
|
-
if (
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
if (!
|
|
90
|
-
log(`Input option needs to be of the format ${chalk.blue(
|
|
100
|
+
if (type === 'bundle') {
|
|
101
|
+
const entries = tryParseJson(input);
|
|
102
|
+
const splitOutput = tryParseJson(output);
|
|
103
|
+
if (!validateBundleEntriesOption(entries)) {
|
|
104
|
+
log(`Input option needs to be of the format ${chalk.blue(`[-i '[{"type":"<extension-type>","name":"<extension-name>","source":<entrypoint>}]']`)}.`, 'error');
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
if (!validateSplitEntrypointOption(splitOutput)) {
|
|
108
|
+
log(`Output option needs to be of the format ${chalk.blue(`[-o '{"app":"<app-entrypoint>","api":"<api-entrypoint>"}']`)}.`, 'error');
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
await buildBundleExtension({
|
|
112
|
+
entries,
|
|
113
|
+
outputApp: splitOutput.app,
|
|
114
|
+
outputApi: splitOutput.api,
|
|
115
|
+
watch,
|
|
116
|
+
sourcemap,
|
|
117
|
+
minify,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else if (isIn(type, HYBRID_EXTENSION_TYPES)) {
|
|
121
|
+
const splitInput = tryParseJson(input);
|
|
122
|
+
const splitOutput = tryParseJson(output);
|
|
123
|
+
if (!validateSplitEntrypointOption(splitInput)) {
|
|
124
|
+
log(`Input option needs to be of the format ${chalk.blue(`[-i '{"app":"<app-entrypoint>","api":"<api-entrypoint>"}']`)}.`, 'error');
|
|
91
125
|
process.exit(1);
|
|
92
126
|
}
|
|
93
|
-
if (!
|
|
94
|
-
log(`Output option needs to be of the format ${chalk.blue(
|
|
127
|
+
if (!validateSplitEntrypointOption(splitOutput)) {
|
|
128
|
+
log(`Output option needs to be of the format ${chalk.blue(`[-o '{"app":"<app-entrypoint>","api":"<api-entrypoint>"}']`)}.`, 'error');
|
|
95
129
|
process.exit(1);
|
|
96
130
|
}
|
|
97
131
|
await buildHybridExtension({
|
|
98
|
-
inputApp:
|
|
99
|
-
inputApi:
|
|
100
|
-
outputApp:
|
|
101
|
-
outputApi:
|
|
132
|
+
inputApp: splitInput.app,
|
|
133
|
+
inputApi: splitInput.api,
|
|
134
|
+
outputApp: splitOutput.app,
|
|
135
|
+
outputApi: splitOutput.api,
|
|
102
136
|
watch,
|
|
103
137
|
sourcemap,
|
|
104
138
|
minify,
|
|
@@ -168,7 +202,7 @@ async function buildHybridExtension({ inputApp, inputApi, outputApp, outputApi,
|
|
|
168
202
|
process.exit(1);
|
|
169
203
|
}
|
|
170
204
|
if (!isLanguage(languageApi)) {
|
|
171
|
-
log(`API language ${chalk.bold(
|
|
205
|
+
log(`API language ${chalk.bold(languageApi)} is not supported.`, 'error');
|
|
172
206
|
process.exit(1);
|
|
173
207
|
}
|
|
174
208
|
const config = await loadConfig();
|
|
@@ -202,6 +236,95 @@ async function buildHybridExtension({ inputApp, inputApi, outputApp, outputApi,
|
|
|
202
236
|
await buildExtension(rollupOptionsAll);
|
|
203
237
|
}
|
|
204
238
|
}
|
|
239
|
+
async function buildBundleExtension({ entries, outputApp, outputApi, watch, sourcemap, minify, }) {
|
|
240
|
+
var _a;
|
|
241
|
+
if (outputApp.length === 0) {
|
|
242
|
+
log(`App output file can not be empty.`, 'error');
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
if (outputApi.length === 0) {
|
|
246
|
+
log(`API output file can not be empty.`, 'error');
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
const languagesApp = new Set();
|
|
250
|
+
const languagesApi = new Set();
|
|
251
|
+
for (const entry of entries) {
|
|
252
|
+
if (isTypeIn(entry, HYBRID_EXTENSION_TYPES)) {
|
|
253
|
+
const inputApp = entry.source.app;
|
|
254
|
+
const inputApi = entry.source.api;
|
|
255
|
+
if (!(await fse.pathExists(inputApp)) || !(await fse.stat(inputApp)).isFile()) {
|
|
256
|
+
log(`App entrypoint ${chalk.bold(inputApp)} does not exist.`, 'error');
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
if (!(await fse.pathExists(inputApi)) || !(await fse.stat(inputApi)).isFile()) {
|
|
260
|
+
log(`API entrypoint ${chalk.bold(inputApi)} does not exist.`, 'error');
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
const languageApp = getLanguageFromPath(inputApp);
|
|
264
|
+
const languageApi = getLanguageFromPath(inputApi);
|
|
265
|
+
if (!isLanguage(languageApp)) {
|
|
266
|
+
log(`App language ${chalk.bold(languageApp)} is not supported.`, 'error');
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
if (!isLanguage(languageApi)) {
|
|
270
|
+
log(`API language ${chalk.bold(languageApi)} is not supported.`, 'error');
|
|
271
|
+
process.exit(1);
|
|
272
|
+
}
|
|
273
|
+
languagesApp.add(languageApp);
|
|
274
|
+
languagesApi.add(languageApi);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
const input = entry.source;
|
|
278
|
+
if (!(await fse.pathExists(input)) || !(await fse.stat(input)).isFile()) {
|
|
279
|
+
log(`Entrypoint ${chalk.bold(input)} does not exist.`, 'error');
|
|
280
|
+
process.exit(1);
|
|
281
|
+
}
|
|
282
|
+
const language = getLanguageFromPath(input);
|
|
283
|
+
if (!isLanguage(language)) {
|
|
284
|
+
log(`Language ${chalk.bold(language)} is not supported.`, 'error');
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
if (isIn(entry.type, APP_EXTENSION_TYPES)) {
|
|
288
|
+
languagesApp.add(language);
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
languagesApi.add(language);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const config = await loadConfig();
|
|
296
|
+
const plugins = (_a = config.plugins) !== null && _a !== void 0 ? _a : [];
|
|
297
|
+
const entrypointApp = generateBundleEntrypoint('app', entries);
|
|
298
|
+
const entrypointApi = generateBundleEntrypoint('api', entries);
|
|
299
|
+
const rollupOptionsApp = getRollupOptions({
|
|
300
|
+
mode: 'browser',
|
|
301
|
+
input: { entry: entrypointApp },
|
|
302
|
+
language: Array.from(languagesApp),
|
|
303
|
+
sourcemap,
|
|
304
|
+
minify,
|
|
305
|
+
plugins,
|
|
306
|
+
});
|
|
307
|
+
const rollupOptionsApi = getRollupOptions({
|
|
308
|
+
mode: 'node',
|
|
309
|
+
input: { entry: entrypointApi },
|
|
310
|
+
language: Array.from(languagesApi),
|
|
311
|
+
sourcemap,
|
|
312
|
+
minify,
|
|
313
|
+
plugins,
|
|
314
|
+
});
|
|
315
|
+
const rollupOutputOptionsApp = getRollupOutputOptions({ mode: 'browser', output: outputApp, sourcemap });
|
|
316
|
+
const rollupOutputOptionsApi = getRollupOutputOptions({ mode: 'node', output: outputApi, sourcemap });
|
|
317
|
+
const rollupOptionsAll = [
|
|
318
|
+
{ rollupOptions: rollupOptionsApp, rollupOutputOptions: rollupOutputOptionsApp },
|
|
319
|
+
{ rollupOptions: rollupOptionsApi, rollupOutputOptions: rollupOutputOptionsApi },
|
|
320
|
+
];
|
|
321
|
+
if (watch) {
|
|
322
|
+
await watchExtension(rollupOptionsAll);
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
await buildExtension(rollupOptionsAll);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
205
328
|
async function buildExtension(config) {
|
|
206
329
|
const configs = Array.isArray(config) ? config : [config];
|
|
207
330
|
const spinner = ora(chalk.bold('Building Directus extension...')).start();
|
|
@@ -266,13 +389,15 @@ async function watchExtension(config) {
|
|
|
266
389
|
}
|
|
267
390
|
}
|
|
268
391
|
function getRollupOptions({ mode, input, language, sourcemap, minify, plugins, }) {
|
|
392
|
+
const languages = Array.isArray(language) ? language : [language];
|
|
269
393
|
if (mode === 'browser') {
|
|
270
394
|
return {
|
|
271
|
-
input,
|
|
395
|
+
input: typeof input !== 'string' ? 'entry' : input,
|
|
272
396
|
external: APP_SHARED_DEPS,
|
|
273
397
|
plugins: [
|
|
398
|
+
typeof input !== 'string' ? virtual(input) : null,
|
|
274
399
|
vue({ preprocessStyles: true }),
|
|
275
|
-
|
|
400
|
+
languages.includes('typescript') ? typescript({ check: false }) : null,
|
|
276
401
|
styles(),
|
|
277
402
|
...plugins,
|
|
278
403
|
nodeResolve({ browser: true }),
|
|
@@ -290,10 +415,11 @@ function getRollupOptions({ mode, input, language, sourcemap, minify, plugins, }
|
|
|
290
415
|
}
|
|
291
416
|
else {
|
|
292
417
|
return {
|
|
293
|
-
input,
|
|
418
|
+
input: typeof input !== 'string' ? 'entry' : input,
|
|
294
419
|
external: API_SHARED_DEPS,
|
|
295
420
|
plugins: [
|
|
296
|
-
|
|
421
|
+
typeof input !== 'string' ? virtual(input) : null,
|
|
422
|
+
languages.includes('typescript') ? typescript({ check: false }) : null,
|
|
297
423
|
...plugins,
|
|
298
424
|
nodeResolve(),
|
|
299
425
|
commonjs({ sourceMap: sourcemap }),
|
|
@@ -322,7 +448,7 @@ function getRollupOutputOptions({ mode, output, sourcemap, }) {
|
|
|
322
448
|
return {
|
|
323
449
|
file: output,
|
|
324
450
|
format: 'cjs',
|
|
325
|
-
exports: '
|
|
451
|
+
exports: 'auto',
|
|
326
452
|
inlineDynamicImports: true,
|
|
327
453
|
sourcemap,
|
|
328
454
|
};
|