Skip to content

Commit c5b43b7

Browse files
fix: Better errors in create-app-bundle.ts [] (#2371)
* fix: Better errors in create-app-bundle.ts * Update packages/contentful--app-scripts/src/upload/create-app-bundle.test.ts Co-authored-by: Jared Jolton <145477871+jjolton-contentful@users.noreply.github.com> --------- Co-authored-by: Jared Jolton <145477871+jjolton-contentful@users.noreply.github.com>
1 parent c86c086 commit c5b43b7

File tree

10 files changed

+81
-43
lines changed

10 files changed

+81
-43
lines changed

packages/contentful--app-scripts/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"contentful-app-scripts": "lib/bin.js"
2626
},
2727
"scripts": {
28-
"prettier": "prettier **/*.js --write --ignore-path .gitignore",
28+
"prettier": "prettier **/*.ts --write --ignore-path .gitignore",
2929
"lint": "eslint ./src",
3030
"lint:fix": "npm run lint -- --fix",
3131
"test": "ts-mocha \"./{,!(node_modules)/**/}*.test.ts\"",

packages/contentful--app-scripts/src/analytics.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Analytics } from '@segment/analytics-node'
1+
import { Analytics } from '@segment/analytics-node';
22

33
// Public write key scoped to data source
44
const SEGMENT_WRITE_KEY = 'IzCq3j4dQlTAgLdMykRW9oBHQKUy1xMm';
@@ -10,16 +10,18 @@ const SEGMENT_WRITE_KEY = 'IzCq3j4dQlTAgLdMykRW9oBHQKUy1xMm';
1010
* @param {boolean} properties.ci value if --ci flag has been set
1111
* @returns
1212
*/
13-
export function track({ command, ci }: { command: string; ci: boolean; }) {
13+
export function track({ command, ci }: { command: string; ci: boolean }) {
1414
if (process.env.DISABLE_ANALYTICS) {
1515
return;
1616
}
1717

1818
try {
1919
const client = new Analytics({
2020
writeKey: SEGMENT_WRITE_KEY,
21-
})
22-
client.on('error', (err) => { /* noop */ })
21+
});
22+
client.on('error', (err) => {
23+
/* noop */
24+
});
2325
client.track({
2426
event: 'app-cli-app-scripts',
2527
properties: {

packages/contentful--app-scripts/src/bin.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ async function runCommand(command: Command, options?: any) {
4848
.description('Upload your build folder and create an AppBundle')
4949
.option('--bundle-dir [directory]', 'The directory of your build folder')
5050
.option('--organization-id [orgId]', 'The id of your organization')
51-
.option('--definition-id [defId]', 'The id of your app\'s definition')
51+
.option('--definition-id [defId]', "The id of your app's definition")
5252
.option('--token [accessToken]', 'Your content management access token')
5353
.option('--comment [comment]', 'Optional comment for the created bundle')
5454
.option('--skip-activation', 'A Boolean flag to skip automatic activation')
@@ -62,7 +62,7 @@ async function runCommand(command: Command, options?: any) {
6262
.description('Mark an AppBundle as "active" for a given AppDefinition')
6363
.option('--bundle-id [bundleId]', 'The id of your bundle')
6464
.option('--organization-id [orgId]', 'The id of your organization')
65-
.option('--definition-id [defId]', 'The id of your app\'s definition')
65+
.option('--definition-id [defId]', "The id of your app's definition")
6666
.option('--token [accessToken]', 'Your content management access token')
6767
.option('--host [host]', 'Contentful subdomain to use, e.g. "api.contentful.com"')
6868
.action(async (options) => {
@@ -72,7 +72,7 @@ async function runCommand(command: Command, options?: any) {
7272
program
7373
.command('open-settings')
7474
.description('Opens the app editor for a given AppDefinition')
75-
.option('--definition-id [defId]', 'The id of your app\'s definition')
75+
.option('--definition-id [defId]', "The id of your app's definition")
7676
.option('--host [host]', 'Contentful subdomain to use, e.g. "api.contentful.com"')
7777
.action(async (options) => {
7878
await runCommand(open, options);
@@ -82,7 +82,7 @@ async function runCommand(command: Command, options?: any) {
8282
.command('bundle-cleanup')
8383
.description('Removes old, non-active bundles, only keeps the 50 most recent ones')
8484
.option('--organization-id [orgId]', 'The id of your organization')
85-
.option('--definition-id [defId]', 'The id of your app\'s definition')
85+
.option('--definition-id [defId]', "The id of your app's definition")
8686
.option('--token [accessToken]', 'Your content management access token')
8787
.option('--keep [keepAmount]', 'The amount of bundles that should remain')
8888
.option('--host [host]', 'Contentful subdomain to use, e.g. "api.contentful.com"')
@@ -102,7 +102,7 @@ async function runCommand(command: Command, options?: any) {
102102
.description(
103103
'Opens a picker to select the space and environment for installing the app associated with a given AppDefinition'
104104
)
105-
.option('--definition-id [defId]', 'The id of your app\'s definition')
105+
.option('--definition-id [defId]', "The id of your app's definition")
106106
.option('--host [host]', 'Contentful subdomain to use, e.g. "api.contentful.com"')
107107
.action(async (options) => {
108108
await runCommand(install, options);
@@ -133,7 +133,7 @@ async function runCommand(command: Command, options?: any) {
133133
.description('Upsert Action(s) for an App')
134134
.option('-m, --manifest-file <path>', 'Contentful app manifest file path')
135135
.option('--organization-id [orgId]', 'The id of your organization')
136-
.option('--definition-id [defId]', 'The id of your app\'s definition')
136+
.option('--definition-id [defId]', "The id of your app's definition")
137137
.option('--token [accessToken]', 'Your content management access token')
138138
.option('--host [host]', 'Contentful subdomain to use, e.g. "api.contentful.com"')
139139
.action(async (options) => {

packages/contentful--app-scripts/src/get-app-info.ts

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,17 @@ import { selectOrganization, getOrganizationById } from './organization-api';
33
import { createClient } from 'contentful-management';
44
import { getManagementToken } from './get-management-token';
55

6-
export const getAppInfo = async (
7-
{
8-
organizationId,
9-
definitionId,
10-
token,
11-
host,
12-
}: {
13-
organizationId?: string;
14-
definitionId?: string;
15-
token?: string;
16-
host?: string;
17-
},
18-
) => {
6+
export const getAppInfo = async ({
7+
organizationId,
8+
definitionId,
9+
token,
10+
host,
11+
}: {
12+
organizationId?: string;
13+
definitionId?: string;
14+
token?: string;
15+
host?: string;
16+
}) => {
1917
const accessToken = token || (await getManagementToken(host));
2018
const client = createClient({ accessToken, host });
2119

packages/contentful--app-scripts/src/organization-api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { ORG_ID_ENV_KEY } from './constants';
44
import { ClientAPI } from 'contentful-management';
55

66
export interface Organization {
7-
name: string,
8-
value: string,
7+
name: string;
8+
value: string;
99
}
1010

1111
async function fetchOrganizations(client: ClientAPI): Promise<Organization[]> {

packages/contentful--app-scripts/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,4 @@ export interface GenerateFunctionSettings {
8787
name: string;
8888
example: string;
8989
language: Language;
90-
}
90+
}

packages/contentful--app-scripts/src/upload/create-app-bundle.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import assert from 'assert';
33
import proxyquire from 'proxyquire';
44
import { AppUpload, ClientAPI } from 'contentful-management';
55
import { UploadSettings } from '../types';
6+
import { processCreateAppBundleError } from './create-app-bundle';
67

78
const bundleMock = { sys: { id: 'mocked_bundle' } };
89
const mockedSettings = {
@@ -116,3 +117,29 @@ describe('createAppBundleFromSettings', () => {
116117
assert.strictEqual(createClientArgs[0].host, 'jane.doe.com');
117118
});
118119
});
120+
121+
describe('processCreateAppBundleError', () => {
122+
it('shows creation error when status is not 403', () => {
123+
const err = new Error('{"status": 404, "message": "Not found"}');
124+
const returnedErr = processCreateAppBundleError(err);
125+
assert.strictEqual(returnedErr, err.message);
126+
})
127+
128+
it('shows creation error when status is 403 and reason is not entitled', () => {
129+
const err = new Error('{"status": 403, "message": "Forbidden", "details": {"reasons": ["Not entitled to App Functions."]}}');
130+
const returnedErr = processCreateAppBundleError(err);
131+
assert.strictEqual(returnedErr, 'Your app seems to be using App Functions, which your organization is not entitled to. Remove your app function, or upgrade your account to proceed with your app upload.');
132+
})
133+
134+
it('shows creation error when status is 403 and reason is feature flag is not enabled', () => {
135+
const err = new Error('{"status": 403, "message": "Forbidden", "details": {"reasons": ["App Functions beta not enabled."]}}');
136+
const returnedErr = processCreateAppBundleError(err);
137+
assert.strictEqual(returnedErr, 'Your app seems to be using App Functions, which your organization has not enabled in the Preview Center. In the Contentful web app, go to the Account Menu → Preview Center → App Functions to enable and proceed with your app upload.');
138+
})
139+
140+
it('shows creation error when status is 403 and reason is unknown', () => {
141+
const err = new Error('{"status": 403, "message": "Forbidden", "details": {"reasons": ["Unknown reason."]}}');
142+
const returnedErr = processCreateAppBundleError(err);
143+
assert.deepEqual(returnedErr, ['Unknown reason.']);
144+
})
145+
});

packages/contentful--app-scripts/src/upload/create-app-bundle.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,33 @@ export async function createAppBundleFromUpload(settings: UploadSettings, appUpl
2727
functions,
2828
});
2929
} catch (err: any) {
30-
try {
31-
const message = JSON.parse(err.message);
32-
if (message['status'] == 403 && message.details?.reasons) {
33-
showCreationError('app upload', message['details']['reasons']);
30+
showCreationError('app upload', processCreateAppBundleError(err))
31+
}
32+
bundleSpinner.stop();
33+
return appBundle;
34+
}
35+
36+
export function processCreateAppBundleError(err: any) {
37+
try {
38+
const message = JSON.parse(err.message);
39+
const reasons = message.details?.reasons;
40+
if (message.status !== 403 || !reasons) {
41+
return err.message
42+
}
43+
if (message['status'] == 403 && message.details?.reasons) {
44+
if (reasons.includes('Not entitled to App Functions.')) {
45+
return 'Your app seems to be using App Functions, which your organization is not entitled to. Remove your app function, or upgrade your account to proceed with your app upload.'
46+
} else if (reasons.includes('App Functions beta not enabled.')) {
47+
return 'Your app seems to be using App Functions, which your organization has not enabled in the Preview Center. In the Contentful web app, go to the Account Menu → Preview Center → App Functions to enable and proceed with your app upload.'
3448
} else {
35-
showCreationError('app upload', message);
49+
return reasons
3650
}
37-
} catch (e) {
38-
showCreationError('app upload', err.message);
51+
} else {
52+
return reasons
3953
}
54+
} catch (e) {
55+
return err.message
4056
}
41-
bundleSpinner.stop();
42-
return appBundle;
4357
}
4458

4559
export async function createAppBundleFromSettings(settings: UploadSettings) {

packages/contentful--app-scripts/src/utils.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,7 @@ export function getFunctionsFromManifest(): Omit<ContentfulFunction, 'entryFile'
129129
return;
130130
}
131131

132-
logProgress(
133-
`functions found in ${chalk.bold(
134-
DEFAULT_MANIFEST_PATH
135-
)}.`
136-
);
132+
logProgress(`functions found in ${chalk.bold(DEFAULT_MANIFEST_PATH)}.`);
137133

138134
const items = (manifest['functions'] as ContentfulFunction[]).map((item) => {
139135
const allowNetworks = Array.isArray(item.allowNetworks)

packages/contentful--app-scripts/src/validate-arguments.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ import chalk from 'chalk';
33
export function validateArguments(
44
requiredOptions: Record<string, string>,
55
options: Record<string, any>,
6-
command?: string,
6+
command?: string
77
) {
88
Object.entries(requiredOptions).forEach(([option, argument]) => {
99
if (!options[option]) {
1010
console.log(
1111
`
1212
${chalk.red('Invalid Arguments:')} the argument ${chalk.cyan(argument)} was not defined.
13-
`);
13+
`
14+
);
1415
if (command) {
1516
console.log(`
1617
Run ${chalk.dim(`npx @contentful/app-scripts ${command} --help`)} to see all required arguments

0 commit comments

Comments
 (0)