@contentful/app-scripts 1.10.2 → 1.12.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 +23 -21
- package/lib/activate/build-bundle-activate-settings.js +18 -10
- package/lib/clean-up/build-clean-up-settings.js +26 -3
- package/lib/clean-up/clean-up-bundles.test.js +2 -2
- package/lib/upload/build-upload-settings.js +23 -4
- package/lib/upload/create-app-bundle.js +5 -4
- package/lib/upload/get-upload-settings-args.js +4 -2
- package/lib/utils.js +30 -24
- package/lib/utils.test.js +139 -14
- package/package.json +7 -7
- package/utils/constants.js +5 -2
package/README.md
CHANGED
|
@@ -106,14 +106,15 @@ When passing the `--ci` argument the command will fail when the required variabl
|
|
|
106
106
|
|
|
107
107
|
**Options:**
|
|
108
108
|
|
|
109
|
-
| Argument | Description |
|
|
110
|
-
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
111
|
-
| `--bundle-dir` | The directory of your build folder (e.g.: `./build`) |
|
|
112
|
-
| `--organization-id` | The ID of your organisation |
|
|
113
|
-
| `--definition-id` | The ID of the app to which to add the bundle |
|
|
114
|
-
| `--token` | A personal [access token](https://www.contentful.com/developers/docs/references/content-management-api/#/reference/personal-access-tokens) |
|
|
115
|
-
| `--skip-activation` | (optional) Boolean flag to skip the automatic activation of the `AppBundle` |
|
|
116
|
-
| `--comment` | (optional) A comment which will be associated with the created `AppBundle`. Can be used to differentiate bundles. |
|
|
109
|
+
| Argument | Description | Default value |
|
|
110
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | - |
|
|
111
|
+
| `--bundle-dir` | The directory of your build folder (e.g.: `./build`) | |
|
|
112
|
+
| `--organization-id` | The ID of your organisation | |
|
|
113
|
+
| `--definition-id` | The ID of the app to which to add the bundle | |
|
|
114
|
+
| `--token` | A personal [access token](https://www.contentful.com/developers/docs/references/content-management-api/#/reference/personal-access-tokens) | |
|
|
115
|
+
| `--skip-activation` | (optional) Boolean flag to skip the automatic activation of the `AppBundle` | `false` |
|
|
116
|
+
| `--comment` | (optional) A comment which will be associated with the created `AppBundle`. Can be used to differentiate bundles. | |
|
|
117
|
+
| `--host` | (optional) Contentful CMA-endpoint to use | `api.contentful.com` |
|
|
117
118
|
|
|
118
119
|
**Note:** You can also pass all arguments in interactive mode to skip being asked for it.
|
|
119
120
|
|
|
@@ -148,12 +149,13 @@ When passing the `--ci` argument adding all variables as arguments is required.
|
|
|
148
149
|
|
|
149
150
|
**Options:**
|
|
150
151
|
|
|
151
|
-
| Argument | Description |
|
|
152
|
-
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
153
|
-
| `--bundle-id` | The ID of the AppBundle you want to activate |
|
|
154
|
-
| `--organization-id` | The ID of your organisation |
|
|
155
|
-
| `--definition-id` | The ID of the app to which to add the bundle |
|
|
156
|
-
| `--token` | A personal [access token](https://www.contentful.com/developers/docs/references/content-management-api/#/reference/personal-access-tokens) |
|
|
152
|
+
| Argument | Description | Default value |
|
|
153
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | --- |
|
|
154
|
+
| `--bundle-id` | The ID of the AppBundle you want to activate | |
|
|
155
|
+
| `--organization-id` | The ID of your organisation | |
|
|
156
|
+
| `--definition-id` | The ID of the app to which to add the bundle | |
|
|
157
|
+
| `--token` | A personal [access token](https://www.contentful.com/developers/docs/references/content-management-api/#/reference/personal-access-tokens) | |
|
|
158
|
+
| `--host` | (optional) Contentful CMA-endpoint to use | `api.contentful.com` |
|
|
157
159
|
|
|
158
160
|
**Note:** You can also pass all arguments in interactive mode to skip being asked for it.
|
|
159
161
|
|
|
@@ -208,13 +210,13 @@ When passing the `--ci` argument adding all variables as arguments is required
|
|
|
208
210
|
|
|
209
211
|
**Options:**
|
|
210
212
|
|
|
211
|
-
| Argument | Description |
|
|
212
|
-
| ------------------- | -------------------------------------------- |
|
|
213
|
-
| `--bundle-id` | The ID of the AppBundle you want to activate |
|
|
214
|
-
| `--organization-id` | The ID of your organisation |
|
|
215
|
-
| `--definition-id` | The ID of the app to which to add the bundle |
|
|
216
|
-
| `--keep` |
|
|
217
|
-
| `--host` |
|
|
213
|
+
| Argument | Description | Default value |
|
|
214
|
+
| ------------------- | -------------------------------------------- | -------------------- |
|
|
215
|
+
| `--bundle-id` | The ID of the AppBundle you want to activate | |
|
|
216
|
+
| `--organization-id` | The ID of your organisation | |
|
|
217
|
+
| `--definition-id` | The ID of the app to which to add the bundle | |
|
|
218
|
+
| `--keep` | (optional) The amount of bundles to keep | `50` |
|
|
219
|
+
| `--host` | (optional) Contentful CMA-endpoint to use | `api.contentful.com` |
|
|
218
220
|
|
|
219
221
|
**Note:** You can also pass all arguments in interactive mode to skip being asked for it.
|
|
220
222
|
|
|
@@ -4,25 +4,33 @@ const inquirer = require('inquirer');
|
|
|
4
4
|
const { getAppInfo } = require('../get-app-info');
|
|
5
5
|
|
|
6
6
|
async function buildBundleActivateSettings(options) {
|
|
7
|
-
|
|
7
|
+
const { bundleId, host } = options;
|
|
8
|
+
const prompts = [];
|
|
9
|
+
|
|
8
10
|
if (!bundleId) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
prompts.push({
|
|
12
|
+
name: 'bundleId',
|
|
13
|
+
message: `The id of the bundle you want to activate (required):`,
|
|
14
|
+
validate: (input) => input.length > 0,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
if (!host) {
|
|
18
|
+
prompts.push({
|
|
19
|
+
name: 'host',
|
|
20
|
+
message: `Contentful CMA endpoint URL:`,
|
|
21
|
+
default: 'api.contentful.com',
|
|
22
|
+
});
|
|
17
23
|
}
|
|
18
24
|
|
|
25
|
+
const appActivateSettings = await inquirer.prompt(prompts);
|
|
19
26
|
const appInfo = await getAppInfo(options);
|
|
20
27
|
|
|
21
28
|
// Add app-config & dialog automatically
|
|
22
29
|
return {
|
|
23
|
-
...appInfo,
|
|
24
30
|
bundleId,
|
|
25
31
|
host,
|
|
32
|
+
...appActivateSettings,
|
|
33
|
+
...appInfo,
|
|
26
34
|
};
|
|
27
35
|
}
|
|
28
36
|
|
|
@@ -1,12 +1,35 @@
|
|
|
1
|
-
const
|
|
1
|
+
const inquirer = require('inquirer');
|
|
2
|
+
const { DEFAULT_BUNDLES_TO_KEEP, CONTENTFUL_API_HOST } = require('../../utils/constants');
|
|
2
3
|
const { getAppInfo } = require('../get-app-info');
|
|
3
4
|
|
|
4
5
|
async function buildCleanUpSettings(options) {
|
|
6
|
+
const { keep, host } = options;
|
|
7
|
+
const prompts = [];
|
|
8
|
+
|
|
9
|
+
if (!keep) {
|
|
10
|
+
prompts.push({
|
|
11
|
+
type: 'number',
|
|
12
|
+
name: 'keep',
|
|
13
|
+
message: `The amount of newest bundles to keep:`,
|
|
14
|
+
default: DEFAULT_BUNDLES_TO_KEEP,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
if (!host) {
|
|
18
|
+
prompts.push({
|
|
19
|
+
name: 'host',
|
|
20
|
+
message: `Contentful CMA endpoint URL:`,
|
|
21
|
+
default: CONTENTFUL_API_HOST,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const appCleanUpSettings = await inquirer.prompt(prompts);
|
|
5
26
|
const appInfo = await getAppInfo(options);
|
|
27
|
+
|
|
6
28
|
return {
|
|
29
|
+
keep: +keep,
|
|
30
|
+
host,
|
|
31
|
+
...appCleanUpSettings,
|
|
7
32
|
...appInfo,
|
|
8
|
-
keep: options.keep !== undefined ? +options.keep : DEFAULT_BUNDLES_TO_KEEP,
|
|
9
|
-
host: options.host,
|
|
10
33
|
};
|
|
11
34
|
}
|
|
12
35
|
|
|
@@ -14,7 +14,7 @@ const bundlesFixture = [
|
|
|
14
14
|
{ sys: { id: 'test-8' } },
|
|
15
15
|
];
|
|
16
16
|
|
|
17
|
-
describe
|
|
17
|
+
describe('cleanUpBundles', () => {
|
|
18
18
|
let subject, clientMock, deleteMock, createClientArgs;
|
|
19
19
|
let mockedBundles = bundlesFixture;
|
|
20
20
|
|
|
@@ -92,7 +92,7 @@ describe.only('cleanUpBundles', () => {
|
|
|
92
92
|
mockedBundles.unshift({ sys: { id: 'slow' } });
|
|
93
93
|
mockedBundles = mockedBundles.reverse();
|
|
94
94
|
clientMock.appBundle.delete = stub().callsFake(
|
|
95
|
-
({ appBundleId }) => new Promise((r) => setTimeout(r, appBundleId === 'slow' ? 200 : 100))
|
|
95
|
+
({ appBundleId }) => new Promise((r) => setTimeout(r, appBundleId === 'slow' ? 200 : 100)),
|
|
96
96
|
);
|
|
97
97
|
subject({ ...mockedSettings, keep: 0 });
|
|
98
98
|
await clock.tickAsync(50);
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
const inquirer = require('inquirer');
|
|
4
4
|
const { getAppInfo } = require('../get-app-info');
|
|
5
|
-
const {
|
|
5
|
+
const { getEntityFromManifest } = require('../utils');
|
|
6
|
+
const { CONTENTFUL_API_HOST } = require('../../utils/constants');
|
|
6
7
|
|
|
7
8
|
async function buildAppUploadSettings(options) {
|
|
8
|
-
const actionsManifest =
|
|
9
|
+
const actionsManifest = getEntityFromManifest('actions');
|
|
10
|
+
const deliveryFnManifest = getEntityFromManifest('deliveryFunctions');
|
|
9
11
|
const prompts = [];
|
|
10
12
|
const { bundleDir, comment, skipActivation, host } = options;
|
|
13
|
+
|
|
11
14
|
if (!bundleDir) {
|
|
12
15
|
prompts.push({
|
|
13
16
|
name: 'bundleDirectory',
|
|
@@ -22,17 +25,33 @@ async function buildAppUploadSettings(options) {
|
|
|
22
25
|
default: '',
|
|
23
26
|
});
|
|
24
27
|
}
|
|
28
|
+
if (skipActivation === undefined) {
|
|
29
|
+
prompts.push({
|
|
30
|
+
type: 'confirm',
|
|
31
|
+
name: 'activateBundle',
|
|
32
|
+
message: `Do you want to activate the bundle after upload?`,
|
|
33
|
+
default: true,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (!host) {
|
|
37
|
+
prompts.push({
|
|
38
|
+
name: 'host',
|
|
39
|
+
message: `Contentful CMA endpoint URL:`,
|
|
40
|
+
default: CONTENTFUL_API_HOST,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
25
43
|
|
|
26
|
-
const appUploadSettings = await inquirer.prompt(prompts);
|
|
44
|
+
const { activateBundle, ...appUploadSettings } = await inquirer.prompt(prompts);
|
|
27
45
|
|
|
28
46
|
const appInfo = await getAppInfo(options);
|
|
29
47
|
// Add app-config & dialog automatically
|
|
30
48
|
return {
|
|
31
49
|
bundleDirectory: bundleDir,
|
|
32
|
-
skipActivation:
|
|
50
|
+
skipActivation: skipActivation === undefined ? !activateBundle : skipActivation,
|
|
33
51
|
comment,
|
|
34
52
|
host,
|
|
35
53
|
actions: actionsManifest,
|
|
54
|
+
deliveryFunctions: deliveryFnManifest,
|
|
36
55
|
...appUploadSettings,
|
|
37
56
|
...appInfo,
|
|
38
57
|
};
|
|
@@ -6,7 +6,7 @@ const { createClient } = require('contentful-management');
|
|
|
6
6
|
const { createAppUpload } = require('./create-app-upload');
|
|
7
7
|
|
|
8
8
|
async function createAppBundleFromUpload(settings, appUploadId) {
|
|
9
|
-
const { accessToken, host, userAgentApplication, comment, actions } = settings;
|
|
9
|
+
const { accessToken, host, userAgentApplication, comment, actions, deliveryFunctions } = settings;
|
|
10
10
|
const clientSpinner = ora('Verifying your upload...').start();
|
|
11
11
|
const client = createClient({
|
|
12
12
|
accessToken,
|
|
@@ -24,6 +24,7 @@ async function createAppBundleFromUpload(settings, appUploadId) {
|
|
|
24
24
|
appUploadId,
|
|
25
25
|
comment: comment && comment.length > 0 ? comment : undefined,
|
|
26
26
|
actions,
|
|
27
|
+
deliveryFunctions,
|
|
27
28
|
});
|
|
28
29
|
} catch (err) {
|
|
29
30
|
showCreationError('app upload', err.message);
|
|
@@ -38,8 +39,8 @@ async function createAppBundleFromSettings(settings) {
|
|
|
38
39
|
appUpload = await createAppUpload(settings);
|
|
39
40
|
console.log(`
|
|
40
41
|
${chalk.yellow('Done!')} Your files were successfully uploaded and a new AppUpload (${chalk.dim(
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
appUpload.sys.id,
|
|
43
|
+
)}) has been created.`);
|
|
43
44
|
} catch (err) {
|
|
44
45
|
showCreationError('app upload', err.message);
|
|
45
46
|
}
|
|
@@ -54,7 +55,7 @@ async function createAppBundleFromSettings(settings) {
|
|
|
54
55
|
|
|
55
56
|
console.log(`
|
|
56
57
|
${chalk.cyan('Success!')} Created a new app bundle for ${chalk.cyan(
|
|
57
|
-
settings.definition.name
|
|
58
|
+
settings.definition.name,
|
|
58
59
|
)} in ${chalk.bold(settings.organization.name)}.
|
|
59
60
|
|
|
60
61
|
Bundle Id: ${chalk.yellow(appBundle.sys.id)}
|
|
@@ -2,7 +2,7 @@ const chalk = require('chalk');
|
|
|
2
2
|
const ora = require('ora');
|
|
3
3
|
const { getAppInfo } = require('../get-app-info');
|
|
4
4
|
const { validateArguments } = require('../validate-arguments');
|
|
5
|
-
const {
|
|
5
|
+
const { getEntityFromManifest } = require('../utils');
|
|
6
6
|
|
|
7
7
|
const requiredOptions = {
|
|
8
8
|
definitionId: '--definition-id',
|
|
@@ -13,7 +13,8 @@ const requiredOptions = {
|
|
|
13
13
|
|
|
14
14
|
async function getUploadSettingsArgs(options) {
|
|
15
15
|
const validateSpinner = ora('Validating your input...').start();
|
|
16
|
-
const actionsManifest =
|
|
16
|
+
const actionsManifest = getEntityFromManifest('actions');
|
|
17
|
+
const deliveryFnManifest = getEntityFromManifest('deliveryFunctions');
|
|
17
18
|
const { bundleDir, comment, skipActivation, host, userAgentApplication } = options;
|
|
18
19
|
|
|
19
20
|
try {
|
|
@@ -27,6 +28,7 @@ async function getUploadSettingsArgs(options) {
|
|
|
27
28
|
host,
|
|
28
29
|
userAgentApplication,
|
|
29
30
|
actions: actionsManifest,
|
|
31
|
+
deliveryFunctions: deliveryFnManifest,
|
|
30
32
|
};
|
|
31
33
|
} catch (err) {
|
|
32
34
|
console.log(`
|
package/lib/utils.js
CHANGED
|
@@ -35,6 +35,14 @@ const showCreationError = (subject, message) => {
|
|
|
35
35
|
`);
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
+
const logProgress = (message) => {
|
|
39
|
+
console.log('');
|
|
40
|
+
console.log(` ----------------------------
|
|
41
|
+
${message}
|
|
42
|
+
----------------------------`);
|
|
43
|
+
console.log('');
|
|
44
|
+
};
|
|
45
|
+
|
|
38
46
|
const throwError = (err, message) => {
|
|
39
47
|
console.log(`
|
|
40
48
|
${chalk.red('Error:')} ${message}.
|
|
@@ -50,10 +58,8 @@ const selectFromList = async (list, message, cachedOptionEnvVar) => {
|
|
|
50
58
|
const cachedElement = list.find((item) => item.value === cachedEnvVar);
|
|
51
59
|
|
|
52
60
|
if (cachedElement) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Using environment variable: ${cachedElement.name} (${chalk.blue(cachedElement.value)})
|
|
56
|
-
`);
|
|
61
|
+
logProgress(`${message}
|
|
62
|
+
Using environment variable: ${cachedElement.name} (${chalk.blue(cachedElement.value)})`);
|
|
57
63
|
return cachedElement;
|
|
58
64
|
} else {
|
|
59
65
|
const { elementId } = await inquirer.prompt([
|
|
@@ -73,7 +79,7 @@ const selectFromList = async (list, message, cachedOptionEnvVar) => {
|
|
|
73
79
|
}
|
|
74
80
|
};
|
|
75
81
|
|
|
76
|
-
function
|
|
82
|
+
function getEntityFromManifest(type) {
|
|
77
83
|
const isManifestExists = fs.existsSync(DEFAULT_MANIFEST_PATH);
|
|
78
84
|
|
|
79
85
|
if (!isManifestExists) {
|
|
@@ -83,29 +89,29 @@ function getActionsManifest() {
|
|
|
83
89
|
try {
|
|
84
90
|
const manifest = JSON.parse(fs.readFileSync(DEFAULT_MANIFEST_PATH, { encoding: 'utf8' }));
|
|
85
91
|
|
|
86
|
-
if (!Array.isArray(manifest
|
|
92
|
+
if (!Array.isArray(manifest[type]) || manifest[type].length === 0) {
|
|
87
93
|
return;
|
|
88
94
|
}
|
|
89
95
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
logProgress(
|
|
97
|
+
`${type === 'actions' ? 'App Actions' : 'Delivery functions'} found in ${chalk.bold(
|
|
98
|
+
DEFAULT_MANIFEST_PATH,
|
|
99
|
+
)}.`,
|
|
100
|
+
);
|
|
95
101
|
|
|
96
|
-
const
|
|
97
|
-
const allowNetworks = Array.isArray(
|
|
98
|
-
?
|
|
102
|
+
const items = manifest[type].map((item) => {
|
|
103
|
+
const allowNetworks = Array.isArray(item.allowNetworks)
|
|
104
|
+
? item.allowNetworks.map(stripProtocol)
|
|
99
105
|
: [];
|
|
100
106
|
|
|
101
107
|
const hasInvalidNetwork = allowNetworks.find((netWork) => !isValidNetwork(netWork));
|
|
102
108
|
if (hasInvalidNetwork) {
|
|
103
109
|
console.log(
|
|
104
110
|
`${chalk.red(
|
|
105
|
-
'Error:'
|
|
106
|
-
)} Invalid IP address ${hasInvalidNetwork} found in the allowNetworks array for
|
|
107
|
-
|
|
108
|
-
}"
|
|
111
|
+
'Error:',
|
|
112
|
+
)} Invalid IP address ${hasInvalidNetwork} found in the allowNetworks array for ${type} "${
|
|
113
|
+
item.name
|
|
114
|
+
}".`,
|
|
109
115
|
);
|
|
110
116
|
// eslint-disable-next-line no-process-exit
|
|
111
117
|
process.exit(1);
|
|
@@ -113,20 +119,20 @@ function getActionsManifest() {
|
|
|
113
119
|
|
|
114
120
|
// EntryFile is not used but we do want to strip it from action
|
|
115
121
|
// eslint-disable-next-line no-unused-vars
|
|
116
|
-
const { entryFile: _, ...
|
|
122
|
+
const { entryFile: _, ...itemWithoutEntryFile } = item;
|
|
117
123
|
|
|
118
124
|
return {
|
|
119
|
-
...
|
|
125
|
+
...itemWithoutEntryFile,
|
|
120
126
|
allowNetworks,
|
|
121
127
|
};
|
|
122
128
|
});
|
|
123
129
|
|
|
124
|
-
return
|
|
130
|
+
return items;
|
|
125
131
|
} catch {
|
|
126
132
|
console.log(
|
|
127
133
|
`${chalk.red('Error:')} Invalid JSON in manifest file at ${chalk.bold(
|
|
128
|
-
DEFAULT_MANIFEST_PATH
|
|
129
|
-
)}
|
|
134
|
+
DEFAULT_MANIFEST_PATH,
|
|
135
|
+
)}.`,
|
|
130
136
|
);
|
|
131
137
|
// eslint-disable-next-line no-process-exit
|
|
132
138
|
process.exit(1);
|
|
@@ -138,7 +144,7 @@ module.exports = {
|
|
|
138
144
|
throwError,
|
|
139
145
|
selectFromList,
|
|
140
146
|
showCreationError,
|
|
141
|
-
|
|
147
|
+
getEntityFromManifest,
|
|
142
148
|
isValidNetwork,
|
|
143
149
|
stripProtocol,
|
|
144
150
|
};
|
package/lib/utils.test.js
CHANGED
|
@@ -68,9 +68,8 @@ describe('removeProtocolFromUrl', () => {
|
|
|
68
68
|
});
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
describe('
|
|
71
|
+
describe('get actions from manifest', () => {
|
|
72
72
|
let fs, exitStub, consoleLog, chalk;
|
|
73
|
-
let DEFAULT_MANIFEST_PATH = 'path/to/manifest';
|
|
74
73
|
|
|
75
74
|
const actionMock = {
|
|
76
75
|
name: 'name',
|
|
@@ -94,7 +93,7 @@ describe('getActionsManifest', () => {
|
|
|
94
93
|
red: stub(),
|
|
95
94
|
};
|
|
96
95
|
|
|
97
|
-
let {
|
|
96
|
+
let { getEntityFromManifest } = proxyquire('./utils', { fs, chalk });
|
|
98
97
|
|
|
99
98
|
beforeEach(() => {
|
|
100
99
|
exitStub = stub(process, 'exit');
|
|
@@ -108,7 +107,7 @@ describe('getActionsManifest', () => {
|
|
|
108
107
|
it('should return undefined if manifest does not exist', () => {
|
|
109
108
|
fs.existsSync.returns(false);
|
|
110
109
|
|
|
111
|
-
const result =
|
|
110
|
+
const result = getEntityFromManifest('actions');
|
|
112
111
|
|
|
113
112
|
assert.equal(result, undefined);
|
|
114
113
|
});
|
|
@@ -117,7 +116,7 @@ describe('getActionsManifest', () => {
|
|
|
117
116
|
fs.existsSync.returns(true);
|
|
118
117
|
fs.readFileSync.returns(JSON.stringify({ actions: [] }));
|
|
119
118
|
|
|
120
|
-
const result =
|
|
119
|
+
const result = getEntityFromManifest('actions');
|
|
121
120
|
assert.equal(result, undefined);
|
|
122
121
|
});
|
|
123
122
|
|
|
@@ -126,10 +125,10 @@ describe('getActionsManifest', () => {
|
|
|
126
125
|
fs.readFileSync.returns(
|
|
127
126
|
JSON.stringify({
|
|
128
127
|
actions: [actionMock],
|
|
129
|
-
})
|
|
128
|
+
}),
|
|
130
129
|
);
|
|
131
130
|
|
|
132
|
-
const result =
|
|
131
|
+
const result = getEntityFromManifest('actions');
|
|
133
132
|
|
|
134
133
|
assert.deepEqual(result, [resultMock]);
|
|
135
134
|
assert.ok(consoleLog.called);
|
|
@@ -146,10 +145,10 @@ describe('getActionsManifest', () => {
|
|
|
146
145
|
fs.readFileSync.returns(
|
|
147
146
|
JSON.stringify({
|
|
148
147
|
actions: [mockAction],
|
|
149
|
-
})
|
|
148
|
+
}),
|
|
150
149
|
);
|
|
151
150
|
|
|
152
|
-
const result =
|
|
151
|
+
const result = getEntityFromManifest('actions');
|
|
153
152
|
|
|
154
153
|
assert.deepEqual(result, [{ ...resultMock, allowNetworks: ['some.domain.tld'] }]);
|
|
155
154
|
assert.ok(consoleLog.called);
|
|
@@ -160,10 +159,10 @@ describe('getActionsManifest', () => {
|
|
|
160
159
|
fs.readFileSync.returns(
|
|
161
160
|
JSON.stringify({
|
|
162
161
|
actions: [actionMock],
|
|
163
|
-
})
|
|
162
|
+
}),
|
|
164
163
|
);
|
|
165
164
|
|
|
166
|
-
const result =
|
|
165
|
+
const result = getEntityFromManifest('actions');
|
|
167
166
|
|
|
168
167
|
assert.notDeepEqual(result, [actionMock]);
|
|
169
168
|
});
|
|
@@ -179,10 +178,10 @@ describe('getActionsManifest', () => {
|
|
|
179
178
|
allowNetworks: ['412.1.1.1'],
|
|
180
179
|
},
|
|
181
180
|
],
|
|
182
|
-
})
|
|
181
|
+
}),
|
|
183
182
|
);
|
|
184
183
|
|
|
185
|
-
|
|
184
|
+
getEntityFromManifest('actions');
|
|
186
185
|
|
|
187
186
|
assert.ok(exitStub.calledOnceWith(1));
|
|
188
187
|
});
|
|
@@ -191,7 +190,133 @@ describe('getActionsManifest', () => {
|
|
|
191
190
|
fs.existsSync.returns(true);
|
|
192
191
|
fs.readFileSync.throws();
|
|
193
192
|
|
|
194
|
-
|
|
193
|
+
getEntityFromManifest('actions');
|
|
194
|
+
|
|
195
|
+
assert.ok(exitStub.calledOnceWith(1));
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe('get delivery functions from manifest', () => {
|
|
200
|
+
let fs, exitStub, consoleLog, chalk;
|
|
201
|
+
|
|
202
|
+
const deliveryFnMock = {
|
|
203
|
+
id: 'test',
|
|
204
|
+
name: 'name',
|
|
205
|
+
description: 'descriptoin',
|
|
206
|
+
path: 'delivery-functions/mock.js',
|
|
207
|
+
entryFile: './delivery-functions/mock.ts',
|
|
208
|
+
allowNetworks: ['127.0.0.1', 'some.domain.tld'],
|
|
209
|
+
};
|
|
210
|
+
// eslint-disable-next-line no-unused-vars
|
|
211
|
+
const { entryFile: _, ...resultMock } = deliveryFnMock;
|
|
212
|
+
|
|
213
|
+
fs = {
|
|
214
|
+
existsSync: stub(),
|
|
215
|
+
readFileSync: stub(),
|
|
216
|
+
};
|
|
217
|
+
chalk = {
|
|
218
|
+
bold: stub(),
|
|
219
|
+
red: stub(),
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
let { getEntityFromManifest } = proxyquire('./utils', { fs, chalk });
|
|
223
|
+
|
|
224
|
+
beforeEach(() => {
|
|
225
|
+
exitStub = stub(process, 'exit');
|
|
226
|
+
consoleLog = stub(console, 'log');
|
|
227
|
+
});
|
|
228
|
+
afterEach(() => {
|
|
229
|
+
exitStub.restore();
|
|
230
|
+
consoleLog.restore();
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('should return undefined if manifest does not exist', () => {
|
|
234
|
+
fs.existsSync.returns(false);
|
|
235
|
+
|
|
236
|
+
const result = getEntityFromManifest('deliveryFunctions');
|
|
237
|
+
|
|
238
|
+
assert.equal(result, undefined);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('should return undefined if manifest has no delivery functions', () => {
|
|
242
|
+
fs.existsSync.returns(true);
|
|
243
|
+
fs.readFileSync.returns(JSON.stringify({ deliveryFunctions: [] }));
|
|
244
|
+
|
|
245
|
+
const result = getEntityFromManifest('deliveryFunctions');
|
|
246
|
+
assert.equal(result, undefined);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('should return an array of delivery functions if manifest is valid', () => {
|
|
250
|
+
fs.existsSync.returns(true);
|
|
251
|
+
fs.readFileSync.returns(
|
|
252
|
+
JSON.stringify({
|
|
253
|
+
deliveryFunctions: [deliveryFnMock],
|
|
254
|
+
}),
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
const result = getEntityFromManifest('deliveryFunctions');
|
|
258
|
+
|
|
259
|
+
assert.deepEqual(result, [resultMock]);
|
|
260
|
+
assert.ok(consoleLog.called);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('should strip the protocol when a domain has a protocol in allowNetworks', () => {
|
|
264
|
+
const mockDeliveryFn = {
|
|
265
|
+
...deliveryFnMock,
|
|
266
|
+
allowNetworks: ['http://some.domain.tld'],
|
|
267
|
+
};
|
|
268
|
+
// eslint-disable-next-line no-unused-vars
|
|
269
|
+
const { entryFile: _, ...resultMock } = mockDeliveryFn;
|
|
270
|
+
fs.existsSync.returns(true);
|
|
271
|
+
fs.readFileSync.returns(
|
|
272
|
+
JSON.stringify({
|
|
273
|
+
deliveryFunctions: [mockDeliveryFn],
|
|
274
|
+
}),
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
const result = getEntityFromManifest('deliveryFunctions');
|
|
278
|
+
|
|
279
|
+
assert.deepEqual(result, [{ ...resultMock, allowNetworks: ['some.domain.tld'] }]);
|
|
280
|
+
assert.ok(consoleLog.called);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('should return an array of delivery functions without entryFile prop if manifest is valid', () => {
|
|
284
|
+
fs.existsSync.returns(true);
|
|
285
|
+
fs.readFileSync.returns(
|
|
286
|
+
JSON.stringify({
|
|
287
|
+
deliveryFunctions: [deliveryFnMock],
|
|
288
|
+
}),
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
const result = getEntityFromManifest('deliveryFunctions');
|
|
292
|
+
|
|
293
|
+
assert.notDeepEqual(result, [deliveryFnMock]);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('should exit with error if invalid network is found in allowNetworks', () => {
|
|
297
|
+
fs.existsSync.returns(true);
|
|
298
|
+
fs.readFileSync.returns(
|
|
299
|
+
JSON.stringify({
|
|
300
|
+
deliveryFunctions: [
|
|
301
|
+
{
|
|
302
|
+
name: 'test resolver fn',
|
|
303
|
+
entryFile: 'entry1',
|
|
304
|
+
allowNetworks: ['412.1.1.1'],
|
|
305
|
+
},
|
|
306
|
+
],
|
|
307
|
+
}),
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
getEntityFromManifest('deliveryFunctions');
|
|
311
|
+
|
|
312
|
+
assert.ok(exitStub.calledOnceWith(1));
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it('should exit with error if manifest is invalid JSON', () => {
|
|
316
|
+
fs.existsSync.returns(true);
|
|
317
|
+
fs.readFileSync.throws();
|
|
318
|
+
|
|
319
|
+
getEntityFromManifest('deliveryFunctions');
|
|
195
320
|
|
|
196
321
|
assert.ok(exitStub.calledOnceWith(1));
|
|
197
322
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/app-scripts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "A collection of scripts for building Contentful Apps",
|
|
5
5
|
"author": "Contentful GmbH",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"prettier": "prettier **/*.js --write --ignore-path .gitignore",
|
|
28
28
|
"lint": "eslint ./lib",
|
|
29
29
|
"lint:fix": "npm run lint -- --fix",
|
|
30
|
-
"test": "mocha ./
|
|
30
|
+
"test": "mocha \"./{,!(node_modules)/**/}*.test.js\" --exit",
|
|
31
31
|
"test:watch": "npm t -- --watch",
|
|
32
32
|
"pre-commit": "lint-staged"
|
|
33
33
|
},
|
|
@@ -52,14 +52,14 @@
|
|
|
52
52
|
"analytics-node": "^6.2.0",
|
|
53
53
|
"bottleneck": "2.19.5",
|
|
54
54
|
"chalk": "4.1.2",
|
|
55
|
-
"commander": "
|
|
56
|
-
"contentful-management": "10.
|
|
57
|
-
"dotenv": "16.
|
|
55
|
+
"commander": "11.0.0",
|
|
56
|
+
"contentful-management": "10.40.0",
|
|
57
|
+
"dotenv": "16.3.1",
|
|
58
58
|
"ignore": "5.2.4",
|
|
59
|
-
"inquirer": "8.2.
|
|
59
|
+
"inquirer": "8.2.6",
|
|
60
60
|
"lodash": "4.17.21",
|
|
61
61
|
"open": "8.4.2",
|
|
62
62
|
"ora": "5.4.1"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "e6ee977c9fc8db111bcd36c8caa1550f4829afb6"
|
|
65
65
|
}
|
package/utils/constants.js
CHANGED
|
@@ -7,12 +7,15 @@ const DEFAULT_BUNDLES_TO_KEEP = 50;
|
|
|
7
7
|
const DEFAULT_BUNDLES_TO_FETCH = 1000;
|
|
8
8
|
const MAX_CONCURRENT_DELETION_CALLS = 5;
|
|
9
9
|
|
|
10
|
+
const DEFAULT_CONTENTFUL_API_HOST = 'api.contentful.com';
|
|
11
|
+
|
|
10
12
|
module.exports = {
|
|
11
13
|
DOTENV_FILE,
|
|
12
|
-
DEFAULT_BUNDLES_TO_KEEP,
|
|
13
14
|
ACCESS_TOKEN_ENV_KEY,
|
|
14
15
|
ORG_ID_ENV_KEY,
|
|
15
16
|
APP_DEF_ENV_KEY,
|
|
16
|
-
|
|
17
|
+
DEFAULT_BUNDLES_TO_KEEP,
|
|
17
18
|
DEFAULT_BUNDLES_TO_FETCH,
|
|
19
|
+
MAX_CONCURRENT_DELETION_CALLS,
|
|
20
|
+
CONTENTFUL_API_HOST: DEFAULT_CONTENTFUL_API_HOST,
|
|
18
21
|
};
|