@contentful/app-scripts 1.33.0 → 2.0.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 +40 -0
- package/lib/bin.js +16 -5
- package/lib/build-functions/build-functions.d.ts +0 -1
- package/lib/build-functions/build-functions.js +5 -10
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -1
- package/lib/types.d.ts +0 -11
- package/lib/upload/build-upload-settings.js +1 -3
- package/lib/upload/create-app-bundle.js +1 -2
- package/lib/upload/get-upload-settings-args.js +1 -3
- package/lib/upload/validate-bundle.d.ts +1 -1
- package/lib/upload/validate-bundle.js +2 -8
- package/lib/upsert-actions/client.d.ts +4 -0
- package/lib/upsert-actions/client.js +37 -0
- package/lib/upsert-actions/get-cli-args.d.ts +2 -0
- package/lib/upsert-actions/get-cli-args.js +40 -0
- package/lib/upsert-actions/index.d.ts +5 -0
- package/lib/upsert-actions/index.js +18 -0
- package/lib/upsert-actions/make-cma-payload.d.ts +2 -0
- package/lib/upsert-actions/make-cma-payload.js +39 -0
- package/lib/upsert-actions/prompt-interactive-args.d.ts +2 -0
- package/lib/upsert-actions/prompt-interactive-args.js +36 -0
- package/lib/upsert-actions/types.d.ts +52 -0
- package/lib/upsert-actions/types.js +2 -0
- package/lib/upsert-actions/upsert-actions.d.ts +16 -0
- package/lib/upsert-actions/upsert-actions.js +80 -0
- package/lib/upsert-actions/validation.d.ts +9 -0
- package/lib/upsert-actions/validation.js +77 -0
- package/lib/utils.d.ts +6 -4
- package/lib/utils.js +16 -8
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -310,3 +310,43 @@ Options:
|
|
|
310
310
|
-m, --manifest-file <path> Contentful app manifest file path
|
|
311
311
|
-w, --watch watch for changes
|
|
312
312
|
-h, --help display help for command
|
|
313
|
+
|
|
314
|
+
### Upsert App Actions
|
|
315
|
+
|
|
316
|
+
Creates or updates Actions for an App using the configuration in a Contentful App Manifest file. Created resources will be synced back to your manifest file.
|
|
317
|
+
|
|
318
|
+
#### Interactive mode:
|
|
319
|
+
|
|
320
|
+
In the interactive mode, the CLI will ask for all required options.
|
|
321
|
+
|
|
322
|
+
> **Example**
|
|
323
|
+
>
|
|
324
|
+
> ```shell
|
|
325
|
+
> $ npx --no-install @contentful/app-scripts upsert-actions
|
|
326
|
+
> ```
|
|
327
|
+
|
|
328
|
+
#### Non-interactive mode:
|
|
329
|
+
|
|
330
|
+
When passing the `--ci` argument adding all variables as arguments is required.
|
|
331
|
+
|
|
332
|
+
> **Example**
|
|
333
|
+
>
|
|
334
|
+
> ```shell
|
|
335
|
+
> $ npx --no-install @contentful/app-scripts upsert-actions --ci \
|
|
336
|
+
> --manifest-file path/to/contentful-app-manifest.json \
|
|
337
|
+
> --organization-id some-org-id \
|
|
338
|
+
> --definition-id some-app-def-id \
|
|
339
|
+
> --token $MY_CONTENTFUL_PAT
|
|
340
|
+
> ```
|
|
341
|
+
|
|
342
|
+
**Options:**
|
|
343
|
+
|
|
344
|
+
| Argument | Description | Default value |
|
|
345
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------ |
|
|
346
|
+
| `--manifest-file` | The path to the Contentful app manifest file | `contentful-app-manifest.json` |
|
|
347
|
+
| `--organization-id` | The ID of the organization which the app is defined in | |
|
|
348
|
+
| `--definition-id` | The ID of the app to which to add the actions | |
|
|
349
|
+
| `--token` | A personal [access token](https://www.contentful.com/developers/docs/references/content-management-api/#/reference/personal-access-tokens) | |
|
|
350
|
+
| `--host` | (optional) Contentful CMA-endpoint to use | `api.contentful.com` |
|
|
351
|
+
|
|
352
|
+
**Note:** You can also pass all arguments in interactive mode to skip being asked for it.
|
package/lib/bin.js
CHANGED
|
@@ -22,7 +22,7 @@ async function runCommand(command, options) {
|
|
|
22
22
|
.description('Upload your build folder and create an AppBundle')
|
|
23
23
|
.option('--bundle-dir [directory]', 'The directory of your build folder')
|
|
24
24
|
.option('--organization-id [orgId]', 'The id of your organization')
|
|
25
|
-
.option('--definition-id [defId]', 'The id of your
|
|
25
|
+
.option('--definition-id [defId]', 'The id of your app\'s definition')
|
|
26
26
|
.option('--token [accessToken]', 'Your content management access token')
|
|
27
27
|
.option('--comment [comment]', 'Optional comment for the created bundle')
|
|
28
28
|
.option('--skip-activation', 'A Boolean flag to skip automatic activation')
|
|
@@ -35,7 +35,7 @@ async function runCommand(command, options) {
|
|
|
35
35
|
.description('Mark an AppBundle as "active" for a given AppDefinition')
|
|
36
36
|
.option('--bundle-id [bundleId]', 'The id of your bundle')
|
|
37
37
|
.option('--organization-id [orgId]', 'The id of your organization')
|
|
38
|
-
.option('--definition-id [defId]', 'The id of your
|
|
38
|
+
.option('--definition-id [defId]', 'The id of your app\'s definition')
|
|
39
39
|
.option('--token [accessToken]', 'Your content management access token')
|
|
40
40
|
.option('--host [host]', 'Contentful subdomain to use, e.g. "api.contentful.com"')
|
|
41
41
|
.action(async (options) => {
|
|
@@ -44,7 +44,7 @@ async function runCommand(command, options) {
|
|
|
44
44
|
commander_1.program
|
|
45
45
|
.command('open-settings')
|
|
46
46
|
.description('Opens the app editor for a given AppDefinition')
|
|
47
|
-
.option('--definition-id [defId]', 'The id of your
|
|
47
|
+
.option('--definition-id [defId]', 'The id of your app\'s definition')
|
|
48
48
|
.option('--host [host]', 'Contentful subdomain to use, e.g. "api.contentful.com"')
|
|
49
49
|
.action(async (options) => {
|
|
50
50
|
await runCommand(index_1.open, options);
|
|
@@ -53,7 +53,7 @@ async function runCommand(command, options) {
|
|
|
53
53
|
.command('bundle-cleanup')
|
|
54
54
|
.description('Removes old, non-active bundles, only keeps the 50 most recent ones')
|
|
55
55
|
.option('--organization-id [orgId]', 'The id of your organization')
|
|
56
|
-
.option('--definition-id [defId]', 'The id of your
|
|
56
|
+
.option('--definition-id [defId]', 'The id of your app\'s definition')
|
|
57
57
|
.option('--token [accessToken]', 'Your content management access token')
|
|
58
58
|
.option('--keep [keepAmount]', 'The amount of bundles that should remain')
|
|
59
59
|
.option('--host [host]', 'Contentful subdomain to use, e.g. "api.contentful.com"')
|
|
@@ -69,7 +69,7 @@ async function runCommand(command, options) {
|
|
|
69
69
|
commander_1.program
|
|
70
70
|
.command('install')
|
|
71
71
|
.description('Opens a picker to select the space and environment for installing the app associated with a given AppDefinition')
|
|
72
|
-
.option('--definition-id [defId]', 'The id of your
|
|
72
|
+
.option('--definition-id [defId]', 'The id of your app\'s definition')
|
|
73
73
|
.option('--host [host]', 'Contentful subdomain to use, e.g. "api.contentful.com"')
|
|
74
74
|
.action(async (options) => {
|
|
75
75
|
await runCommand(index_1.install, options);
|
|
@@ -93,6 +93,17 @@ async function runCommand(command, options) {
|
|
|
93
93
|
.action(async (options) => {
|
|
94
94
|
await runCommand(index_1.generateFunction, options);
|
|
95
95
|
});
|
|
96
|
+
commander_1.program
|
|
97
|
+
.command('upsert-actions')
|
|
98
|
+
.description('Upsert Action(s) for an App')
|
|
99
|
+
.option('-m, --manifest-file <path>', 'Contentful app manifest file path')
|
|
100
|
+
.option('--organization-id [orgId]', 'The id of your organization')
|
|
101
|
+
.option('--definition-id [defId]', 'The id of your app\'s definition')
|
|
102
|
+
.option('--token [accessToken]', 'Your content management access token')
|
|
103
|
+
.option('--host [host]', 'Contentful subdomain to use, e.g. "api.contentful.com"')
|
|
104
|
+
.action(async (options) => {
|
|
105
|
+
await runCommand(index_1.upsertActions, options);
|
|
106
|
+
});
|
|
96
107
|
commander_1.program.hook('preAction', (thisCommand) => {
|
|
97
108
|
(0, index_1.track)({ command: thisCommand.args[0], ci: thisCommand.opts().ci });
|
|
98
109
|
});
|
|
@@ -3,7 +3,6 @@ type ContentfulFunctionToBuild = Omit<ContentfulFunction, 'entryFile'> & {
|
|
|
3
3
|
entryFile: string;
|
|
4
4
|
};
|
|
5
5
|
export declare const validateFunctions: (manifest: Record<string, any>) => void;
|
|
6
|
-
export declare const resolveManifestFile: (options: BuildFunctionsOptions, cwd?: string) => any;
|
|
7
6
|
export declare const resolveEsBuildConfig: (options: BuildFunctionsOptions, manifest: {
|
|
8
7
|
functions: ContentfulFunctionToBuild[];
|
|
9
8
|
}, cwd?: string) => any;
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.resolveEsBuildConfig = exports.
|
|
6
|
+
exports.resolveEsBuildConfig = exports.validateFunctions = void 0;
|
|
7
7
|
exports.buildFunctions = buildFunctions;
|
|
8
8
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
9
9
|
const esbuild_1 = __importDefault(require("esbuild"));
|
|
@@ -11,17 +11,18 @@ const path_1 = require("path");
|
|
|
11
11
|
const node_modules_polyfill_1 = require("@esbuild-plugins/node-modules-polyfill");
|
|
12
12
|
const node_globals_polyfill_1 = require("@esbuild-plugins/node-globals-polyfill");
|
|
13
13
|
const zod_1 = require("zod");
|
|
14
|
+
const utils_1 = require("../utils");
|
|
14
15
|
const functionManifestSchema = zod_1.z
|
|
15
16
|
.object({
|
|
16
17
|
functions: zod_1.z.array(zod_1.z
|
|
17
18
|
.object({
|
|
18
|
-
id: zod_1.z.string(),
|
|
19
|
+
id: zod_1.z.string().regex(utils_1.ID_REGEX, 'Invalid "id" (must only contain alphanumeric characters)'),
|
|
19
20
|
name: zod_1.z.string(),
|
|
20
21
|
description: zod_1.z.string(),
|
|
21
22
|
path: zod_1.z.string(),
|
|
22
23
|
entryFile: zod_1.z.string(),
|
|
23
24
|
accepts: zod_1.z.array(zod_1.z.string()),
|
|
24
|
-
})
|
|
25
|
+
}, {})
|
|
25
26
|
.required()),
|
|
26
27
|
})
|
|
27
28
|
.required();
|
|
@@ -52,12 +53,6 @@ const validateFunctions = (manifest) => {
|
|
|
52
53
|
});
|
|
53
54
|
};
|
|
54
55
|
exports.validateFunctions = validateFunctions;
|
|
55
|
-
const resolveManifestFile = (options, cwd = process.cwd()) => {
|
|
56
|
-
return require(options.manifestFile
|
|
57
|
-
? (0, path_1.resolve)(cwd, options.manifestFile)
|
|
58
|
-
: (0, path_1.resolve)(cwd, 'contentful-app-manifest.json'));
|
|
59
|
-
};
|
|
60
|
-
exports.resolveManifestFile = resolveManifestFile;
|
|
61
56
|
const getEntryPoints = (manifest, cwd = process.cwd()) => {
|
|
62
57
|
return manifest.functions.reduce((result, contentfulFunction) => {
|
|
63
58
|
const fileProperties = (0, path_1.parse)(contentfulFunction.path);
|
|
@@ -85,7 +80,7 @@ const resolveEsBuildConfig = (options, manifest, cwd = process.cwd()) => {
|
|
|
85
80
|
};
|
|
86
81
|
exports.resolveEsBuildConfig = resolveEsBuildConfig;
|
|
87
82
|
async function buildFunctions(options) {
|
|
88
|
-
const manifest = (0,
|
|
83
|
+
const manifest = (0, utils_1.resolveManifestFile)(options);
|
|
89
84
|
try {
|
|
90
85
|
console.log('Building functions');
|
|
91
86
|
(0, exports.validateFunctions)(manifest);
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateFunction = exports.buildFunctions = exports.install = exports.feedback = exports.track = exports.open = exports.cleanup = exports.activate = exports.upload = exports.createAppDefinition = void 0;
|
|
3
|
+
exports.upsertActions = exports.generateFunction = exports.buildFunctions = exports.install = exports.feedback = exports.track = exports.open = exports.cleanup = exports.activate = exports.upload = exports.createAppDefinition = void 0;
|
|
4
4
|
var create_app_definition_1 = require("./create-app-definition");
|
|
5
5
|
Object.defineProperty(exports, "createAppDefinition", { enumerable: true, get: function () { return create_app_definition_1.createAppDefinition; } });
|
|
6
6
|
var upload_1 = require("./upload");
|
|
@@ -21,3 +21,5 @@ var build_functions_1 = require("./build-functions");
|
|
|
21
21
|
Object.defineProperty(exports, "buildFunctions", { enumerable: true, get: function () { return build_functions_1.buildFunctions; } });
|
|
22
22
|
var generate_function_1 = require("./generate-function");
|
|
23
23
|
Object.defineProperty(exports, "generateFunction", { enumerable: true, get: function () { return generate_function_1.generateFunction; } });
|
|
24
|
+
var upsert_actions_1 = require("./upsert-actions");
|
|
25
|
+
Object.defineProperty(exports, "upsertActions", { enumerable: true, get: function () { return upsert_actions_1.upsertActions; } });
|
package/lib/types.d.ts
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
import { Definition } from './definition-api';
|
|
2
2
|
import { Organization } from './organization-api';
|
|
3
|
-
export interface FunctionAppAction {
|
|
4
|
-
id: string;
|
|
5
|
-
name: string;
|
|
6
|
-
description: string;
|
|
7
|
-
category: 'Custom';
|
|
8
|
-
type: 'function';
|
|
9
|
-
path: string;
|
|
10
|
-
allowNetworks?: string[];
|
|
11
|
-
entryFile?: string;
|
|
12
|
-
}
|
|
13
3
|
export interface ContentfulFunction {
|
|
14
4
|
id: string;
|
|
15
5
|
name: string;
|
|
@@ -74,7 +64,6 @@ export interface UploadSettings {
|
|
|
74
64
|
skipActivation?: boolean;
|
|
75
65
|
userAgentApplication?: string;
|
|
76
66
|
host?: string;
|
|
77
|
-
actions?: FunctionAppAction[];
|
|
78
67
|
functions?: ContentfulFunction[];
|
|
79
68
|
}
|
|
80
69
|
export interface BuildFunctionsOptions {
|
|
@@ -7,8 +7,7 @@ const get_app_info_1 = require("../get-app-info");
|
|
|
7
7
|
const utils_1 = require("../utils");
|
|
8
8
|
const constants_1 = require("../constants");
|
|
9
9
|
async function buildAppUploadSettings(options) {
|
|
10
|
-
const
|
|
11
|
-
const functionManifest = (0, utils_1.getEntityFromManifest)('functions');
|
|
10
|
+
const functionManifest = (0, utils_1.getFunctionsFromManifest)();
|
|
12
11
|
const prompts = [];
|
|
13
12
|
const { bundleDir, comment, skipActivation, host } = options;
|
|
14
13
|
if (!bundleDir) {
|
|
@@ -49,7 +48,6 @@ async function buildAppUploadSettings(options) {
|
|
|
49
48
|
skipActivation: skipActivation === undefined ? !activateBundle : skipActivation,
|
|
50
49
|
comment,
|
|
51
50
|
host: hostValue,
|
|
52
|
-
actions: actionsManifest,
|
|
53
51
|
functions: functionManifest,
|
|
54
52
|
...appUploadSettings,
|
|
55
53
|
...appInfo,
|
|
@@ -11,7 +11,7 @@ const utils_1 = require("../utils");
|
|
|
11
11
|
const contentful_management_1 = require("contentful-management");
|
|
12
12
|
const create_app_upload_1 = require("./create-app-upload");
|
|
13
13
|
async function createAppBundleFromUpload(settings, appUploadId) {
|
|
14
|
-
const { accessToken, host, userAgentApplication, comment,
|
|
14
|
+
const { accessToken, host, userAgentApplication, comment, functions } = settings;
|
|
15
15
|
const clientSpinner = (0, ora_1.default)('Verifying your upload...').start();
|
|
16
16
|
const client = (0, contentful_management_1.createClient)({
|
|
17
17
|
accessToken,
|
|
@@ -27,7 +27,6 @@ async function createAppBundleFromUpload(settings, appUploadId) {
|
|
|
27
27
|
appBundle = await appDefinition.createAppBundle({
|
|
28
28
|
appUploadId,
|
|
29
29
|
comment: comment && comment.length > 0 ? comment : undefined,
|
|
30
|
-
actions,
|
|
31
30
|
functions,
|
|
32
31
|
});
|
|
33
32
|
}
|
|
@@ -17,8 +17,7 @@ const requiredOptions = {
|
|
|
17
17
|
};
|
|
18
18
|
async function getUploadSettingsArgs(options) {
|
|
19
19
|
const validateSpinner = (0, ora_1.default)('Validating your input...').start();
|
|
20
|
-
const
|
|
21
|
-
const functionManifest = (0, utils_1.getEntityFromManifest)('functions');
|
|
20
|
+
const functionManifest = (0, utils_1.getFunctionsFromManifest)();
|
|
22
21
|
const { bundleDir, comment, skipActivation, host, userAgentApplication } = options;
|
|
23
22
|
try {
|
|
24
23
|
(0, validate_arguments_1.validateArguments)(requiredOptions, options, 'upload');
|
|
@@ -30,7 +29,6 @@ async function getUploadSettingsArgs(options) {
|
|
|
30
29
|
comment,
|
|
31
30
|
host,
|
|
32
31
|
userAgentApplication,
|
|
33
|
-
actions: actionsManifest,
|
|
34
32
|
functions: functionManifest,
|
|
35
33
|
};
|
|
36
34
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { UploadSettings } from '../types';
|
|
2
|
-
export declare const validateBundle: (path: string, { functions
|
|
2
|
+
export declare const validateBundle: (path: string, { functions }: Pick<UploadSettings, "functions">) => void;
|
|
@@ -13,11 +13,11 @@ const ABSOLUTE_PATH_REG_EXP = /(src|href)="\/([^/])([^"]*)+"/g;
|
|
|
13
13
|
const fileContainsAbsolutePath = (fileContent) => {
|
|
14
14
|
return [...fileContent.matchAll(ABSOLUTE_PATH_REG_EXP)].length > 0;
|
|
15
15
|
};
|
|
16
|
-
const validateBundle = (path, { functions
|
|
16
|
+
const validateBundle = (path, { functions }) => {
|
|
17
17
|
const buildFolder = path_1.default.join('./', path);
|
|
18
18
|
const files = fs_1.default.readdirSync(buildFolder, { recursive: true, encoding: 'utf-8' });
|
|
19
19
|
const entry = getEntryFile(files);
|
|
20
|
-
if (!entry && !functions
|
|
20
|
+
if (!entry && !functions) {
|
|
21
21
|
throw new Error('Ensure your bundle includes a valid index.html file in its root folder, or a valid Contentful Function entrypoint (defined in your contentful-app-manifest.json file).');
|
|
22
22
|
}
|
|
23
23
|
if (entry) {
|
|
@@ -34,11 +34,5 @@ const validateBundle = (path, { functions, actions }) => {
|
|
|
34
34
|
throw new Error(`Function "${functionWithoutEntryFile.id}" is missing its entry file at "${path_1.default.join(buildFolder, functionWithoutEntryFile.path)}".`);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
if (actions) {
|
|
38
|
-
const actionWithoutEntryFile = actions.find(({ path }) => !files.includes(path));
|
|
39
|
-
if (actionWithoutEntryFile) {
|
|
40
|
-
throw new Error(`Action "${actionWithoutEntryFile.id}" is missing its entry file at "${path_1.default.join(buildFolder, actionWithoutEntryFile.path)}".`);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
37
|
};
|
|
44
38
|
exports.validateBundle = validateBundle;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { AppActionProps, CreateAppActionProps, PlainClientAPI } from 'contentful-management';
|
|
2
|
+
export declare function createAction(client: PlainClientAPI, appDefinitionId: string, payload: CreateAppActionProps): Promise<AppActionProps>;
|
|
3
|
+
export declare function getExistingAction(client: PlainClientAPI, appDefinitionId: string, appActionId: string): Promise<AppActionProps | null>;
|
|
4
|
+
export declare function updateAction(client: PlainClientAPI, appDefinitionId: string, appActionId: string, payload: CreateAppActionProps): Promise<AppActionProps>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAction = createAction;
|
|
4
|
+
exports.getExistingAction = getExistingAction;
|
|
5
|
+
exports.updateAction = updateAction;
|
|
6
|
+
const chalk_1 = require("chalk");
|
|
7
|
+
async function createAction(client, appDefinitionId, payload) {
|
|
8
|
+
const action = await client.appAction.create({
|
|
9
|
+
appDefinitionId,
|
|
10
|
+
}, payload);
|
|
11
|
+
console.log(`
|
|
12
|
+
${(0, chalk_1.cyan)('Success!')} Created Action ${(0, chalk_1.cyan)(action.name)} with ID ${(0, chalk_1.cyan)(action.sys.id)} for App ${(0, chalk_1.cyan)(appDefinitionId)}.`);
|
|
13
|
+
return action;
|
|
14
|
+
}
|
|
15
|
+
async function getExistingAction(client, appDefinitionId, appActionId) {
|
|
16
|
+
try {
|
|
17
|
+
return await client.appAction.get({
|
|
18
|
+
appDefinitionId,
|
|
19
|
+
appActionId,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
if (err.name === 'NotFound') {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function updateAction(client, appDefinitionId, appActionId, payload) {
|
|
30
|
+
const action = await client.appAction.update({
|
|
31
|
+
appDefinitionId,
|
|
32
|
+
appActionId,
|
|
33
|
+
}, payload);
|
|
34
|
+
console.log(`
|
|
35
|
+
${(0, chalk_1.cyan)('Success!')} Updated Action ${(0, chalk_1.cyan)(action.name)} with ID ${(0, chalk_1.cyan)(appActionId)} for App ${(0, chalk_1.cyan)(appDefinitionId)}.`);
|
|
36
|
+
return action;
|
|
37
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
exports.getCreateAppActionsArgs = getCreateAppActionsArgs;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const get_app_info_1 = require("../get-app-info");
|
|
10
|
+
const validate_arguments_1 = require("../validate-arguments");
|
|
11
|
+
const requiredOptions = {
|
|
12
|
+
organizationId: '--organization-id',
|
|
13
|
+
definitionId: '--definition-id',
|
|
14
|
+
token: '--token',
|
|
15
|
+
};
|
|
16
|
+
async function getCreateAppActionsArgs(settings) {
|
|
17
|
+
const validateSpinner = (0, ora_1.default)('Validating your input').start();
|
|
18
|
+
try {
|
|
19
|
+
(0, validate_arguments_1.validateArguments)(requiredOptions, settings, 'upsert-actions');
|
|
20
|
+
const appInfo = await (0, get_app_info_1.getAppInfo)(settings);
|
|
21
|
+
return {
|
|
22
|
+
host: settings.host || 'api.contentful.com',
|
|
23
|
+
manifestFile: settings.manifestFile,
|
|
24
|
+
accessToken: settings.token,
|
|
25
|
+
appDefinitionId: appInfo.definition.value,
|
|
26
|
+
organizationId: appInfo.organization.value,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
console.log(`
|
|
31
|
+
${chalk_1.default.red('Validation failed')}
|
|
32
|
+
${err.message}
|
|
33
|
+
`);
|
|
34
|
+
// eslint-disable-next-line no-process-exit
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
validateSpinner.stop();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.upsertActions = void 0;
|
|
4
|
+
const upsert_actions_1 = require("./upsert-actions");
|
|
5
|
+
const get_cli_args_1 = require("./get-cli-args");
|
|
6
|
+
const prompt_interactive_args_1 = require("./prompt-interactive-args");
|
|
7
|
+
const interactive = async (options) => {
|
|
8
|
+
const settings = await (0, prompt_interactive_args_1.promptCreateAppAction)(options);
|
|
9
|
+
await (0, upsert_actions_1.upsertAppActions)(settings);
|
|
10
|
+
};
|
|
11
|
+
const nonInteractive = async (options) => {
|
|
12
|
+
const settings = await (0, get_cli_args_1.getCreateAppActionsArgs)(options);
|
|
13
|
+
await (0, upsert_actions_1.upsertAppActions)(settings);
|
|
14
|
+
};
|
|
15
|
+
exports.upsertActions = {
|
|
16
|
+
interactive,
|
|
17
|
+
nonInteractive,
|
|
18
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeAppActionCMAPayload = makeAppActionCMAPayload;
|
|
4
|
+
function makeAppActionCMAPayload(action) {
|
|
5
|
+
const baseProps = {
|
|
6
|
+
name: action.name,
|
|
7
|
+
...(action.description && { description: action.description }),
|
|
8
|
+
...(action.id && { id: action.id }),
|
|
9
|
+
};
|
|
10
|
+
const additionalPropsByType = action.type === 'function-invocation'
|
|
11
|
+
? {
|
|
12
|
+
type: action.type,
|
|
13
|
+
function: {
|
|
14
|
+
sys: {
|
|
15
|
+
id: action.functionId,
|
|
16
|
+
linkType: 'Function',
|
|
17
|
+
type: 'Link',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
: {
|
|
22
|
+
type: action.type,
|
|
23
|
+
url: action.url,
|
|
24
|
+
};
|
|
25
|
+
const additionalPropsByCategory = action.category === 'Custom'
|
|
26
|
+
? {
|
|
27
|
+
category: action.category,
|
|
28
|
+
parameters: action.parameters,
|
|
29
|
+
}
|
|
30
|
+
: {
|
|
31
|
+
category: action.category,
|
|
32
|
+
};
|
|
33
|
+
const payload = {
|
|
34
|
+
...baseProps,
|
|
35
|
+
...additionalPropsByType,
|
|
36
|
+
...additionalPropsByCategory,
|
|
37
|
+
};
|
|
38
|
+
return payload;
|
|
39
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promptCreateAppAction = promptCreateAppAction;
|
|
4
|
+
const inquirer_1 = require("inquirer");
|
|
5
|
+
const constants_1 = require("../constants");
|
|
6
|
+
const get_app_info_1 = require("../get-app-info");
|
|
7
|
+
async function promptCreateAppAction(options) {
|
|
8
|
+
const { manifestFile, host } = options;
|
|
9
|
+
const prompts = [];
|
|
10
|
+
if (manifestFile === undefined) {
|
|
11
|
+
prompts.push({
|
|
12
|
+
type: 'input',
|
|
13
|
+
name: 'manifestFile',
|
|
14
|
+
message: `Path to your Contentful app manifest file:`,
|
|
15
|
+
default: constants_1.DEFAULT_APP_MANIFEST_PATH,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
if (!host) {
|
|
19
|
+
prompts.push({
|
|
20
|
+
name: 'host',
|
|
21
|
+
message: `Contentful CMA endpoint URL:`,
|
|
22
|
+
default: 'api.contentful.com',
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
const { host: interactiveHost, manifestFile: interactiveManifest } = await (0, inquirer_1.prompt)(prompts);
|
|
26
|
+
const hostValue = host || interactiveHost;
|
|
27
|
+
const manifestFileValue = manifestFile || interactiveManifest;
|
|
28
|
+
const appInfo = await (0, get_app_info_1.getAppInfo)({ ...options, host: hostValue });
|
|
29
|
+
return {
|
|
30
|
+
host: hostValue,
|
|
31
|
+
manifestFile: manifestFileValue,
|
|
32
|
+
appDefinitionId: appInfo.definition.value,
|
|
33
|
+
accessToken: appInfo.accessToken,
|
|
34
|
+
organizationId: appInfo.organization.value,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { AppActionCategoryType, AppActionParameterDefinition } from "contentful-management";
|
|
2
|
+
export type BaseAppActionProps = {
|
|
3
|
+
id?: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
};
|
|
7
|
+
export type FunctionAppActionManifestProps = {
|
|
8
|
+
type: 'function-invocation';
|
|
9
|
+
functionId: string;
|
|
10
|
+
};
|
|
11
|
+
export type EndpointAppActionProps = {
|
|
12
|
+
type: 'endpoint';
|
|
13
|
+
url: string;
|
|
14
|
+
};
|
|
15
|
+
export type CustomCategoryAppActionProps = {
|
|
16
|
+
category: 'Custom';
|
|
17
|
+
parameters: AppActionParameterDefinition[];
|
|
18
|
+
};
|
|
19
|
+
export type BuiltInCategoryAppActionProps = {
|
|
20
|
+
category: Omit<AppActionCategoryType, 'Custom'>;
|
|
21
|
+
};
|
|
22
|
+
type CategoryProps = CustomCategoryAppActionProps | BuiltInCategoryAppActionProps;
|
|
23
|
+
export type FunctionAppActionProps = {
|
|
24
|
+
id?: string;
|
|
25
|
+
type: 'function-invocation';
|
|
26
|
+
function: {
|
|
27
|
+
sys: {
|
|
28
|
+
id: string;
|
|
29
|
+
linkType: string;
|
|
30
|
+
type: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export type AppActionManifest = BaseAppActionProps & (FunctionAppActionManifestProps | EndpointAppActionProps) & CategoryProps;
|
|
35
|
+
export type CreateAppActionPayload = BaseAppActionProps & (FunctionAppActionProps | EndpointAppActionProps) & CategoryProps;
|
|
36
|
+
export type AppActionToCreate = {
|
|
37
|
+
actions: AppActionManifest[];
|
|
38
|
+
};
|
|
39
|
+
export type CreateAppActionOptions = AppActionToCreate & {
|
|
40
|
+
organizationId: string;
|
|
41
|
+
appDefinitionId: string;
|
|
42
|
+
accessToken: string;
|
|
43
|
+
host: string;
|
|
44
|
+
};
|
|
45
|
+
export type CreateAppActionSettings = {
|
|
46
|
+
manifestFile?: string;
|
|
47
|
+
organizationId?: string;
|
|
48
|
+
appDefinitionId?: string;
|
|
49
|
+
accessToken?: string;
|
|
50
|
+
host?: string;
|
|
51
|
+
};
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AppActionProps, PlainClientAPI } from 'contentful-management';
|
|
2
|
+
import { AppActionManifest, CreateAppActionPayload, CreateAppActionSettings } from './types';
|
|
3
|
+
export declare function doUpsert(client: PlainClientAPI, appDefinitionId: string, payload: CreateAppActionPayload): Promise<AppActionProps>;
|
|
4
|
+
export declare function syncUpsertToManifest(manifestActions: AppActionManifest[], actionsToSync: {
|
|
5
|
+
[i: number]: AppActionManifest;
|
|
6
|
+
}, manifest: Record<string, any>, manifestFile: string): void;
|
|
7
|
+
export declare function processActionManifests(actions: AppActionManifest[], doUpsert: (payload: CreateAppActionPayload) => Promise<AppActionProps>): Promise<{
|
|
8
|
+
actionsToSync: {
|
|
9
|
+
[i: number]: AppActionManifest;
|
|
10
|
+
};
|
|
11
|
+
errors: {
|
|
12
|
+
details: any;
|
|
13
|
+
path: (string | number)[];
|
|
14
|
+
}[];
|
|
15
|
+
}>;
|
|
16
|
+
export declare function upsertAppActions(settings: Required<CreateAppActionSettings>): Promise<void>;
|
|
@@ -0,0 +1,80 @@
|
|
|
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
|
+
exports.doUpsert = doUpsert;
|
|
7
|
+
exports.syncUpsertToManifest = syncUpsertToManifest;
|
|
8
|
+
exports.processActionManifests = processActionManifests;
|
|
9
|
+
exports.upsertAppActions = upsertAppActions;
|
|
10
|
+
const chalk_1 = require("chalk");
|
|
11
|
+
const contentful_management_1 = require("contentful-management");
|
|
12
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
|
+
const ora_1 = __importDefault(require("ora"));
|
|
14
|
+
const utils_1 = require("../utils");
|
|
15
|
+
const client_1 = require("./client");
|
|
16
|
+
const make_cma_payload_1 = require("./make-cma-payload");
|
|
17
|
+
const validation_1 = require("./validation");
|
|
18
|
+
async function doUpsert(client, appDefinitionId, payload) {
|
|
19
|
+
if (payload.id) {
|
|
20
|
+
const existingAction = await (0, client_1.getExistingAction)(client, appDefinitionId, payload.id);
|
|
21
|
+
if (existingAction) {
|
|
22
|
+
const { id, ...update } = payload;
|
|
23
|
+
return (0, client_1.updateAction)(client, appDefinitionId, id, update);
|
|
24
|
+
}
|
|
25
|
+
else if (!existingAction && payload.type === 'endpoint') {
|
|
26
|
+
throw new Error(`Action with id ${payload.id} not found. Endpoint actions may not set a custom ID.`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return (0, client_1.createAction)(client, appDefinitionId, payload);
|
|
30
|
+
}
|
|
31
|
+
function syncUpsertToManifest(manifestActions, actionsToSync, manifest, manifestFile) {
|
|
32
|
+
const actions = manifestActions.map((action, i) => {
|
|
33
|
+
const syncedAction = actionsToSync[i];
|
|
34
|
+
return syncedAction || action;
|
|
35
|
+
});
|
|
36
|
+
node_fs_1.default.writeFileSync(manifestFile, JSON.stringify({ ...manifest, actions }, null, 2));
|
|
37
|
+
console.log(`Remote updates synced to your manifest file at ${(0, chalk_1.yellow)(manifestFile)}.`);
|
|
38
|
+
}
|
|
39
|
+
async function processActionManifests(actions, doUpsert) {
|
|
40
|
+
const actionsToSync = {};
|
|
41
|
+
const errors = [];
|
|
42
|
+
for (const i in actions) {
|
|
43
|
+
const action = actions[i];
|
|
44
|
+
const payload = (0, make_cma_payload_1.makeAppActionCMAPayload)(action);
|
|
45
|
+
try {
|
|
46
|
+
const appAction = await doUpsert(payload);
|
|
47
|
+
actionsToSync[i] = {
|
|
48
|
+
...action,
|
|
49
|
+
id: appAction.sys.id,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
errors.push({ details: err, path: ['actions', i] });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { actionsToSync, errors };
|
|
57
|
+
}
|
|
58
|
+
async function upsertAppActions(settings) {
|
|
59
|
+
const { accessToken, appDefinitionId, host, organizationId, manifestFile } = settings;
|
|
60
|
+
const manifest = await (0, utils_1.resolveManifestFile)({ manifestFile });
|
|
61
|
+
const actions = (0, validation_1.validateActionsManifest)(manifest);
|
|
62
|
+
const spinner = (0, ora_1.default)('Creating your app action(s)').start();
|
|
63
|
+
const client = (0, contentful_management_1.createClient)({
|
|
64
|
+
accessToken,
|
|
65
|
+
host,
|
|
66
|
+
}, {
|
|
67
|
+
type: 'plain',
|
|
68
|
+
defaults: {
|
|
69
|
+
organizationId,
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
const { actionsToSync, errors } = await processActionManifests(actions, async (payload) => doUpsert(client, appDefinitionId, payload));
|
|
73
|
+
syncUpsertToManifest(actions, actionsToSync, manifest, manifestFile);
|
|
74
|
+
if (errors.length) {
|
|
75
|
+
const error = new Error(`Failed to upsert actions`);
|
|
76
|
+
Object.assign(error, { details: errors.map(({ details }) => details) });
|
|
77
|
+
(0, utils_1.throwError)(error, 'Failed to upsert actions');
|
|
78
|
+
}
|
|
79
|
+
spinner.stop();
|
|
80
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CreateAppActionOptions as UpsertAppActionOptions } from './types';
|
|
2
|
+
export declare const validateId: (id: string) => {
|
|
3
|
+
ok: boolean;
|
|
4
|
+
message: string;
|
|
5
|
+
} | {
|
|
6
|
+
ok: boolean;
|
|
7
|
+
message?: undefined;
|
|
8
|
+
};
|
|
9
|
+
export declare function validateActionsManifest(manifest: Record<string, any>): UpsertAppActionOptions['actions'];
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
exports.validateId = void 0;
|
|
7
|
+
exports.validateActionsManifest = validateActionsManifest;
|
|
8
|
+
const zod_1 = __importDefault(require("zod"));
|
|
9
|
+
const utils_1 = require("../utils");
|
|
10
|
+
const parametersSchema = zod_1.default
|
|
11
|
+
.array(zod_1.default.object({
|
|
12
|
+
id: zod_1.default.string(),
|
|
13
|
+
name: zod_1.default.string(),
|
|
14
|
+
description: zod_1.default.string().optional(),
|
|
15
|
+
type: zod_1.default.enum(['Symbol', 'Enum', 'Number', 'Boolean']),
|
|
16
|
+
required: zod_1.default.boolean(),
|
|
17
|
+
default: zod_1.default.union([zod_1.default.string(), zod_1.default.number(), zod_1.default.boolean()]).optional(),
|
|
18
|
+
}));
|
|
19
|
+
const validateId = (id) => {
|
|
20
|
+
if (!utils_1.ID_REGEX.test(id)) {
|
|
21
|
+
return {
|
|
22
|
+
ok: false,
|
|
23
|
+
message: `Invalid "id" (must only contain alphanumeric characters). Received: ${id}.`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return { ok: true };
|
|
27
|
+
};
|
|
28
|
+
exports.validateId = validateId;
|
|
29
|
+
function validateActionsManifest(manifest) {
|
|
30
|
+
if (!manifest.actions) {
|
|
31
|
+
throw new Error('Invalid App Action manifest: missing "actions" field');
|
|
32
|
+
}
|
|
33
|
+
const { actions } = manifest;
|
|
34
|
+
if (!Array.isArray(actions)) {
|
|
35
|
+
throw new Error('Invalid App Action manifest: "actions" must be an array');
|
|
36
|
+
}
|
|
37
|
+
const errors = actions.reduce((acc, action) => {
|
|
38
|
+
if (!action.name) {
|
|
39
|
+
acc.push(new Error('Invalid App Action manifest: Actions must define a "name".'));
|
|
40
|
+
}
|
|
41
|
+
if (!action.type) {
|
|
42
|
+
acc.push(new Error('Invalid App Action manifest: Actions must define a "type".'));
|
|
43
|
+
}
|
|
44
|
+
if (!action.category) {
|
|
45
|
+
acc.push(new Error('Invalid App Action manifest: Actions must define a "category".'));
|
|
46
|
+
}
|
|
47
|
+
if (action.type === 'function-invocation' && (!action.functionId || action.url)) {
|
|
48
|
+
acc.push(new Error('Invalid App Action manifest: "function-invocation" Actions must define a "functionId" and may not target a "url".'));
|
|
49
|
+
}
|
|
50
|
+
if (action.type === 'endpoint' && (!action.url || action.functionId)) {
|
|
51
|
+
acc.push(new Error('Invalid App Action manifest: "endpoint" Actions must define a "url" and may not target a "functionId".'));
|
|
52
|
+
}
|
|
53
|
+
if (action.id) {
|
|
54
|
+
const { ok, message } = (0, exports.validateId)(action.id);
|
|
55
|
+
if (!ok) {
|
|
56
|
+
acc.push(new Error(`Invalid App Action manifest: ${message}`));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (action.category !== 'Custom' && action.parameters) {
|
|
60
|
+
acc.push(new Error('Invalid App Action manifest: native Action categories may not define "parameters"'));
|
|
61
|
+
}
|
|
62
|
+
if (action.category === 'Custom' && !action.parameters) {
|
|
63
|
+
acc.push(new Error('Invalid App Action manifest: "Custom" Action categories must define "parameters"'));
|
|
64
|
+
}
|
|
65
|
+
if (action.category === 'Custom' && action.parameters) {
|
|
66
|
+
const parametersValidationResult = parametersSchema.safeParse(action.parameters);
|
|
67
|
+
if (!parametersValidationResult.success) {
|
|
68
|
+
acc.push(new Error(`Invalid App Action manifest: invalid "parameters" - ${JSON.stringify(parametersValidationResult.error.errors)}`));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return acc;
|
|
72
|
+
}, []);
|
|
73
|
+
if (errors.length) {
|
|
74
|
+
throw new Error(errors.map((error) => error.message).join('\n'));
|
|
75
|
+
}
|
|
76
|
+
return actions;
|
|
77
|
+
}
|
package/lib/utils.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { Definition } from './definition-api';
|
|
2
2
|
import { Organization } from './organization-api';
|
|
3
|
-
import { ContentfulFunction
|
|
3
|
+
import { ContentfulFunction } from './types';
|
|
4
4
|
export declare const throwValidationException: (subject: string, message?: string, details?: string) => never;
|
|
5
5
|
export declare const isValidNetwork: (address: string) => boolean;
|
|
6
6
|
export declare const stripProtocol: (url: string) => string;
|
|
7
7
|
export declare const showCreationError: (subject: string, message: string) => void;
|
|
8
8
|
export declare const throwError: (err: Error, message: string) => never;
|
|
9
9
|
export declare const selectFromList: <T extends Definition | Organization>(list: T[], message: string, cachedOptionEnvVar: string) => Promise<T>;
|
|
10
|
-
|
|
11
|
-
export declare function getEntityFromManifest<Type extends 'actions' | 'functions'>(type: Type): Entities<Type> | undefined;
|
|
10
|
+
export declare function getFunctionsFromManifest(): Omit<ContentfulFunction, 'entryFile'>[] | undefined;
|
|
12
11
|
export declare function getWebAppHostname(host: string | undefined): string;
|
|
13
|
-
export {
|
|
12
|
+
export declare const resolveManifestFile: (options: {
|
|
13
|
+
manifestFile?: string;
|
|
14
|
+
}, cwd?: string) => any;
|
|
15
|
+
export declare const ID_REGEX: RegExp;
|
package/lib/utils.js
CHANGED
|
@@ -3,14 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.selectFromList = exports.throwError = exports.showCreationError = exports.stripProtocol = exports.isValidNetwork = exports.throwValidationException = void 0;
|
|
7
|
-
exports.
|
|
6
|
+
exports.ID_REGEX = exports.resolveManifestFile = exports.selectFromList = exports.throwError = exports.showCreationError = exports.stripProtocol = exports.isValidNetwork = exports.throwValidationException = void 0;
|
|
7
|
+
exports.getFunctionsFromManifest = getFunctionsFromManifest;
|
|
8
8
|
exports.getWebAppHostname = getWebAppHostname;
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
10
|
const chalk_1 = __importDefault(require("chalk"));
|
|
11
11
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
12
12
|
const cache_credential_1 = require("./cache-credential");
|
|
13
13
|
const constants_1 = require("./constants");
|
|
14
|
+
const node_path_1 = require("node:path");
|
|
14
15
|
const DEFAULT_MANIFEST_PATH = './contentful-app-manifest.json';
|
|
15
16
|
const functionEvents = {
|
|
16
17
|
appActionCall: 'appaction.call',
|
|
@@ -105,18 +106,18 @@ const selectFromList = async (list, message, cachedOptionEnvVar) => {
|
|
|
105
106
|
}
|
|
106
107
|
};
|
|
107
108
|
exports.selectFromList = selectFromList;
|
|
108
|
-
function
|
|
109
|
+
function getFunctionsFromManifest() {
|
|
109
110
|
const isManifestExists = fs_1.default.existsSync(DEFAULT_MANIFEST_PATH);
|
|
110
111
|
if (!isManifestExists) {
|
|
111
112
|
return;
|
|
112
113
|
}
|
|
113
114
|
try {
|
|
114
115
|
const manifest = JSON.parse(fs_1.default.readFileSync(DEFAULT_MANIFEST_PATH, { encoding: 'utf8' }));
|
|
115
|
-
if (!Array.isArray(manifest[
|
|
116
|
+
if (!Array.isArray(manifest['functions']) || manifest['functions'].length === 0) {
|
|
116
117
|
return;
|
|
117
118
|
}
|
|
118
|
-
logProgress(
|
|
119
|
-
const items = manifest[
|
|
119
|
+
logProgress(`functions found in ${chalk_1.default.bold(DEFAULT_MANIFEST_PATH)}.`);
|
|
120
|
+
const items = manifest['functions'].map((item) => {
|
|
120
121
|
const allowNetworks = Array.isArray(item.allowNetworks)
|
|
121
122
|
? item.allowNetworks.map(exports.stripProtocol)
|
|
122
123
|
: [];
|
|
@@ -124,12 +125,12 @@ function getEntityFromManifest(type) {
|
|
|
124
125
|
const hasInvalidEvent = accepts?.some((event) => !Object.values(functionEvents).includes(event));
|
|
125
126
|
const hasInvalidNetwork = allowNetworks.find((netWork) => !(0, exports.isValidNetwork)(netWork));
|
|
126
127
|
if (hasInvalidNetwork) {
|
|
127
|
-
console.log(`${chalk_1.default.red('Error:')} Invalid IP address ${hasInvalidNetwork} found in the allowNetworks array for
|
|
128
|
+
console.log(`${chalk_1.default.red('Error:')} Invalid IP address ${hasInvalidNetwork} found in the allowNetworks array for Function "${item.name}".`);
|
|
128
129
|
// eslint-disable-next-line no-process-exit
|
|
129
130
|
process.exit(1);
|
|
130
131
|
}
|
|
131
132
|
if (hasInvalidEvent) {
|
|
132
|
-
console.log(`${chalk_1.default.red('Error:')} Invalid events found in the accepts array for
|
|
133
|
+
console.log(`${chalk_1.default.red('Error:')} Invalid events found in the accepts array for Function "${item.name}".`);
|
|
133
134
|
// eslint-disable-next-line no-process-exit
|
|
134
135
|
process.exit(1);
|
|
135
136
|
}
|
|
@@ -153,3 +154,10 @@ function getEntityFromManifest(type) {
|
|
|
153
154
|
function getWebAppHostname(host) {
|
|
154
155
|
return host && host.includes('api') ? host.replace('api', 'app') : constants_1.DEFAULT_CONTENTFUL_APP_HOST;
|
|
155
156
|
}
|
|
157
|
+
const resolveManifestFile = (options, cwd = process.cwd()) => {
|
|
158
|
+
return require(options.manifestFile
|
|
159
|
+
? (0, node_path_1.resolve)(cwd, options.manifestFile)
|
|
160
|
+
: (0, node_path_1.resolve)(cwd, 'contentful-app-manifest.json'));
|
|
161
|
+
};
|
|
162
|
+
exports.resolveManifestFile = resolveManifestFile;
|
|
163
|
+
exports.ID_REGEX = /^[a-zA-Z0-9]+$/;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/app-scripts",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A collection of scripts for building Contentful Apps",
|
|
5
5
|
"author": "Contentful GmbH",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"directory": "packages/contentful--app-scripts"
|
|
11
11
|
},
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=
|
|
14
|
-
"npm": ">=
|
|
13
|
+
"node": ">=18",
|
|
14
|
+
"npm": ">=9"
|
|
15
15
|
},
|
|
16
16
|
"main": "lib/index.js",
|
|
17
17
|
"types": "lib/index.d.ts",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"tiged": "^2.12.7",
|
|
68
68
|
"zod": "^3.24.1"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "b978a5b14bd327dafbd4349fbc6b624eaffb5e05",
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/adm-zip": "0.5.7",
|
|
73
73
|
"@types/analytics-node": "3.1.14",
|
|
@@ -76,12 +76,12 @@
|
|
|
76
76
|
"@types/lodash": "4.17.15",
|
|
77
77
|
"@types/mocha": "10.0.10",
|
|
78
78
|
"@types/proxyquire": "1.3.31",
|
|
79
|
-
"@types/sinon": "17.0.
|
|
79
|
+
"@types/sinon": "17.0.4",
|
|
80
80
|
"chai": "4.5.0",
|
|
81
81
|
"mocha": "10.8.2",
|
|
82
82
|
"proxyquire": "2.1.3",
|
|
83
83
|
"sinon": "19.0.2",
|
|
84
|
-
"ts-mocha": "
|
|
84
|
+
"ts-mocha": "11.1.0",
|
|
85
85
|
"ts-node": "10.9.2"
|
|
86
86
|
}
|
|
87
87
|
}
|