@directus/extensions-sdk 9.22.1 → 9.22.3
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.js +9 -8
- package/dist/cjs/cli/commands/build.js +11 -15
- package/dist/cjs/cli/commands/create.js +12 -5
- package/dist/cjs/cli/commands/helpers/copy-template.d.ts +2 -2
- package/dist/cjs/cli/commands/helpers/generate-bundle-entrypoint.js +1 -1
- package/dist/cjs/cli/commands/helpers/get-extension-dev-deps.d.ts +2 -2
- package/dist/cjs/cli/commands/helpers/get-extension-dev-deps.js +2 -2
- package/dist/cjs/cli/commands/helpers/validate-cli-options.d.ts +1 -2
- package/dist/cjs/cli/commands/helpers/validate-cli-options.js +1 -17
- package/dist/cjs/cli/commands/link.d.ts +2 -0
- package/dist/cjs/cli/commands/link.js +54 -0
- package/dist/cjs/cli/run.js +6 -0
- package/dist/esm/cli/commands/add.js +10 -9
- package/dist/esm/cli/commands/build.js +14 -18
- package/dist/esm/cli/commands/create.js +13 -6
- package/dist/esm/cli/commands/helpers/copy-template.d.ts +2 -2
- package/dist/esm/cli/commands/helpers/generate-bundle-entrypoint.js +2 -2
- package/dist/esm/cli/commands/helpers/get-extension-dev-deps.d.ts +2 -2
- package/dist/esm/cli/commands/helpers/get-extension-dev-deps.js +3 -3
- package/dist/esm/cli/commands/helpers/validate-cli-options.d.ts +1 -2
- package/dist/esm/cli/commands/helpers/validate-cli-options.js +0 -15
- package/dist/esm/cli/commands/link.d.ts +2 -0
- package/dist/esm/cli/commands/link.js +48 -0
- package/dist/esm/cli/run.js +6 -0
- package/package.json +13 -13
|
@@ -8,6 +8,7 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
8
8
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
9
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
10
|
const logger_1 = require("../utils/logger");
|
|
11
|
+
const types_1 = require("@directus/shared/types");
|
|
11
12
|
const utils_1 = require("@directus/shared/utils");
|
|
12
13
|
const node_1 = require("@directus/shared/utils/node");
|
|
13
14
|
const constants_1 = require("@directus/shared/constants");
|
|
@@ -26,18 +27,18 @@ async function add() {
|
|
|
26
27
|
(0, logger_1.log)(`Current directory is not a valid package.`, 'error');
|
|
27
28
|
process.exit(1);
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
let extensionManifest;
|
|
31
|
+
let indent = null;
|
|
32
|
+
try {
|
|
33
|
+
const extensionManifestFile = await fs_extra_1.default.readFile(packagePath, 'utf8');
|
|
34
|
+
extensionManifest = types_1.ExtensionManifest.parse(JSON.parse(extensionManifestFile));
|
|
35
|
+
indent = (0, detect_json_indent_1.default)(extensionManifestFile);
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
33
38
|
(0, logger_1.log)(`Current directory is not a valid Directus extension.`, 'error');
|
|
34
39
|
process.exit(1);
|
|
35
40
|
}
|
|
36
41
|
const extensionOptions = extensionManifest[constants_1.EXTENSION_PKG_KEY];
|
|
37
|
-
if (extensionOptions.type === 'pack') {
|
|
38
|
-
(0, logger_1.log)(`Adding entries to extensions with type ${chalk_1.default.bold('pack')} is not currently supported.`, 'error');
|
|
39
|
-
process.exit(1);
|
|
40
|
-
}
|
|
41
42
|
const sourceExists = await fs_extra_1.default.pathExists(path_1.default.resolve('src'));
|
|
42
43
|
if (extensionOptions.type === 'bundle') {
|
|
43
44
|
const { type, name, language, alternativeSource } = await inquirer_1.default.prompt([
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const constants_1 = require("@directus/shared/constants");
|
|
7
|
+
const types_1 = require("@directus/shared/types");
|
|
7
8
|
const utils_1 = require("@directus/shared/utils");
|
|
8
9
|
const plugin_commonjs_1 = __importDefault(require("@rollup/plugin-commonjs"));
|
|
9
10
|
const plugin_json_1 = __importDefault(require("@rollup/plugin-json"));
|
|
@@ -36,16 +37,15 @@ async function build(options) {
|
|
|
36
37
|
(0, logger_1.log)(`Current directory is not a valid package.`, 'error');
|
|
37
38
|
process.exit(1);
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
let extensionManifest;
|
|
41
|
+
try {
|
|
42
|
+
extensionManifest = types_1.ExtensionManifest.parse(await fs_extra_1.default.readJSON(packagePath));
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
41
45
|
(0, logger_1.log)(`Current directory is not a valid Directus extension.`, 'error');
|
|
42
46
|
process.exit(1);
|
|
43
47
|
}
|
|
44
48
|
const extensionOptions = extensionManifest[constants_1.EXTENSION_PKG_KEY];
|
|
45
|
-
if (extensionOptions.type === 'pack') {
|
|
46
|
-
(0, logger_1.log)(`Building extension type ${chalk_1.default.bold('pack')} is not currently supported.`, 'error');
|
|
47
|
-
process.exit(1);
|
|
48
|
-
}
|
|
49
49
|
if (extensionOptions.type === 'bundle') {
|
|
50
50
|
await buildBundleExtension({
|
|
51
51
|
entries: extensionOptions.entries,
|
|
@@ -86,12 +86,8 @@ async function build(options) {
|
|
|
86
86
|
(0, logger_1.log)(`Extension type has to be specified using the ${chalk_1.default.blue('[-t, --type <type>]')} option.`, 'error');
|
|
87
87
|
process.exit(1);
|
|
88
88
|
}
|
|
89
|
-
if (!(0, utils_1.isIn)(type, constants_1.
|
|
90
|
-
(0, logger_1.log)(`Extension type ${chalk_1.default.bold(type)} is not supported. Available extension types: ${constants_1.
|
|
91
|
-
process.exit(1);
|
|
92
|
-
}
|
|
93
|
-
if (type === 'pack') {
|
|
94
|
-
(0, logger_1.log)(`Building extension type ${chalk_1.default.bold('pack')} is not currently supported.`, 'error');
|
|
89
|
+
if (!(0, utils_1.isIn)(type, constants_1.EXTENSION_TYPES)) {
|
|
90
|
+
(0, logger_1.log)(`Extension type ${chalk_1.default.bold(type)} is not supported. Available extension types: ${constants_1.EXTENSION_TYPES.map((t) => chalk_1.default.bold.magenta(t)).join(', ')}.`, 'error');
|
|
95
91
|
process.exit(1);
|
|
96
92
|
}
|
|
97
93
|
if (!input) {
|
|
@@ -103,9 +99,9 @@ async function build(options) {
|
|
|
103
99
|
process.exit(1);
|
|
104
100
|
}
|
|
105
101
|
if (type === 'bundle') {
|
|
106
|
-
const entries = (0, try_parse_json_1.default)(input);
|
|
102
|
+
const entries = types_1.ExtensionOptionsBundleEntries.safeParse((0, try_parse_json_1.default)(input));
|
|
107
103
|
const splitOutput = (0, try_parse_json_1.default)(output);
|
|
108
|
-
if (
|
|
104
|
+
if (entries.success === false) {
|
|
109
105
|
(0, logger_1.log)(`Input option needs to be of the format ${chalk_1.default.blue(`[-i '[{"type":"<extension-type>","name":"<extension-name>","source":<entrypoint>}]']`)}.`, 'error');
|
|
110
106
|
process.exit(1);
|
|
111
107
|
}
|
|
@@ -114,7 +110,7 @@ async function build(options) {
|
|
|
114
110
|
process.exit(1);
|
|
115
111
|
}
|
|
116
112
|
await buildBundleExtension({
|
|
117
|
-
entries,
|
|
113
|
+
entries: entries.data,
|
|
118
114
|
outputApp: splitOutput.app,
|
|
119
115
|
outputApi: splitOutput.api,
|
|
120
116
|
watch,
|
|
@@ -20,8 +20,8 @@ async function create(type, name, options) {
|
|
|
20
20
|
var _a;
|
|
21
21
|
const targetDir = name.substring(name.lastIndexOf('/') + 1);
|
|
22
22
|
const targetPath = path_1.default.resolve(targetDir);
|
|
23
|
-
if (!(0, utils_1.isIn)(type, constants_1.
|
|
24
|
-
(0, logger_1.log)(`Extension type ${chalk_1.default.bold(type)} is not supported. Available extension types: ${constants_1.
|
|
23
|
+
if (!(0, utils_1.isIn)(type, constants_1.EXTENSION_TYPES)) {
|
|
24
|
+
(0, logger_1.log)(`Extension type ${chalk_1.default.bold(type)} is not supported. Available extension types: ${constants_1.EXTENSION_TYPES.map((t) => chalk_1.default.bold.magenta(t)).join(', ')}.`, 'error');
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
if (targetDir.length === 0) {
|
|
@@ -40,7 +40,7 @@ async function create(type, name, options) {
|
|
|
40
40
|
process.exit(1);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
if ((0, utils_1.isIn)(type, constants_1.
|
|
43
|
+
if ((0, utils_1.isIn)(type, constants_1.BUNDLE_EXTENSION_TYPES)) {
|
|
44
44
|
await createPackageExtension({ type, name, targetDir, targetPath });
|
|
45
45
|
}
|
|
46
46
|
else {
|
|
@@ -54,7 +54,7 @@ async function createPackageExtension({ type, name, targetDir, targetPath, }) {
|
|
|
54
54
|
await fs_extra_1.default.ensureDir(targetPath);
|
|
55
55
|
await (0, copy_template_1.default)(type, targetPath);
|
|
56
56
|
const host = `^${(0, get_sdk_version_1.default)()}`;
|
|
57
|
-
const options =
|
|
57
|
+
const options = { type, path: { app: 'dist/app.js', api: 'dist/api.js' }, entries: [], host };
|
|
58
58
|
const packageManifest = getPackageManifest(name, options, await (0, get_extension_dev_deps_1.default)(type));
|
|
59
59
|
await fs_extra_1.default.writeJSON(path_1.default.join(targetPath, 'package.json'), packageManifest, { spaces: '\t' });
|
|
60
60
|
const packageManager = (0, get_package_manager_1.default)();
|
|
@@ -92,17 +92,24 @@ async function createLocalExtension({ type, name, targetDir, targetPath, languag
|
|
|
92
92
|
(0, logger_1.log)(getDoneMessage(type, targetDir, targetPath, packageManager));
|
|
93
93
|
}
|
|
94
94
|
function getPackageManifest(name, options, deps) {
|
|
95
|
-
|
|
95
|
+
const packageManifest = {
|
|
96
96
|
name: constants_1.EXTENSION_NAME_REGEX.test(name) ? name : `directus-extension-${name}`,
|
|
97
|
+
description: 'Please enter a description for your extension',
|
|
98
|
+
icon: 'extension',
|
|
97
99
|
version: '1.0.0',
|
|
98
100
|
keywords: ['directus', 'directus-extension', `directus-custom-${options.type}`],
|
|
99
101
|
[constants_1.EXTENSION_PKG_KEY]: options,
|
|
100
102
|
scripts: {
|
|
101
103
|
build: 'directus-extension build',
|
|
102
104
|
dev: 'directus-extension build -w --no-minify',
|
|
105
|
+
link: 'directus-extension link',
|
|
103
106
|
},
|
|
104
107
|
devDependencies: deps,
|
|
105
108
|
};
|
|
109
|
+
if (options.type === 'bundle') {
|
|
110
|
+
packageManifest.scripts['add'] = 'directus-extension add';
|
|
111
|
+
}
|
|
112
|
+
return packageManifest;
|
|
106
113
|
}
|
|
107
114
|
function getDoneMessage(type, targetDir, targetPath, packageManager) {
|
|
108
115
|
return `
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtensionType } from '@directus/shared/types';
|
|
2
2
|
import { Language } from '../../types';
|
|
3
|
-
export default function copyTemplate(type:
|
|
3
|
+
export default function copyTemplate(type: ExtensionType, extensionPath: string, sourcePath?: string, language?: Language): Promise<void>;
|
|
4
4
|
//# sourceMappingURL=copy-template.d.ts.map
|
|
@@ -8,7 +8,7 @@ const constants_1 = require("@directus/shared/constants");
|
|
|
8
8
|
const utils_1 = require("@directus/shared/utils");
|
|
9
9
|
const node_1 = require("@directus/shared/utils/node");
|
|
10
10
|
function generateBundleEntrypoint(mode, entries) {
|
|
11
|
-
const types = mode === 'app' ? constants_1.
|
|
11
|
+
const types = [...(mode === 'app' ? constants_1.APP_EXTENSION_TYPES : constants_1.API_EXTENSION_TYPES), ...constants_1.HYBRID_EXTENSION_TYPES];
|
|
12
12
|
const entriesForTypes = entries.filter((entry) => (0, utils_1.isIn)(entry.type, types));
|
|
13
13
|
const imports = entriesForTypes.map((entry, i) => `import e${i} from './${(0, node_1.pathToRelativeUrl)(path_1.default.resolve((0, utils_1.isTypeIn)(entry, constants_1.HYBRID_EXTENSION_TYPES)
|
|
14
14
|
? mode === 'app'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtensionType } from '@directus/shared/types';
|
|
2
2
|
import { Language } from '../../types';
|
|
3
|
-
export default function getExtensionDevDeps(type:
|
|
3
|
+
export default function getExtensionDevDeps(type: ExtensionType | ExtensionType[], language?: Language | Language[]): Promise<Record<string, string>>;
|
|
4
4
|
//# sourceMappingURL=get-extension-dev-deps.d.ts.map
|
|
@@ -14,12 +14,12 @@ async function getExtensionDevDeps(type, language = []) {
|
|
|
14
14
|
'@directus/extensions-sdk': (0, get_sdk_version_1.default)(),
|
|
15
15
|
};
|
|
16
16
|
if (languages.includes('typescript')) {
|
|
17
|
-
if (types.some((type) => (0, utils_1.isIn)(type, constants_1.
|
|
17
|
+
if (types.some((type) => (0, utils_1.isIn)(type, [...constants_1.API_EXTENSION_TYPES, ...constants_1.HYBRID_EXTENSION_TYPES]))) {
|
|
18
18
|
deps['@types/node'] = `^${await (0, get_package_version_1.default)('@types/node')}`;
|
|
19
19
|
}
|
|
20
20
|
deps['typescript'] = `^${await (0, get_package_version_1.default)('typescript')}`;
|
|
21
21
|
}
|
|
22
|
-
if (types.some((type) => (0, utils_1.isIn)(type, constants_1.
|
|
22
|
+
if (types.some((type) => (0, utils_1.isIn)(type, [...constants_1.APP_EXTENSION_TYPES, ...constants_1.HYBRID_EXTENSION_TYPES]))) {
|
|
23
23
|
deps['vue'] = `^${await (0, get_package_version_1.default)('vue')}`;
|
|
24
24
|
}
|
|
25
25
|
return deps;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JsonValue, SplitEntrypoint } from '@directus/shared/types';
|
|
2
2
|
export declare function validateSplitEntrypointOption(option: JsonValue | undefined): option is SplitEntrypoint;
|
|
3
|
-
export declare function validateBundleEntriesOption(option: JsonValue | undefined): option is ExtensionOptionsBundleEntry[];
|
|
4
3
|
//# sourceMappingURL=validate-cli-options.d.ts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const utils_1 = require("@directus/shared/utils");
|
|
3
|
+
exports.validateSplitEntrypointOption = void 0;
|
|
5
4
|
function validateNonPrimitive(value) {
|
|
6
5
|
if (value === undefined ||
|
|
7
6
|
value === null ||
|
|
@@ -22,18 +21,3 @@ function validateSplitEntrypointOption(option) {
|
|
|
22
21
|
return true;
|
|
23
22
|
}
|
|
24
23
|
exports.validateSplitEntrypointOption = validateSplitEntrypointOption;
|
|
25
|
-
function validateBundleEntriesOption(option) {
|
|
26
|
-
if (!validateNonPrimitive(option) || !Array.isArray(option)) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
if (!option.every((entry) => {
|
|
30
|
-
if (!validateNonPrimitive(entry) || Array.isArray(entry)) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
return (0, utils_1.validateExtensionOptionsBundleEntry)(entry);
|
|
34
|
-
})) {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
exports.validateBundleEntriesOption = validateBundleEntriesOption;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const logger_1 = require("../utils/logger");
|
|
9
|
+
const types_1 = require("@directus/shared/types");
|
|
10
|
+
async function link(extensionsPath) {
|
|
11
|
+
var _a;
|
|
12
|
+
const extensionPath = process.cwd();
|
|
13
|
+
const absoluteExtensionsPath = path_1.default.resolve(extensionsPath);
|
|
14
|
+
if (!fs_extra_1.default.existsSync(absoluteExtensionsPath)) {
|
|
15
|
+
(0, logger_1.log)(`Extensions folder does not exist at ${absoluteExtensionsPath}`, 'error');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const packagePath = path_1.default.resolve('package.json');
|
|
19
|
+
if (!(await fs_extra_1.default.pathExists(packagePath))) {
|
|
20
|
+
(0, logger_1.log)(`Current directory is not a valid package.`, 'error');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
let manifestFile;
|
|
24
|
+
try {
|
|
25
|
+
manifestFile = await fs_extra_1.default.readJSON(packagePath);
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
(0, logger_1.log)(`Current directory is not a valid Directus extension.`, 'error');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const extensionManifest = types_1.ExtensionManifest.parse(manifestFile);
|
|
32
|
+
const extensionName = extensionManifest.name;
|
|
33
|
+
if (!extensionName) {
|
|
34
|
+
(0, logger_1.log)(`Extension name not found in package.json`, 'error');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const type = (_a = extensionManifest['directus:extension']) === null || _a === void 0 ? void 0 : _a.type;
|
|
38
|
+
if (!type) {
|
|
39
|
+
(0, logger_1.log)(`Extension type not found in package.json`, 'error');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const extensionTarget = path_1.default.join(absoluteExtensionsPath, extensionName);
|
|
43
|
+
try {
|
|
44
|
+
fs_extra_1.default.ensureSymlinkSync(extensionPath, extensionTarget);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
(0, logger_1.log)(error.message, 'error');
|
|
48
|
+
(0, logger_1.log)(`Try running this command with administrator privileges`, 'info');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
(0, logger_1.log)(`Linked ${extensionName} to ${extensionTarget}`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
exports.default = link;
|
package/dist/cjs/cli/run.js
CHANGED
|
@@ -7,6 +7,7 @@ const commander_1 = require("commander");
|
|
|
7
7
|
const create_1 = __importDefault(require("./commands/create"));
|
|
8
8
|
const add_1 = __importDefault(require("./commands/add"));
|
|
9
9
|
const build_1 = __importDefault(require("./commands/build"));
|
|
10
|
+
const link_1 = __importDefault(require("./commands/link"));
|
|
10
11
|
const pkg = require('../../../package.json');
|
|
11
12
|
const program = new commander_1.Command();
|
|
12
13
|
program.name('directus-extension').usage('[command] [options]');
|
|
@@ -30,4 +31,9 @@ program
|
|
|
30
31
|
.option('--no-minify', 'disable minification')
|
|
31
32
|
.option('--sourcemap', 'include source maps in output')
|
|
32
33
|
.action(build_1.default);
|
|
34
|
+
program
|
|
35
|
+
.command('link')
|
|
36
|
+
.description('Creates a symlink to the extension in the Directus extensions folder')
|
|
37
|
+
.argument('<path>', 'path to the extension folder of directus')
|
|
38
|
+
.action(link_1.default);
|
|
33
39
|
program.parse(process.argv);
|
|
@@ -3,7 +3,8 @@ import chalk from 'chalk';
|
|
|
3
3
|
import fse from 'fs-extra';
|
|
4
4
|
import inquirer from 'inquirer';
|
|
5
5
|
import { log } from '../utils/logger';
|
|
6
|
-
import {
|
|
6
|
+
import { ExtensionManifest, } from '@directus/shared/types';
|
|
7
|
+
import { isIn, isTypeIn } from '@directus/shared/utils';
|
|
7
8
|
import { pathToRelativeUrl } from '@directus/shared/utils/node';
|
|
8
9
|
import { EXTENSION_LANGUAGES, EXTENSION_NAME_REGEX, EXTENSION_PKG_KEY, EXTENSION_TYPES, HYBRID_EXTENSION_TYPES, } from '@directus/shared/constants';
|
|
9
10
|
import { getLanguageFromPath, isLanguage, languageToShort } from '../utils/languages';
|
|
@@ -21,18 +22,18 @@ export default async function add() {
|
|
|
21
22
|
log(`Current directory is not a valid package.`, 'error');
|
|
22
23
|
process.exit(1);
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
let extensionManifest;
|
|
26
|
+
let indent = null;
|
|
27
|
+
try {
|
|
28
|
+
const extensionManifestFile = await fse.readFile(packagePath, 'utf8');
|
|
29
|
+
extensionManifest = ExtensionManifest.parse(JSON.parse(extensionManifestFile));
|
|
30
|
+
indent = detectJsonIndent(extensionManifestFile);
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
28
33
|
log(`Current directory is not a valid Directus extension.`, 'error');
|
|
29
34
|
process.exit(1);
|
|
30
35
|
}
|
|
31
36
|
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
37
|
const sourceExists = await fse.pathExists(path.resolve('src'));
|
|
37
38
|
if (extensionOptions.type === 'bundle') {
|
|
38
39
|
const { type, name, language, alternativeSource } = await inquirer.prompt([
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { API_SHARED_DEPS, APP_EXTENSION_TYPES, APP_SHARED_DEPS,
|
|
2
|
-
import {
|
|
1
|
+
import { API_SHARED_DEPS, APP_EXTENSION_TYPES, APP_SHARED_DEPS, EXTENSION_PKG_KEY, EXTENSION_TYPES, HYBRID_EXTENSION_TYPES, } from '@directus/shared/constants';
|
|
2
|
+
import { ExtensionManifest, ExtensionOptionsBundleEntries, } from '@directus/shared/types';
|
|
3
|
+
import { isIn, isTypeIn } from '@directus/shared/utils';
|
|
3
4
|
import commonjs from '@rollup/plugin-commonjs';
|
|
4
5
|
import json from '@rollup/plugin-json';
|
|
5
6
|
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
@@ -19,7 +20,7 @@ import { clear, log } from '../utils/logger';
|
|
|
19
20
|
import tryParseJson from '../utils/try-parse-json';
|
|
20
21
|
import generateBundleEntrypoint from './helpers/generate-bundle-entrypoint';
|
|
21
22
|
import loadConfig from './helpers/load-config';
|
|
22
|
-
import {
|
|
23
|
+
import { validateSplitEntrypointOption } from './helpers/validate-cli-options';
|
|
23
24
|
export default async function build(options) {
|
|
24
25
|
var _a, _b, _c;
|
|
25
26
|
const watch = (_a = options.watch) !== null && _a !== void 0 ? _a : false;
|
|
@@ -31,16 +32,15 @@ export default async function build(options) {
|
|
|
31
32
|
log(`Current directory is not a valid package.`, 'error');
|
|
32
33
|
process.exit(1);
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
let extensionManifest;
|
|
36
|
+
try {
|
|
37
|
+
extensionManifest = ExtensionManifest.parse(await fse.readJSON(packagePath));
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
36
40
|
log(`Current directory is not a valid Directus extension.`, 'error');
|
|
37
41
|
process.exit(1);
|
|
38
42
|
}
|
|
39
43
|
const extensionOptions = extensionManifest[EXTENSION_PKG_KEY];
|
|
40
|
-
if (extensionOptions.type === 'pack') {
|
|
41
|
-
log(`Building extension type ${chalk.bold('pack')} is not currently supported.`, 'error');
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
44
|
if (extensionOptions.type === 'bundle') {
|
|
45
45
|
await buildBundleExtension({
|
|
46
46
|
entries: extensionOptions.entries,
|
|
@@ -81,12 +81,8 @@ export default async function build(options) {
|
|
|
81
81
|
log(`Extension type has to be specified using the ${chalk.blue('[-t, --type <type>]')} option.`, 'error');
|
|
82
82
|
process.exit(1);
|
|
83
83
|
}
|
|
84
|
-
if (!isIn(type,
|
|
85
|
-
log(`Extension type ${chalk.bold(type)} is not supported. Available extension types: ${
|
|
86
|
-
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
if (type === 'pack') {
|
|
89
|
-
log(`Building extension type ${chalk.bold('pack')} is not currently supported.`, 'error');
|
|
84
|
+
if (!isIn(type, EXTENSION_TYPES)) {
|
|
85
|
+
log(`Extension type ${chalk.bold(type)} is not supported. Available extension types: ${EXTENSION_TYPES.map((t) => chalk.bold.magenta(t)).join(', ')}.`, 'error');
|
|
90
86
|
process.exit(1);
|
|
91
87
|
}
|
|
92
88
|
if (!input) {
|
|
@@ -98,9 +94,9 @@ export default async function build(options) {
|
|
|
98
94
|
process.exit(1);
|
|
99
95
|
}
|
|
100
96
|
if (type === 'bundle') {
|
|
101
|
-
const entries = tryParseJson(input);
|
|
97
|
+
const entries = ExtensionOptionsBundleEntries.safeParse(tryParseJson(input));
|
|
102
98
|
const splitOutput = tryParseJson(output);
|
|
103
|
-
if (
|
|
99
|
+
if (entries.success === false) {
|
|
104
100
|
log(`Input option needs to be of the format ${chalk.blue(`[-i '[{"type":"<extension-type>","name":"<extension-name>","source":<entrypoint>}]']`)}.`, 'error');
|
|
105
101
|
process.exit(1);
|
|
106
102
|
}
|
|
@@ -109,7 +105,7 @@ export default async function build(options) {
|
|
|
109
105
|
process.exit(1);
|
|
110
106
|
}
|
|
111
107
|
await buildBundleExtension({
|
|
112
|
-
entries,
|
|
108
|
+
entries: entries.data,
|
|
113
109
|
outputApp: splitOutput.app,
|
|
114
110
|
outputApi: splitOutput.api,
|
|
115
111
|
watch,
|
|
@@ -3,7 +3,7 @@ import chalk from 'chalk';
|
|
|
3
3
|
import fse from 'fs-extra';
|
|
4
4
|
import execa from 'execa';
|
|
5
5
|
import ora from 'ora';
|
|
6
|
-
import { EXTENSION_PKG_KEY, EXTENSION_LANGUAGES, HYBRID_EXTENSION_TYPES, EXTENSION_NAME_REGEX,
|
|
6
|
+
import { EXTENSION_PKG_KEY, EXTENSION_LANGUAGES, HYBRID_EXTENSION_TYPES, EXTENSION_NAME_REGEX, EXTENSION_TYPES, BUNDLE_EXTENSION_TYPES, } from '@directus/shared/constants';
|
|
7
7
|
import { isIn } from '@directus/shared/utils';
|
|
8
8
|
import { log } from '../utils/logger';
|
|
9
9
|
import { isLanguage, languageToShort } from '../utils/languages';
|
|
@@ -15,8 +15,8 @@ export default async function create(type, name, options) {
|
|
|
15
15
|
var _a;
|
|
16
16
|
const targetDir = name.substring(name.lastIndexOf('/') + 1);
|
|
17
17
|
const targetPath = path.resolve(targetDir);
|
|
18
|
-
if (!isIn(type,
|
|
19
|
-
log(`Extension type ${chalk.bold(type)} is not supported. Available extension types: ${
|
|
18
|
+
if (!isIn(type, EXTENSION_TYPES)) {
|
|
19
|
+
log(`Extension type ${chalk.bold(type)} is not supported. Available extension types: ${EXTENSION_TYPES.map((t) => chalk.bold.magenta(t)).join(', ')}.`, 'error');
|
|
20
20
|
process.exit(1);
|
|
21
21
|
}
|
|
22
22
|
if (targetDir.length === 0) {
|
|
@@ -35,7 +35,7 @@ export default async function create(type, name, options) {
|
|
|
35
35
|
process.exit(1);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
if (isIn(type,
|
|
38
|
+
if (isIn(type, BUNDLE_EXTENSION_TYPES)) {
|
|
39
39
|
await createPackageExtension({ type, name, targetDir, targetPath });
|
|
40
40
|
}
|
|
41
41
|
else {
|
|
@@ -48,7 +48,7 @@ async function createPackageExtension({ type, name, targetDir, targetPath, }) {
|
|
|
48
48
|
await fse.ensureDir(targetPath);
|
|
49
49
|
await copyTemplate(type, targetPath);
|
|
50
50
|
const host = `^${getSdkVersion()}`;
|
|
51
|
-
const options =
|
|
51
|
+
const options = { type, path: { app: 'dist/app.js', api: 'dist/api.js' }, entries: [], host };
|
|
52
52
|
const packageManifest = getPackageManifest(name, options, await getExtensionDevDeps(type));
|
|
53
53
|
await fse.writeJSON(path.join(targetPath, 'package.json'), packageManifest, { spaces: '\t' });
|
|
54
54
|
const packageManager = getPackageManager();
|
|
@@ -86,17 +86,24 @@ async function createLocalExtension({ type, name, targetDir, targetPath, languag
|
|
|
86
86
|
log(getDoneMessage(type, targetDir, targetPath, packageManager));
|
|
87
87
|
}
|
|
88
88
|
function getPackageManifest(name, options, deps) {
|
|
89
|
-
|
|
89
|
+
const packageManifest = {
|
|
90
90
|
name: EXTENSION_NAME_REGEX.test(name) ? name : `directus-extension-${name}`,
|
|
91
|
+
description: 'Please enter a description for your extension',
|
|
92
|
+
icon: 'extension',
|
|
91
93
|
version: '1.0.0',
|
|
92
94
|
keywords: ['directus', 'directus-extension', `directus-custom-${options.type}`],
|
|
93
95
|
[EXTENSION_PKG_KEY]: options,
|
|
94
96
|
scripts: {
|
|
95
97
|
build: 'directus-extension build',
|
|
96
98
|
dev: 'directus-extension build -w --no-minify',
|
|
99
|
+
link: 'directus-extension link',
|
|
97
100
|
},
|
|
98
101
|
devDependencies: deps,
|
|
99
102
|
};
|
|
103
|
+
if (options.type === 'bundle') {
|
|
104
|
+
packageManifest.scripts['add'] = 'directus-extension add';
|
|
105
|
+
}
|
|
106
|
+
return packageManifest;
|
|
100
107
|
}
|
|
101
108
|
function getDoneMessage(type, targetDir, targetPath, packageManager) {
|
|
102
109
|
return `
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtensionType } from '@directus/shared/types';
|
|
2
2
|
import { Language } from '../../types';
|
|
3
|
-
export default function copyTemplate(type:
|
|
3
|
+
export default function copyTemplate(type: ExtensionType, extensionPath: string, sourcePath?: string, language?: Language): Promise<void>;
|
|
4
4
|
//# sourceMappingURL=copy-template.d.ts.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import {
|
|
2
|
+
import { API_EXTENSION_TYPES, APP_EXTENSION_TYPES, HYBRID_EXTENSION_TYPES } from '@directus/shared/constants';
|
|
3
3
|
import { isIn, isTypeIn, pluralize } from '@directus/shared/utils';
|
|
4
4
|
import { pathToRelativeUrl } from '@directus/shared/utils/node';
|
|
5
5
|
export default function generateBundleEntrypoint(mode, entries) {
|
|
6
|
-
const types = mode === 'app' ?
|
|
6
|
+
const types = [...(mode === 'app' ? APP_EXTENSION_TYPES : API_EXTENSION_TYPES), ...HYBRID_EXTENSION_TYPES];
|
|
7
7
|
const entriesForTypes = entries.filter((entry) => isIn(entry.type, types));
|
|
8
8
|
const imports = entriesForTypes.map((entry, i) => `import e${i} from './${pathToRelativeUrl(path.resolve(isTypeIn(entry, HYBRID_EXTENSION_TYPES)
|
|
9
9
|
? mode === 'app'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtensionType } from '@directus/shared/types';
|
|
2
2
|
import { Language } from '../../types';
|
|
3
|
-
export default function getExtensionDevDeps(type:
|
|
3
|
+
export default function getExtensionDevDeps(type: ExtensionType | ExtensionType[], language?: Language | Language[]): Promise<Record<string, string>>;
|
|
4
4
|
//# sourceMappingURL=get-extension-dev-deps.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { APP_EXTENSION_TYPES, API_EXTENSION_TYPES, HYBRID_EXTENSION_TYPES } from '@directus/shared/constants';
|
|
2
2
|
import { isIn } from '@directus/shared/utils';
|
|
3
3
|
import getPackageVersion from '../../utils/get-package-version';
|
|
4
4
|
import getSdkVersion from '../../utils/get-sdk-version';
|
|
@@ -9,12 +9,12 @@ export default async function getExtensionDevDeps(type, language = []) {
|
|
|
9
9
|
'@directus/extensions-sdk': getSdkVersion(),
|
|
10
10
|
};
|
|
11
11
|
if (languages.includes('typescript')) {
|
|
12
|
-
if (types.some((type) => isIn(type,
|
|
12
|
+
if (types.some((type) => isIn(type, [...API_EXTENSION_TYPES, ...HYBRID_EXTENSION_TYPES]))) {
|
|
13
13
|
deps['@types/node'] = `^${await getPackageVersion('@types/node')}`;
|
|
14
14
|
}
|
|
15
15
|
deps['typescript'] = `^${await getPackageVersion('typescript')}`;
|
|
16
16
|
}
|
|
17
|
-
if (types.some((type) => isIn(type,
|
|
17
|
+
if (types.some((type) => isIn(type, [...APP_EXTENSION_TYPES, ...HYBRID_EXTENSION_TYPES]))) {
|
|
18
18
|
deps['vue'] = `^${await getPackageVersion('vue')}`;
|
|
19
19
|
}
|
|
20
20
|
return deps;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JsonValue, SplitEntrypoint } from '@directus/shared/types';
|
|
2
2
|
export declare function validateSplitEntrypointOption(option: JsonValue | undefined): option is SplitEntrypoint;
|
|
3
|
-
export declare function validateBundleEntriesOption(option: JsonValue | undefined): option is ExtensionOptionsBundleEntry[];
|
|
4
3
|
//# sourceMappingURL=validate-cli-options.d.ts.map
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { validateExtensionOptionsBundleEntry } from '@directus/shared/utils';
|
|
2
1
|
function validateNonPrimitive(value) {
|
|
3
2
|
if (value === undefined ||
|
|
4
3
|
value === null ||
|
|
@@ -18,17 +17,3 @@ export function validateSplitEntrypointOption(option) {
|
|
|
18
17
|
}
|
|
19
18
|
return true;
|
|
20
19
|
}
|
|
21
|
-
export function validateBundleEntriesOption(option) {
|
|
22
|
-
if (!validateNonPrimitive(option) || !Array.isArray(option)) {
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
if (!option.every((entry) => {
|
|
26
|
-
if (!validateNonPrimitive(entry) || Array.isArray(entry)) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
return validateExtensionOptionsBundleEntry(entry);
|
|
30
|
-
})) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { log } from '../utils/logger';
|
|
4
|
+
import { ExtensionManifest } from '@directus/shared/types';
|
|
5
|
+
export default async function link(extensionsPath) {
|
|
6
|
+
var _a;
|
|
7
|
+
const extensionPath = process.cwd();
|
|
8
|
+
const absoluteExtensionsPath = path.resolve(extensionsPath);
|
|
9
|
+
if (!fs.existsSync(absoluteExtensionsPath)) {
|
|
10
|
+
log(`Extensions folder does not exist at ${absoluteExtensionsPath}`, 'error');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const packagePath = path.resolve('package.json');
|
|
14
|
+
if (!(await fs.pathExists(packagePath))) {
|
|
15
|
+
log(`Current directory is not a valid package.`, 'error');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
let manifestFile;
|
|
19
|
+
try {
|
|
20
|
+
manifestFile = await fs.readJSON(packagePath);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
log(`Current directory is not a valid Directus extension.`, 'error');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const extensionManifest = ExtensionManifest.parse(manifestFile);
|
|
27
|
+
const extensionName = extensionManifest.name;
|
|
28
|
+
if (!extensionName) {
|
|
29
|
+
log(`Extension name not found in package.json`, 'error');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const type = (_a = extensionManifest['directus:extension']) === null || _a === void 0 ? void 0 : _a.type;
|
|
33
|
+
if (!type) {
|
|
34
|
+
log(`Extension type not found in package.json`, 'error');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const extensionTarget = path.join(absoluteExtensionsPath, extensionName);
|
|
38
|
+
try {
|
|
39
|
+
fs.ensureSymlinkSync(extensionPath, extensionTarget);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
log(error.message, 'error');
|
|
43
|
+
log(`Try running this command with administrator privileges`, 'info');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
log(`Linked ${extensionName} to ${extensionTarget}`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
package/dist/esm/cli/run.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Command } from 'commander';
|
|
|
2
2
|
import create from './commands/create';
|
|
3
3
|
import add from './commands/add';
|
|
4
4
|
import build from './commands/build';
|
|
5
|
+
import link from './commands/link';
|
|
5
6
|
const pkg = require('../../../package.json');
|
|
6
7
|
const program = new Command();
|
|
7
8
|
program.name('directus-extension').usage('[command] [options]');
|
|
@@ -25,4 +26,9 @@ program
|
|
|
25
26
|
.option('--no-minify', 'disable minification')
|
|
26
27
|
.option('--sourcemap', 'include source maps in output')
|
|
27
28
|
.action(build);
|
|
29
|
+
program
|
|
30
|
+
.command('link')
|
|
31
|
+
.description('Creates a symlink to the extension in the Directus extensions folder')
|
|
32
|
+
.argument('<path>', 'path to the extension folder of directus')
|
|
33
|
+
.action(link);
|
|
28
34
|
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@directus/extensions-sdk",
|
|
3
|
-
"version": "9.22.
|
|
3
|
+
"version": "9.22.3",
|
|
4
4
|
"description": "A toolkit to develop extensions to extend Directus",
|
|
5
5
|
"homepage": "https://directus.io",
|
|
6
6
|
"bugs": {
|
|
@@ -41,33 +41,33 @@
|
|
|
41
41
|
"!**/*.d.ts.map"
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@rollup/plugin-commonjs": "
|
|
45
|
-
"@rollup/plugin-json": "
|
|
44
|
+
"@rollup/plugin-commonjs": "24.0.0",
|
|
45
|
+
"@rollup/plugin-json": "6.0.0",
|
|
46
46
|
"@rollup/plugin-node-resolve": "15.0.1",
|
|
47
|
-
"@rollup/plugin-replace": "5.0.
|
|
48
|
-
"@rollup/plugin-terser": "0.1
|
|
47
|
+
"@rollup/plugin-replace": "5.0.2",
|
|
48
|
+
"@rollup/plugin-terser": "0.2.1",
|
|
49
49
|
"@rollup/plugin-virtual": "3.0.1",
|
|
50
50
|
"@vue/compiler-sfc": "3.2.45",
|
|
51
51
|
"chalk": "4.1.1",
|
|
52
52
|
"commander": "9.4.1",
|
|
53
|
-
"esbuild": "0.
|
|
53
|
+
"esbuild": "0.16.10",
|
|
54
54
|
"execa": "5.1.1",
|
|
55
|
-
"fs-extra": "
|
|
55
|
+
"fs-extra": "11.1.0",
|
|
56
56
|
"inquirer": "8.2.4",
|
|
57
57
|
"ora": "5.4.0",
|
|
58
|
-
"rollup": "3.
|
|
58
|
+
"rollup": "3.7.5",
|
|
59
59
|
"rollup-plugin-esbuild": "5.0.0",
|
|
60
60
|
"rollup-plugin-styles": "4.0.0",
|
|
61
61
|
"rollup-plugin-vue": "6.0.0",
|
|
62
|
-
"@directus/shared": "9.22.
|
|
62
|
+
"@directus/shared": "9.22.2"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@types/fs-extra": "9.0.13",
|
|
66
66
|
"@types/inquirer": "8.2.1",
|
|
67
|
-
"@vitest/coverage-c8": "0.
|
|
68
|
-
"concurrently": "7.
|
|
69
|
-
"typescript": "4.9.
|
|
70
|
-
"vitest": "0.
|
|
67
|
+
"@vitest/coverage-c8": "0.26.2",
|
|
68
|
+
"concurrently": "7.6.0",
|
|
69
|
+
"typescript": "4.9.4",
|
|
70
|
+
"vitest": "0.26.2"
|
|
71
71
|
},
|
|
72
72
|
"engines": {
|
|
73
73
|
"node": ">=12.20.0"
|