@contentful/app-scripts 2.2.0 → 2.3.1

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.
@@ -0,0 +1,2 @@
1
+ import { AddLocationsSettings } from '../types';
2
+ export declare function add(settings: AddLocationsSettings): Promise<void>;
@@ -0,0 +1,53 @@
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.add = add;
7
+ const ora_1 = __importDefault(require("ora"));
8
+ const chalk_1 = require("chalk");
9
+ const utils_1 = require("../utils");
10
+ const contentful_management_1 = require("contentful-management");
11
+ const create_type_safe_locations_1 = require("../create-type-safe-locations");
12
+ async function add(settings) {
13
+ const { accessToken, organization, definition, host } = settings;
14
+ const activationSpinner = (0, ora_1.default)('Adding locations').start();
15
+ const plainClient = (0, contentful_management_1.createClient)({ accessToken, host }, { type: 'plain' });
16
+ const defaultLocations = [{ location: 'dialog' }];
17
+ try {
18
+ const currentDefinition = await plainClient.appDefinition.get({
19
+ appDefinitionId: definition.value,
20
+ organizationId: organization.value,
21
+ });
22
+ const typeSafeLocations = (0, create_type_safe_locations_1.createTypeSafeLocations)(settings);
23
+ currentDefinition.locations = [
24
+ ...(currentDefinition.locations ?? defaultLocations),
25
+ ...typeSafeLocations,
26
+ ];
27
+ const appBundleId = currentDefinition.bundle?.sys.id;
28
+ const currentBundle = appBundleId ? await plainClient.appBundle.get({
29
+ appDefinitionId: definition.value,
30
+ appBundleId,
31
+ organizationId: organization.value,
32
+ }) : await Promise.resolve(undefined);
33
+ const hasFrontendFiles = (currentBundle?.files?.length ?? 0) > 0;
34
+ const hasSrc = !!currentDefinition.src;
35
+ const useDefaultSrc = !hasFrontendFiles && !hasSrc;
36
+ if (useDefaultSrc) {
37
+ currentDefinition.src = 'http://localhost:3000';
38
+ }
39
+ await plainClient.appDefinition.update({
40
+ appDefinitionId: definition.value,
41
+ organizationId: organization.value,
42
+ }, currentDefinition);
43
+ console.log(`
44
+ ${(0, chalk_1.cyan)('Success!')} Your locations were added to ${(0, chalk_1.cyan)(definition.name)}
45
+ Locations: ${(0, chalk_1.yellow)(typeSafeLocations.map((l) => (0, chalk_1.bold)(l.location)).join(', '))}`);
46
+ }
47
+ catch (err) {
48
+ (0, utils_1.throwError)(err, 'Something went wrong addding locations. Make sure you used the correct definition-id.');
49
+ }
50
+ finally {
51
+ activationSpinner.stop();
52
+ }
53
+ }
@@ -0,0 +1,3 @@
1
+ import { AddLocationsOptions, AddLocationsSettings } from '../types';
2
+ export declare function buildAddLocationsSettings(options: AddLocationsOptions): Promise<AddLocationsSettings>;
3
+ export declare function hostProtocolFilter(input: string): string;
@@ -0,0 +1,65 @@
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.buildAddLocationsSettings = buildAddLocationsSettings;
7
+ exports.hostProtocolFilter = hostProtocolFilter;
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const inquirer_1 = require("inquirer");
10
+ const get_app_info_1 = require("../get-app-info");
11
+ const constants_1 = require("../constants");
12
+ const location_prompts_1 = require("../location-prompts");
13
+ async function buildAddLocationsSettings(options) {
14
+ const appPrompts = [];
15
+ const { host } = options;
16
+ if (!host) {
17
+ appPrompts.push({
18
+ name: 'host',
19
+ message: `Contentful CMA endpoint URL:`,
20
+ default: constants_1.DEFAULT_CONTENTFUL_API_HOST,
21
+ filter: hostProtocolFilter,
22
+ });
23
+ }
24
+ const { host: interactiveHost } = await (0, inquirer_1.prompt)(appPrompts);
25
+ const hostValue = host || interactiveHost;
26
+ const appInfo = await (0, get_app_info_1.getAppInfo)({ ...options, host: hostValue });
27
+ const locationPrompts = [];
28
+ const currentLocations = new Set(appInfo.definition.locations);
29
+ const possibleLocations = location_prompts_1.selectLocationsPrompt.choices.filter((locationChoice) => !currentLocations.has(locationChoice.value));
30
+ if (possibleLocations.length === 0) {
31
+ console.log(`${chalk_1.default.red('No locations to add')}`);
32
+ // eslint-disable-next-line no-process-exit
33
+ process.exit(1);
34
+ }
35
+ if (possibleLocations.length > 0) {
36
+ locationPrompts.push({
37
+ ...location_prompts_1.selectLocationsPrompt,
38
+ choices: possibleLocations,
39
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
+ validate(input) {
41
+ if (input.length < 1) {
42
+ return 'You must choose at least one location to add.';
43
+ }
44
+ return true;
45
+ },
46
+ });
47
+ if (possibleLocations.some((location) => location.value === 'entry-field')) {
48
+ locationPrompts.push({ ...location_prompts_1.selectFieldsPrompt });
49
+ }
50
+ if (possibleLocations.some((location) => location.value === 'page')) {
51
+ locationPrompts.push({ ...location_prompts_1.pageNavPrompt });
52
+ locationPrompts.push({ ...location_prompts_1.pageNavLinkNamePrompt });
53
+ locationPrompts.push({ ...location_prompts_1.pageNavLinkPathPrompt });
54
+ }
55
+ }
56
+ const addLocationSettings = await (0, inquirer_1.prompt)(locationPrompts);
57
+ return {
58
+ host: hostValue,
59
+ ...addLocationSettings,
60
+ ...appInfo,
61
+ };
62
+ }
63
+ function hostProtocolFilter(input) {
64
+ return input.replace(/^https?:\/\//, '');
65
+ }
@@ -0,0 +1,5 @@
1
+ import { AddLocationsOptions } from "../types";
2
+ export declare const addLocations: {
3
+ interactive: (options: AddLocationsOptions) => Promise<void>;
4
+ nonInteractive: () => Promise<never>;
5
+ };
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addLocations = void 0;
4
+ const add_locations_1 = require("./add-locations");
5
+ const build_add_locations_settings_1 = require("./build-add-locations-settings");
6
+ const interactive = async (options) => {
7
+ const settings = await (0, build_add_locations_settings_1.buildAddLocationsSettings)(options);
8
+ await (0, add_locations_1.add)(settings);
9
+ };
10
+ const nonInteractive = async () => {
11
+ throw new Error(`"add-locations" is not available in non-interactive mode`);
12
+ };
13
+ exports.addLocations = {
14
+ interactive,
15
+ nonInteractive,
16
+ };
package/lib/bin.js CHANGED
@@ -103,6 +103,16 @@ async function runCommand(command, options) {
103
103
  .action(async (options) => {
104
104
  await runCommand(index_1.upsertActions, options);
105
105
  });
106
+ commander_1.program
107
+ .command('add-locations')
108
+ .description('Add locations(s) to an App')
109
+ .option('--organization-id [orgId]', 'The id of your organization')
110
+ .option('--definition-id [defId]', "The id of your app's definition")
111
+ .option('--token [accessToken]', 'Your content management access token')
112
+ .option('--host [host]', 'Contentful subdomain to use, e.g. "api.contentful.com"')
113
+ .action(async (options) => {
114
+ await runCommand(index_1.addLocations, options);
115
+ });
106
116
  commander_1.program.hook('preAction', (thisCommand) => {
107
117
  (0, index_1.track)({ command: thisCommand.args[0], ci: thisCommand.opts().ci });
108
118
  });
@@ -1,16 +1,2 @@
1
- import { AppLocation, FieldType, ParameterDefinition, InstallationParameterType } from 'contentful-management';
2
- export interface AppDefinitionSettings {
3
- name: string;
4
- locations: AppLocation['location'][];
5
- fields?: FieldType[];
6
- pageNav?: boolean;
7
- pageNavLinkName?: string;
8
- pageNavLinkPath?: string;
9
- host?: string;
10
- buildAppParameters: boolean;
11
- parameters?: {
12
- instance: ParameterDefinition[];
13
- installation: ParameterDefinition<InstallationParameterType>[];
14
- };
15
- }
1
+ import { AppDefinitionSettings } from '../types';
16
2
  export declare function buildAppDefinitionSettings(): Promise<AppDefinitionSettings>;
@@ -9,6 +9,7 @@ const inquirer_1 = __importDefault(require("inquirer"));
9
9
  const node_path_1 = __importDefault(require("node:path"));
10
10
  const constants_1 = require("../constants");
11
11
  const build_app_parameter_settings_1 = require("./build-app-parameter-settings");
12
+ const location_prompts_1 = require("../location-prompts");
12
13
  async function buildAppDefinitionSettings() {
13
14
  console.log(chalk_1.default.dim(`
14
15
  NOTE: This will create an app definition in your Contentful organization.
@@ -20,103 +21,11 @@ NOTE: This will create an app definition in your Contentful organization.
20
21
  name: 'name',
21
22
  message: `App name (${node_path_1.default.basename(process.cwd())}):`,
22
23
  },
23
- {
24
- name: 'locations',
25
- message: `Select where your app can be rendered:`,
26
- type: 'checkbox',
27
- choices: [
28
- { name: 'App configuration screen ', value: 'app-config' },
29
- { name: 'Entry field', value: 'entry-field' },
30
- { name: 'Entry sidebar', value: 'entry-sidebar' },
31
- { name: 'Entry editor', value: 'entry-editor' },
32
- { name: 'Page', value: 'page' },
33
- { name: 'Home', value: 'home' },
34
- ],
35
- },
36
- {
37
- name: 'fields',
38
- message: 'Select the field types the app can be rendered:',
39
- type: 'checkbox',
40
- choices: [
41
- { name: 'Short text', value: { type: 'Symbol' } },
42
- { name: 'Short text, list', value: { type: 'Array', items: { type: 'Symbol' } } },
43
- { name: 'Long text', value: { type: 'Text' } },
44
- { name: 'Rich text', value: { type: 'RichText' } },
45
- { name: 'Number, integer', value: { type: 'Integer' } },
46
- { name: 'Number, decimal', value: { type: 'Number' } },
47
- { name: 'Date and time', value: { type: 'Date' } },
48
- { name: 'Location', value: { type: 'Location' } },
49
- { name: 'Boolean', value: { type: 'Boolean' } },
50
- { name: 'JSON object', value: { type: 'Object' } },
51
- { name: 'Entry reference', value: { type: 'Link', linkType: 'Entry' } },
52
- {
53
- name: 'Entry reference, list',
54
- value: {
55
- type: 'Array',
56
- items: {
57
- type: 'Link',
58
- linkType: 'Entry',
59
- },
60
- },
61
- },
62
- { name: 'Media reference', value: { type: 'Link', linkType: 'Asset' } },
63
- {
64
- name: 'Media reference, list',
65
- value: { type: 'Array', items: { type: 'Link', linkType: 'Asset' } },
66
- },
67
- ],
68
- when(answers) {
69
- return answers.locations.includes('entry-field');
70
- },
71
- validate(input) {
72
- if (input.length < 1) {
73
- return 'You must choose at least one field type.';
74
- }
75
- return true;
76
- },
77
- },
78
- {
79
- name: 'pageNav',
80
- message: 'Page location: Would you like your page location to render in the main navigation?',
81
- type: 'confirm',
82
- default: false,
83
- when(answers) {
84
- return answers.locations.includes('page');
85
- },
86
- },
87
- {
88
- name: 'pageNavLinkName',
89
- message: 'Page location: Provide a name for the link in the main navigation:',
90
- when(answers) {
91
- return answers.locations.includes('page') && answers.pageNav;
92
- },
93
- validate(input) {
94
- if (input.length < 1 || input.length > 40) {
95
- return 'Size must be at least 1 and at most 40';
96
- }
97
- return true;
98
- },
99
- },
100
- {
101
- name: 'pageNavLinkPath',
102
- message: 'Page location: Provide a path which starts with / and does not contain empty space:',
103
- default: '/',
104
- when(answers) {
105
- return answers.locations.includes('page') && answers.pageNav;
106
- },
107
- validate(input) {
108
- if (input.length > 512) {
109
- return 'Maximum 512 characters';
110
- }
111
- if (input.includes(' ')) {
112
- return 'Path cannot contain empty space';
113
- }
114
- if (!input.startsWith('/')) {
115
- return 'Path must start with /';
116
- }
117
- return true;
118
- },
119
- },
24
+ { ...location_prompts_1.selectLocationsPrompt },
25
+ { ...location_prompts_1.selectFieldsPrompt },
26
+ { ...location_prompts_1.pageNavPrompt },
27
+ { ...location_prompts_1.pageNavLinkNamePrompt },
28
+ { ...location_prompts_1.pageNavLinkPathPrompt },
120
29
  {
121
30
  name: 'host',
122
31
  message: `Contentful CMA endpoint URL:`,
@@ -1,2 +1,2 @@
1
- import { AppDefinitionSettings } from './build-app-definition-settings';
1
+ import { AppDefinitionSettings } from '../types';
2
2
  export declare function createAppDefinition(accessToken: string, appDefinitionSettings: AppDefinitionSettings): Promise<void>;
@@ -11,6 +11,7 @@ const lodash_1 = require("lodash");
11
11
  const utils_1 = require("../utils");
12
12
  const cache_credential_1 = require("../cache-credential");
13
13
  const constants_1 = require("../constants");
14
+ const create_type_safe_locations_1 = require("../create-type-safe-locations");
14
15
  async function fetchOrganizations(client) {
15
16
  try {
16
17
  const orgs = await client.getOrganizations();
@@ -48,31 +49,7 @@ async function createAppDefinition(accessToken, appDefinitionSettings) {
48
49
  const selectedOrg = await (0, utils_1.selectFromList)(organizations, 'Select an organization for your app:', constants_1.ORG_ID_ENV_KEY);
49
50
  const organizationId = selectedOrg.value;
50
51
  const appName = appDefinitionSettings.name || node_path_1.default.basename(process.cwd());
51
- const locations = appDefinitionSettings.locations.map((location) => {
52
- if (location === 'entry-field') {
53
- return {
54
- location,
55
- fieldTypes: appDefinitionSettings.fields || [],
56
- };
57
- }
58
- if (location === 'page') {
59
- const { pageNav, pageNavLinkName, pageNavLinkPath } = appDefinitionSettings;
60
- return {
61
- location,
62
- ...(pageNav
63
- ? {
64
- navigationItem: {
65
- name: pageNavLinkName,
66
- path: pageNavLinkPath,
67
- },
68
- }
69
- : {}),
70
- };
71
- }
72
- return {
73
- location,
74
- };
75
- });
52
+ const locations = (0, create_type_safe_locations_1.createTypeSafeLocations)(appDefinitionSettings);
76
53
  const hasFrontendLocation = locations.some(({ location }) => location !== 'dialog');
77
54
  const body = {
78
55
  name: appName,
@@ -0,0 +1,15 @@
1
+ import { LocationsSettings } from './types';
2
+ export declare function createTypeSafeLocations(settings: LocationsSettings): ({
3
+ location: "entry-field";
4
+ fieldTypes: import("contentful-management").FieldType[];
5
+ } | {
6
+ navigationItem?: {
7
+ name: string | undefined;
8
+ path: string | undefined;
9
+ } | undefined;
10
+ location: "page";
11
+ fieldTypes?: undefined;
12
+ } | {
13
+ location: "app-config" | "entry-sidebar" | "entry-editor" | "dialog" | "home";
14
+ fieldTypes?: undefined;
15
+ })[];
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTypeSafeLocations = createTypeSafeLocations;
4
+ function createTypeSafeLocations(settings) {
5
+ const { locations, fields, pageNav, pageNavLinkName, pageNavLinkPath } = settings;
6
+ return locations.map((location) => {
7
+ if (location === 'entry-field') {
8
+ return {
9
+ location,
10
+ fieldTypes: fields || [],
11
+ };
12
+ }
13
+ if (location === 'page') {
14
+ return {
15
+ location,
16
+ ...(pageNav
17
+ ? {
18
+ navigationItem: {
19
+ name: pageNavLinkName,
20
+ path: pageNavLinkPath,
21
+ },
22
+ }
23
+ : {}),
24
+ };
25
+ }
26
+ return {
27
+ location,
28
+ };
29
+ });
30
+ }
@@ -2,6 +2,7 @@ import { ClientAPI } from 'contentful-management';
2
2
  export interface Definition {
3
3
  name: string;
4
4
  value: string;
5
+ locations: string[];
5
6
  }
6
7
  export declare function selectDefinition(client: ClientAPI, orgId: string): Promise<Definition>;
7
8
  export declare function getDefinitionById(client: ClientAPI, orgId: string, defId: string): Promise<Definition>;
@@ -23,6 +23,7 @@ async function fetchDefinitions(client, orgId) {
23
23
  return batchedAppDefinitions.map((def) => ({
24
24
  name: def.name,
25
25
  value: def.sys.id,
26
+ locations: def.locations ? def.locations.map((location) => location.location) : [],
26
27
  }));
27
28
  }
28
29
  catch (err) {
@@ -42,6 +43,9 @@ async function getDefinitionById(client, orgId, defId) {
42
43
  return {
43
44
  name: definition.name,
44
45
  value: definition.sys.id,
46
+ locations: definition.locations
47
+ ? definition.locations.map((location) => location.location)
48
+ : [],
45
49
  };
46
50
  }
47
51
  catch (err) {
package/lib/index.d.ts CHANGED
@@ -9,3 +9,4 @@ export { install } from './install';
9
9
  export { buildFunctions } from './build-functions';
10
10
  export { generateFunction } from './generate-function';
11
11
  export { upsertActions } from './upsert-actions';
12
+ export { addLocations } from './add-locations';
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
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;
3
+ exports.addLocations = 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");
@@ -23,3 +23,5 @@ var generate_function_1 = require("./generate-function");
23
23
  Object.defineProperty(exports, "generateFunction", { enumerable: true, get: function () { return generate_function_1.generateFunction; } });
24
24
  var upsert_actions_1 = require("./upsert-actions");
25
25
  Object.defineProperty(exports, "upsertActions", { enumerable: true, get: function () { return upsert_actions_1.upsertActions; } });
26
+ var add_locations_1 = require("./add-locations");
27
+ Object.defineProperty(exports, "addLocations", { enumerable: true, get: function () { return add_locations_1.addLocations; } });
@@ -0,0 +1,72 @@
1
+ import { LocationsSettings } from './types';
2
+ export declare const selectLocationsPrompt: {
3
+ name: string;
4
+ message: string;
5
+ type: string;
6
+ choices: {
7
+ name: string;
8
+ value: string;
9
+ }[];
10
+ };
11
+ export declare const selectFieldsPrompt: {
12
+ name: string;
13
+ message: string;
14
+ type: string;
15
+ choices: ({
16
+ name: string;
17
+ value: {
18
+ type: string;
19
+ items?: undefined;
20
+ linkType?: undefined;
21
+ };
22
+ } | {
23
+ name: string;
24
+ value: {
25
+ type: string;
26
+ items: {
27
+ type: string;
28
+ linkType?: undefined;
29
+ };
30
+ linkType?: undefined;
31
+ };
32
+ } | {
33
+ name: string;
34
+ value: {
35
+ type: string;
36
+ linkType: string;
37
+ items?: undefined;
38
+ };
39
+ } | {
40
+ name: string;
41
+ value: {
42
+ type: string;
43
+ items: {
44
+ type: string;
45
+ linkType: string;
46
+ };
47
+ linkType?: undefined;
48
+ };
49
+ })[];
50
+ when(answers: LocationsSettings): boolean;
51
+ validate(input: any): true | "You must choose at least one field type.";
52
+ };
53
+ export declare const pageNavPrompt: {
54
+ name: string;
55
+ message: string;
56
+ type: string;
57
+ default: boolean;
58
+ when(answers: LocationsSettings): boolean;
59
+ };
60
+ export declare const pageNavLinkNamePrompt: {
61
+ name: string;
62
+ message: string;
63
+ when(answers: LocationsSettings): boolean | undefined;
64
+ validate(input: any): true | "Size must be at least 1 and at most 40";
65
+ };
66
+ export declare const pageNavLinkPathPrompt: {
67
+ name: string;
68
+ message: string;
69
+ default: string;
70
+ when(answers: LocationsSettings): boolean | undefined;
71
+ validate(input: any): true | "Maximum 512 characters" | "Path cannot contain empty space" | "Path must start with /";
72
+ };
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pageNavLinkPathPrompt = exports.pageNavLinkNamePrompt = exports.pageNavPrompt = exports.selectFieldsPrompt = exports.selectLocationsPrompt = void 0;
4
+ exports.selectLocationsPrompt = {
5
+ name: 'locations',
6
+ message: `Select where your app can be rendered:`,
7
+ type: 'checkbox',
8
+ choices: [
9
+ { name: 'App configuration screen ', value: 'app-config' },
10
+ { name: 'Entry field', value: 'entry-field' },
11
+ { name: 'Entry sidebar', value: 'entry-sidebar' },
12
+ { name: 'Entry editor', value: 'entry-editor' },
13
+ { name: 'Page', value: 'page' },
14
+ { name: 'Home', value: 'home' },
15
+ ],
16
+ };
17
+ exports.selectFieldsPrompt = {
18
+ name: 'fields',
19
+ message: 'Select the field types the app can be rendered:',
20
+ type: 'checkbox',
21
+ choices: [
22
+ { name: 'Short text', value: { type: 'Symbol' } },
23
+ { name: 'Short text, list', value: { type: 'Array', items: { type: 'Symbol' } } },
24
+ { name: 'Long text', value: { type: 'Text' } },
25
+ { name: 'Rich text', value: { type: 'RichText' } },
26
+ { name: 'Number, integer', value: { type: 'Integer' } },
27
+ { name: 'Number, decimal', value: { type: 'Number' } },
28
+ { name: 'Date and time', value: { type: 'Date' } },
29
+ { name: 'Location', value: { type: 'Location' } },
30
+ { name: 'Boolean', value: { type: 'Boolean' } },
31
+ { name: 'JSON object', value: { type: 'Object' } },
32
+ { name: 'Entry reference', value: { type: 'Link', linkType: 'Entry' } },
33
+ {
34
+ name: 'Entry reference, list',
35
+ value: {
36
+ type: 'Array',
37
+ items: {
38
+ type: 'Link',
39
+ linkType: 'Entry',
40
+ },
41
+ },
42
+ },
43
+ { name: 'Media reference', value: { type: 'Link', linkType: 'Asset' } },
44
+ {
45
+ name: 'Media reference, list',
46
+ value: { type: 'Array', items: { type: 'Link', linkType: 'Asset' } },
47
+ },
48
+ ],
49
+ when(answers) {
50
+ return answers.locations.includes('entry-field');
51
+ },
52
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ validate(input) {
54
+ if (input.length < 1) {
55
+ return 'You must choose at least one field type.';
56
+ }
57
+ return true;
58
+ },
59
+ };
60
+ exports.pageNavPrompt = {
61
+ name: 'pageNav',
62
+ message: 'Page location: Would you like your page location to render in the main navigation?',
63
+ type: 'confirm',
64
+ default: false,
65
+ when(answers) {
66
+ return answers.locations.includes('page');
67
+ },
68
+ };
69
+ exports.pageNavLinkNamePrompt = {
70
+ name: 'pageNavLinkName',
71
+ message: 'Page location: Provide a name for the link in the main navigation:',
72
+ when(answers) {
73
+ return answers.locations.includes('page') && answers.pageNav;
74
+ },
75
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
+ validate(input) {
77
+ if (input.length < 1 || input.length > 40) {
78
+ return 'Size must be at least 1 and at most 40';
79
+ }
80
+ return true;
81
+ },
82
+ };
83
+ exports.pageNavLinkPathPrompt = {
84
+ name: 'pageNavLinkPath',
85
+ message: 'Page location: Provide a path which starts with / and does not contain empty space:',
86
+ default: '/',
87
+ when(answers) {
88
+ return answers.locations.includes('page') && answers.pageNav;
89
+ },
90
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
91
+ validate(input) {
92
+ if (input.length > 512) {
93
+ return 'Maximum 512 characters';
94
+ }
95
+ if (input.includes(' ')) {
96
+ return 'Path cannot contain empty space';
97
+ }
98
+ if (!input.startsWith('/')) {
99
+ return 'Path must start with /';
100
+ }
101
+ return true;
102
+ },
103
+ };
package/lib/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { AppLocation, FieldType, InstallationParameterType, ParameterDefinition } from 'contentful-management';
1
2
  import { Definition } from './definition-api';
2
3
  import { Organization } from './organization-api';
3
4
  export interface ContentfulFunction {
@@ -77,3 +78,31 @@ export interface GenerateFunctionSettings {
77
78
  example: string;
78
79
  language: Language;
79
80
  }
81
+ export interface AddLocationsOptions {
82
+ organizationId?: string;
83
+ definitionId?: string;
84
+ token?: string;
85
+ host?: string;
86
+ }
87
+ export interface LocationsSettings {
88
+ locations: AppLocation['location'][];
89
+ fields?: FieldType[];
90
+ pageNav?: boolean;
91
+ pageNavLinkName?: string;
92
+ pageNavLinkPath?: string;
93
+ }
94
+ export interface AddLocationsSettings extends LocationsSettings {
95
+ organization: Organization;
96
+ definition: Definition;
97
+ accessToken: string;
98
+ host?: string;
99
+ }
100
+ export interface AppDefinitionSettings extends LocationsSettings {
101
+ name: string;
102
+ host?: string;
103
+ buildAppParameters: boolean;
104
+ parameters?: {
105
+ instance: ParameterDefinition[];
106
+ installation: ParameterDefinition<InstallationParameterType>[];
107
+ };
108
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/app-scripts",
3
- "version": "2.2.0",
3
+ "version": "2.3.1",
4
4
  "description": "A collection of scripts for building Contentful Apps",
5
5
  "author": "Contentful GmbH",
6
6
  "license": "MIT",
@@ -51,11 +51,11 @@
51
51
  "@esbuild-plugins/node-modules-polyfill": "^0.2.2",
52
52
  "@segment/analytics-node": "^2.0.0",
53
53
  "adm-zip": "0.5.16",
54
- "axios": "^1.7.9",
54
+ "axios": "^1.8.4",
55
55
  "bottleneck": "2.19.5",
56
56
  "chalk": "4.1.2",
57
57
  "commander": "12.1.0",
58
- "contentful-management": "11.48.0",
58
+ "contentful-management": "^11.48.1",
59
59
  "dotenv": "16.4.7",
60
60
  "esbuild": "^0.25.1",
61
61
  "ignore": "7.0.3",
@@ -67,7 +67,7 @@
67
67
  "tiged": "^2.12.7",
68
68
  "zod": "^3.24.1"
69
69
  },
70
- "gitHead": "f74bc713b10f3b7eafc95193327bebc91ec64d74",
70
+ "gitHead": "5569e704260c531e9e33ced31ad5d4820f867b1a",
71
71
  "devDependencies": {
72
72
  "@types/adm-zip": "0.5.7",
73
73
  "@types/analytics-node": "3.1.14",
@@ -81,7 +81,7 @@
81
81
  "chai": "4.5.0",
82
82
  "mocha": "10.8.2",
83
83
  "proxyquire": "2.1.3",
84
- "sinon": "19.0.2",
84
+ "sinon": "20.0.0",
85
85
  "ts-mocha": "11.1.0",
86
86
  "ts-node": "10.9.2"
87
87
  }