@contentful/create-contentful-app 1.16.2 → 1.16.4
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/lib/getTemplateSource.js +70 -88
- package/lib/includeAppAction.js +37 -48
- package/lib/includeFunction.js +37 -48
- package/lib/index.js +95 -112
- package/lib/template.js +27 -40
- package/lib/utils/file.js +14 -27
- package/lib/utils/package.js +1 -2
- package/lib/utils.js +2 -2
- package/package.json +6 -7
package/lib/getTemplateSource.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -21,97 +12,88 @@ const logger_1 = require("./logger");
|
|
|
21
12
|
const constants_1 = require("./constants");
|
|
22
13
|
const utils_1 = require("./utils");
|
|
23
14
|
const CONTENTFUL_APPS_EXAMPLE_FOLDER = 'https://api.github.com/repos/contentful/apps/contents/examples';
|
|
24
|
-
function getGithubFolderNames() {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
.map((content) => content.name);
|
|
31
|
-
});
|
|
15
|
+
async function getGithubFolderNames() {
|
|
16
|
+
const response = await (0, node_fetch_1.default)(CONTENTFUL_APPS_EXAMPLE_FOLDER);
|
|
17
|
+
const contents = await response.json();
|
|
18
|
+
return contents
|
|
19
|
+
.filter((content) => content.type === 'dir' && !constants_1.IGNORED_EXAMPLE_FOLDERS.includes(content.name))
|
|
20
|
+
.map((content) => content.name);
|
|
32
21
|
}
|
|
33
|
-
function promptExampleSelection() {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
22
|
+
async function promptExampleSelection() {
|
|
23
|
+
let template = 'typescript';
|
|
24
|
+
// ask user whether to start with a blank template or use an example
|
|
25
|
+
const { starter } = await inquirer_1.default.prompt([
|
|
26
|
+
{
|
|
27
|
+
name: 'starter',
|
|
28
|
+
message: 'Do you want to start with a blank template or use one of our examples?',
|
|
29
|
+
type: 'list',
|
|
30
|
+
choices: [
|
|
31
|
+
{ name: 'Template', value: 'template' },
|
|
32
|
+
{ name: 'Example', value: 'example' },
|
|
33
|
+
],
|
|
34
|
+
default: 'template',
|
|
35
|
+
},
|
|
36
|
+
]);
|
|
37
|
+
// if the user chose to use a template, ask which language they prefer
|
|
38
|
+
if (starter === 'template') {
|
|
39
|
+
const { language } = await inquirer_1.default.prompt([
|
|
38
40
|
{
|
|
39
|
-
name: '
|
|
40
|
-
message: '
|
|
41
|
+
name: 'language',
|
|
42
|
+
message: 'Pick a template',
|
|
41
43
|
type: 'list',
|
|
42
44
|
choices: [
|
|
43
|
-
{ name: '
|
|
44
|
-
{ name: '
|
|
45
|
+
{ name: 'TypeScript', value: 'typescript' },
|
|
46
|
+
{ name: 'JavaScript', value: 'javascript' },
|
|
47
|
+
{ name: 'Next.js', value: 'nextjs' },
|
|
48
|
+
{ name: 'React + Vite', value: 'vite-react' },
|
|
49
|
+
{ name: 'Vue', value: 'vue' },
|
|
45
50
|
],
|
|
46
|
-
default: '
|
|
51
|
+
default: 'typescript',
|
|
52
|
+
},
|
|
53
|
+
]);
|
|
54
|
+
template = language;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// get available templates from examples
|
|
58
|
+
const availableTemplates = await getGithubFolderNames();
|
|
59
|
+
// ask user to select a template from the available examples
|
|
60
|
+
const { example } = await inquirer_1.default.prompt([
|
|
61
|
+
{
|
|
62
|
+
name: 'example',
|
|
63
|
+
message: 'Select a template',
|
|
64
|
+
type: 'list',
|
|
65
|
+
choices: availableTemplates,
|
|
47
66
|
},
|
|
48
67
|
]);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
name: 'language',
|
|
54
|
-
message: 'Pick a template',
|
|
55
|
-
type: 'list',
|
|
56
|
-
choices: [
|
|
57
|
-
{ name: 'TypeScript', value: 'typescript' },
|
|
58
|
-
{ name: 'JavaScript', value: 'javascript' },
|
|
59
|
-
{ name: 'Next.js', value: 'nextjs' },
|
|
60
|
-
{ name: 'React + Vite', value: 'vite-react' },
|
|
61
|
-
{ name: 'Vue', value: 'vue' },
|
|
62
|
-
],
|
|
63
|
-
default: 'typescript',
|
|
64
|
-
},
|
|
65
|
-
]);
|
|
66
|
-
template = language;
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
// get available templates from examples
|
|
70
|
-
const availableTemplates = yield getGithubFolderNames();
|
|
71
|
-
// ask user to select a template from the available examples
|
|
72
|
-
const { example } = yield inquirer_1.default.prompt([
|
|
73
|
-
{
|
|
74
|
-
name: 'example',
|
|
75
|
-
message: 'Select a template',
|
|
76
|
-
type: 'list',
|
|
77
|
-
choices: availableTemplates,
|
|
78
|
-
},
|
|
79
|
-
]);
|
|
80
|
-
template = example;
|
|
81
|
-
}
|
|
82
|
-
// return the selected template
|
|
83
|
-
return selectTemplate(template);
|
|
84
|
-
});
|
|
68
|
+
template = example;
|
|
69
|
+
}
|
|
70
|
+
// return the selected template
|
|
71
|
+
return selectTemplate(template);
|
|
85
72
|
}
|
|
86
73
|
function selectTemplate(template) {
|
|
87
74
|
(0, logger_1.wrapInBlanks)((0, logger_1.highlight)(`---- Cloning the ${chalk_1.default.cyan(template)} template...`));
|
|
88
75
|
return constants_1.EXAMPLES_PATH + template;
|
|
89
76
|
}
|
|
90
|
-
function makeContentfulExampleSource(options) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return yield promptExampleSelection();
|
|
105
|
-
});
|
|
77
|
+
async function makeContentfulExampleSource(options) {
|
|
78
|
+
if (options.example) {
|
|
79
|
+
return selectTemplate(options.example);
|
|
80
|
+
}
|
|
81
|
+
if (options.javascript) {
|
|
82
|
+
return selectTemplate(types_1.ContentfulExample.Javascript);
|
|
83
|
+
}
|
|
84
|
+
if (options.typescript) {
|
|
85
|
+
return selectTemplate(types_1.ContentfulExample.Typescript);
|
|
86
|
+
}
|
|
87
|
+
if (options.function || options.action) {
|
|
88
|
+
return selectTemplate(types_1.ContentfulExample.Typescript);
|
|
89
|
+
}
|
|
90
|
+
return await promptExampleSelection();
|
|
106
91
|
}
|
|
107
|
-
function getTemplateSource(options) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
return source;
|
|
115
|
-
});
|
|
92
|
+
async function getTemplateSource(options) {
|
|
93
|
+
const source = options.source ?? (await makeContentfulExampleSource(options));
|
|
94
|
+
if (options.source && !(0, utils_1.isContentfulTemplate)(source)) {
|
|
95
|
+
(0, logger_1.warn)(`Template at ${(0, logger_1.highlight)(source)} is not an official Contentful app template!`);
|
|
96
|
+
}
|
|
97
|
+
return source;
|
|
116
98
|
}
|
|
117
99
|
exports.getTemplateSource = getTemplateSource;
|
package/lib/includeAppAction.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -17,7 +8,7 @@ const inquirer_1 = __importDefault(require("inquirer"));
|
|
|
17
8
|
const promises_1 = require("fs/promises");
|
|
18
9
|
const path_1 = require("path");
|
|
19
10
|
const constants_1 = require("./constants");
|
|
20
|
-
const
|
|
11
|
+
const tiged_1 = __importDefault(require("tiged"));
|
|
21
12
|
const logger_1 = require("./logger");
|
|
22
13
|
const package_1 = require("./utils/package");
|
|
23
14
|
const file_1 = require("./utils/file");
|
|
@@ -25,46 +16,44 @@ const addBuildCommand = (0, package_1.getAddBuildCommandFn)({
|
|
|
25
16
|
name: 'build:actions',
|
|
26
17
|
command: 'node build-actions.js',
|
|
27
18
|
});
|
|
28
|
-
function cloneAppAction(destination, templateIsJavascript) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
const writeBuildCommand = yield (0, file_1.mergeJsonIntoFile)({
|
|
52
|
-
source: `${appActionDirectoryPath}/package.json`,
|
|
53
|
-
destination: packageJsonLocation,
|
|
54
|
-
mergeFn: addBuildCommand,
|
|
55
|
-
});
|
|
56
|
-
yield Promise.all([writeAppManifest, copyBuildFile, writeBuildCommand]);
|
|
57
|
-
yield d.remove(appActionDirectoryPath, destination, { action: 'remove', files: constants_1.IGNORED_CLONED_FILES.map(fileName => `${appActionDirectoryPath}/${fileName}`) });
|
|
58
|
-
}
|
|
59
|
-
catch (e) {
|
|
60
|
-
console.log(e);
|
|
61
|
-
process.exit(1);
|
|
19
|
+
async function cloneAppAction(destination, templateIsJavascript) {
|
|
20
|
+
try {
|
|
21
|
+
console.log((0, logger_1.highlight)('---- Cloning hosted app action.'));
|
|
22
|
+
// Clone the app actions template to the created directory under the folder 'actions'
|
|
23
|
+
const templateSource = (0, path_1.join)('contentful/apps/examples/hosted-app-action-templates', templateIsJavascript ? 'javascript' : 'typescript');
|
|
24
|
+
const appActionDirectoryPath = (0, path_1.resolve)(`${destination}/actions`);
|
|
25
|
+
const d = await (0, tiged_1.default)(templateSource, { mode: 'tar', disableCache: true });
|
|
26
|
+
await d.clone(appActionDirectoryPath);
|
|
27
|
+
// move the manifest from the actions folder to the root folder
|
|
28
|
+
const writeAppManifest = await (0, file_1.mergeJsonIntoFile)({
|
|
29
|
+
source: `${appActionDirectoryPath}/${constants_1.CONTENTFUL_APP_MANIFEST}`,
|
|
30
|
+
destination: `${destination}/${constants_1.CONTENTFUL_APP_MANIFEST}`,
|
|
31
|
+
});
|
|
32
|
+
// move the build file from the actions folder to the root folder
|
|
33
|
+
const copyBuildFile = await (0, promises_1.rename)(`${appActionDirectoryPath}/build-actions.js`, `${destination}/build-actions.js`);
|
|
34
|
+
// modify package.json build commands
|
|
35
|
+
const packageJsonLocation = (0, path_1.resolve)(`${destination}/package.json`);
|
|
36
|
+
const packageJsonExists = await (0, file_1.exists)(packageJsonLocation);
|
|
37
|
+
if (!packageJsonExists) {
|
|
38
|
+
console.error(`Failed to add app action build commands: ${packageJsonLocation} does not exist.`);
|
|
39
|
+
return;
|
|
62
40
|
}
|
|
63
|
-
|
|
41
|
+
const writeBuildCommand = await (0, file_1.mergeJsonIntoFile)({
|
|
42
|
+
source: `${appActionDirectoryPath}/package.json`,
|
|
43
|
+
destination: packageJsonLocation,
|
|
44
|
+
mergeFn: addBuildCommand,
|
|
45
|
+
});
|
|
46
|
+
await Promise.all([writeAppManifest, copyBuildFile, writeBuildCommand]);
|
|
47
|
+
await d.remove(appActionDirectoryPath, destination, { action: 'remove', files: constants_1.IGNORED_CLONED_FILES.map(fileName => `${appActionDirectoryPath}/${fileName}`) });
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
console.log(e);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
64
53
|
}
|
|
65
54
|
exports.cloneAppAction = cloneAppAction;
|
|
66
|
-
const promptIncludeActionInTemplate = ({ fullAppFolder, templateSource, }) =>
|
|
67
|
-
const { includeAppAction } =
|
|
55
|
+
const promptIncludeActionInTemplate = async ({ fullAppFolder, templateSource, }) => {
|
|
56
|
+
const { includeAppAction } = await inquirer_1.default.prompt([
|
|
68
57
|
{
|
|
69
58
|
name: 'includeAppAction',
|
|
70
59
|
message: 'Do you want to include a hosted app action?',
|
|
@@ -77,5 +66,5 @@ const promptIncludeActionInTemplate = ({ fullAppFolder, templateSource, }) => __
|
|
|
77
66
|
const templateIsTypescript = templateSource.includes('typescript');
|
|
78
67
|
cloneAppAction(fullAppFolder, templateIsTypescript);
|
|
79
68
|
}
|
|
80
|
-
}
|
|
69
|
+
};
|
|
81
70
|
exports.promptIncludeActionInTemplate = promptIncludeActionInTemplate;
|
package/lib/includeFunction.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -16,7 +7,7 @@ exports.cloneFunction = void 0;
|
|
|
16
7
|
const promises_1 = require("fs/promises");
|
|
17
8
|
const path_1 = require("path");
|
|
18
9
|
const constants_1 = require("./constants");
|
|
19
|
-
const
|
|
10
|
+
const tiged_1 = __importDefault(require("tiged"));
|
|
20
11
|
const logger_1 = require("./logger");
|
|
21
12
|
const file_1 = require("./utils/file");
|
|
22
13
|
const package_1 = require("./utils/package");
|
|
@@ -40,44 +31,42 @@ function functionTemplateFromName(functionName) {
|
|
|
40
31
|
dirName = 'templates'; // backwards compatible for the apps repo examples folder for delivery functions (external-references)
|
|
41
32
|
return dirName;
|
|
42
33
|
}
|
|
43
|
-
function cloneFunction(destination, templateIsJavascript, functionName) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
const writeBuildCommand = (0, file_1.mergeJsonIntoFile)({
|
|
67
|
-
source: `${functionDirectoryPath}/package.json`,
|
|
68
|
-
destination: packageJsonLocation,
|
|
69
|
-
mergeFn: addBuildCommand,
|
|
70
|
-
});
|
|
71
|
-
yield Promise.all([writeAppManifest, copyBuildFile, writeBuildCommand]);
|
|
72
|
-
yield d.remove(functionDirectoryPath, destination, {
|
|
73
|
-
action: 'remove',
|
|
74
|
-
files: constants_1.IGNORED_CLONED_FILES.map((fileName) => `${functionDirectoryPath}/${fileName}`),
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
catch (e) {
|
|
78
|
-
console.error(e);
|
|
79
|
-
process.exit(1);
|
|
34
|
+
async function cloneFunction(destination, templateIsJavascript, functionName) {
|
|
35
|
+
try {
|
|
36
|
+
console.log((0, logger_1.highlight)(`---- Cloning function "${functionName}".`));
|
|
37
|
+
// Clone the function template to the created directory under the folder 'actions'
|
|
38
|
+
const templateSource = (0, path_1.join)(`contentful/apps/examples/function-${functionTemplateFromName(functionName)}`, templateIsJavascript ? 'javascript' : 'typescript');
|
|
39
|
+
const functionDirectoryPath = (0, path_1.resolve)(`${destination}/functions`);
|
|
40
|
+
const d = (0, tiged_1.default)(templateSource, { mode: 'tar', disableCache: true });
|
|
41
|
+
await d.clone(functionDirectoryPath);
|
|
42
|
+
// merge the manifest from the template folder to the root folder
|
|
43
|
+
const writeAppManifest = (0, file_1.mergeJsonIntoFile)({
|
|
44
|
+
source: `${functionDirectoryPath}/${constants_1.CONTENTFUL_APP_MANIFEST}`,
|
|
45
|
+
destination: `${destination}/${constants_1.CONTENTFUL_APP_MANIFEST}`,
|
|
46
|
+
});
|
|
47
|
+
// move the build file from the actions folder to the root folder
|
|
48
|
+
const copyBuildFile = (0, promises_1.rename)(`${functionDirectoryPath}/build-functions.js`, `${destination}/build-functions.js`);
|
|
49
|
+
// modify package.json build commands
|
|
50
|
+
const packageJsonLocation = (0, path_1.resolve)(`${destination}/package.json`);
|
|
51
|
+
const packageJsonExists = await (0, file_1.exists)(packageJsonLocation);
|
|
52
|
+
if (!packageJsonExists) {
|
|
53
|
+
console.error(`Failed to add function build commands: ${packageJsonLocation} does not exist.`);
|
|
54
|
+
return;
|
|
80
55
|
}
|
|
81
|
-
|
|
56
|
+
const writeBuildCommand = (0, file_1.mergeJsonIntoFile)({
|
|
57
|
+
source: `${functionDirectoryPath}/package.json`,
|
|
58
|
+
destination: packageJsonLocation,
|
|
59
|
+
mergeFn: addBuildCommand,
|
|
60
|
+
});
|
|
61
|
+
await Promise.all([writeAppManifest, copyBuildFile, writeBuildCommand]);
|
|
62
|
+
await d.remove(functionDirectoryPath, destination, {
|
|
63
|
+
action: 'remove',
|
|
64
|
+
files: constants_1.IGNORED_CLONED_FILES.map((fileName) => `${functionDirectoryPath}/${fileName}`),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
console.error(e);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
82
71
|
}
|
|
83
72
|
exports.cloneFunction = cloneFunction;
|
package/lib/index.js
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
-
});
|
|
11
|
-
};
|
|
12
3
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
5
|
};
|
|
@@ -54,16 +45,14 @@ function updatePackageName(appFolder) {
|
|
|
54
45
|
packageJson.name = (0, path_1.basename)(appFolder);
|
|
55
46
|
(0, fs_1.writeFileSync)(packageJsonPath, JSON.stringify(packageJson, null, 2) + os_1.EOL);
|
|
56
47
|
}
|
|
57
|
-
function promptAppName() {
|
|
58
|
-
return
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
]);
|
|
66
|
-
});
|
|
48
|
+
async function promptAppName() {
|
|
49
|
+
return await inquirer_1.default.prompt([
|
|
50
|
+
{
|
|
51
|
+
name: 'name',
|
|
52
|
+
message: 'App name',
|
|
53
|
+
default: DEFAULT_APP_NAME,
|
|
54
|
+
},
|
|
55
|
+
]);
|
|
67
56
|
}
|
|
68
57
|
/**
|
|
69
58
|
* Validates the user input and ensures it can be used as app name. If no app name is provided, shows a prompt.
|
|
@@ -71,102 +60,96 @@ function promptAppName() {
|
|
|
71
60
|
* @param appName App name entered by the user
|
|
72
61
|
* @returns Valid app name
|
|
73
62
|
*/
|
|
74
|
-
function validateAppName(appName) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return appName;
|
|
91
|
-
});
|
|
63
|
+
async function validateAppName(appName) {
|
|
64
|
+
if (appName === 'create-definition') {
|
|
65
|
+
throw new Error(`The ${(0, logger_1.code)('create-definition')} command has been removed from ${(0, logger_1.code)('create-contentful-app')}.\nTo create a new app definition first run ${(0, logger_1.code)('npx create-contentful-app')} and then ${(0, logger_1.code)('npm run create-app-definition')} within the new folder.`);
|
|
66
|
+
}
|
|
67
|
+
if (appName === 'init') {
|
|
68
|
+
(0, logger_1.warn)(`The ${(0, logger_1.code)('init')} command has been removed from ${(0, logger_1.code)('create-contentful-app')}. You can now create new apps running ${(0, logger_1.code)('npx create-contentful-app')} directly.`);
|
|
69
|
+
appName = '';
|
|
70
|
+
}
|
|
71
|
+
if (!appName) {
|
|
72
|
+
const prompt = await promptAppName();
|
|
73
|
+
appName = prompt.name;
|
|
74
|
+
}
|
|
75
|
+
if (!(0, validate_npm_package_name_1.default)(appName).validForNewPackages) {
|
|
76
|
+
throw new Error(`Cannot create an app named "${appName}". Please choose a different name for your app.`);
|
|
77
|
+
}
|
|
78
|
+
return appName;
|
|
92
79
|
}
|
|
93
|
-
function initProject(appName, options) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
normalizedOptions.function = 'external-references';
|
|
121
|
-
}
|
|
122
|
-
yield (0, includeFunction_1.cloneFunction)(fullAppFolder, !!normalizedOptions.javascript, normalizedOptions.function);
|
|
123
|
-
}
|
|
124
|
-
updatePackageName(fullAppFolder);
|
|
125
|
-
const useYarn = normalizedOptions.yarn || (0, utils_1.detectManager)() === 'yarn';
|
|
126
|
-
(0, logger_1.wrapInBlanks)((0, logger_1.highlight)(`---- Installing the dependencies for your app (using ${chalk_1.default.cyan(useYarn ? 'yarn' : 'npm')})...`));
|
|
127
|
-
if (useYarn) {
|
|
128
|
-
yield (0, utils_1.exec)('yarn', [], { cwd: fullAppFolder });
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
yield (0, utils_1.exec)('npm', ['install', '--no-audit', '--no-fund'], { cwd: fullAppFolder });
|
|
80
|
+
async function initProject(appName, options) {
|
|
81
|
+
const normalizedOptions = (0, utils_1.normalizeOptions)(options);
|
|
82
|
+
try {
|
|
83
|
+
appName = await validateAppName(appName);
|
|
84
|
+
const fullAppFolder = (0, path_1.resolve)(process.cwd(), appName);
|
|
85
|
+
console.log(`Creating a Contentful app in ${(0, logger_1.highlight)((0, tildify_1.default)(fullAppFolder))}.`);
|
|
86
|
+
const isInteractive = !normalizedOptions.example &&
|
|
87
|
+
!normalizedOptions.source &&
|
|
88
|
+
!normalizedOptions.javascript &&
|
|
89
|
+
!normalizedOptions.typescript &&
|
|
90
|
+
!normalizedOptions.function &&
|
|
91
|
+
!normalizedOptions.action;
|
|
92
|
+
const templateSource = await (0, getTemplateSource_1.getTemplateSource)(options);
|
|
93
|
+
(0, analytics_1.track)({
|
|
94
|
+
template: templateSource,
|
|
95
|
+
manager: normalizedOptions.npm ? 'npm' : 'yarn',
|
|
96
|
+
interactive: isInteractive,
|
|
97
|
+
});
|
|
98
|
+
await (0, template_1.cloneTemplateIn)(fullAppFolder, templateSource);
|
|
99
|
+
if (!isInteractive && (0, utils_1.isContentfulTemplate)(templateSource) && normalizedOptions.action) {
|
|
100
|
+
await (0, includeAppAction_1.cloneAppAction)(fullAppFolder, !!normalizedOptions.javascript);
|
|
101
|
+
}
|
|
102
|
+
if (!isInteractive && (0, utils_1.isContentfulTemplate)(templateSource) && normalizedOptions.function) {
|
|
103
|
+
// If function flag is specified, but no function name is provided, we default to external-references
|
|
104
|
+
// for legacy support.
|
|
105
|
+
if (normalizedOptions.function === true) {
|
|
106
|
+
normalizedOptions.function = 'external-references';
|
|
132
107
|
}
|
|
133
|
-
|
|
108
|
+
await (0, includeFunction_1.cloneFunction)(fullAppFolder, !!normalizedOptions.javascript, normalizedOptions.function);
|
|
109
|
+
}
|
|
110
|
+
updatePackageName(fullAppFolder);
|
|
111
|
+
const useYarn = normalizedOptions.yarn || (0, utils_1.detectManager)() === 'yarn';
|
|
112
|
+
(0, logger_1.wrapInBlanks)((0, logger_1.highlight)(`---- Installing the dependencies for your app (using ${chalk_1.default.cyan(useYarn ? 'yarn' : 'npm')})...`));
|
|
113
|
+
if (useYarn) {
|
|
114
|
+
await (0, utils_1.exec)('yarn', [], { cwd: fullAppFolder });
|
|
134
115
|
}
|
|
135
|
-
|
|
136
|
-
(0,
|
|
137
|
-
process.exit(1);
|
|
116
|
+
else {
|
|
117
|
+
await (0, utils_1.exec)('npm', ['install', '--no-audit', '--no-fund'], { cwd: fullAppFolder });
|
|
138
118
|
}
|
|
139
|
-
|
|
119
|
+
successMessage(fullAppFolder, useYarn);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
(0, logger_1.error)(`Failed to create ${appName}`, err);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
140
125
|
}
|
|
141
|
-
(function main() {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
yield commander_1.program.parseAsync();
|
|
171
|
-
});
|
|
126
|
+
(async function main() {
|
|
127
|
+
commander_1.program
|
|
128
|
+
.name(`npx ${(0, logger_1.code)('create-contentful-app')}`)
|
|
129
|
+
.helpOption(true, 'shows all available CLI options')
|
|
130
|
+
.description([
|
|
131
|
+
'Bootstrap your app inside a new folder `my-app`',
|
|
132
|
+
'',
|
|
133
|
+
(0, logger_1.code)(' create-contentful-app my-app'),
|
|
134
|
+
'',
|
|
135
|
+
'or specify your own template',
|
|
136
|
+
'',
|
|
137
|
+
(0, logger_1.code)(' create-contentful-app my-app --source "github:user/repo"'),
|
|
138
|
+
'',
|
|
139
|
+
`Official Contentful templates and examples are hosted at ${(0, logger_1.highlight)(constants_1.EXAMPLES_REPO_URL)}.`,
|
|
140
|
+
].join('\n'))
|
|
141
|
+
.argument('[app-name]', 'app name')
|
|
142
|
+
.option('--npm', 'use npm')
|
|
143
|
+
.option('--yarn', 'use Yarn')
|
|
144
|
+
.option('-ts, --typescript', 'use TypeScript template (default)')
|
|
145
|
+
.option('-js, --javascript', 'use JavaScript template')
|
|
146
|
+
.option('-e, --example <example-name>', `bootstrap an example app from ${constants_1.EXAMPLES_REPO_URL}`)
|
|
147
|
+
.option('-s, --source <url>', [
|
|
148
|
+
`provide a template by its source repository.`,
|
|
149
|
+
`format: URL (HTTPS or SSH) or ${(0, logger_1.code)('vendor:user/repo')} (e.g., ${(0, logger_1.code)('github:user/repo')})`,
|
|
150
|
+
].join('\n'))
|
|
151
|
+
.option('-a, --action', 'include a hosted app action in the ts or js template')
|
|
152
|
+
.option('-f, --function [function-template-name]', 'include the specified function template')
|
|
153
|
+
.action(initProject);
|
|
154
|
+
await commander_1.program.parseAsync();
|
|
172
155
|
})();
|
package/lib/template.js
CHANGED
|
@@ -22,15 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
27
|
};
|
|
@@ -38,27 +29,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
38
29
|
exports.cloneTemplateIn = void 0;
|
|
39
30
|
const path_1 = require("path");
|
|
40
31
|
const fs_1 = require("fs");
|
|
41
|
-
const
|
|
32
|
+
const tiged_1 = __importDefault(require("tiged"));
|
|
42
33
|
const rimraf = __importStar(require("rimraf"));
|
|
43
34
|
const logger_1 = require("./logger");
|
|
44
35
|
const utils_1 = require("./utils");
|
|
45
|
-
function clone(source, destination) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
throw new Error('Destination directory is not empty.');
|
|
58
|
-
}
|
|
59
|
-
throw e;
|
|
36
|
+
async function clone(source, destination) {
|
|
37
|
+
const d = (0, tiged_1.default)(source, { mode: 'tar', disableCache: true });
|
|
38
|
+
try {
|
|
39
|
+
await d.clone(destination);
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
if (e.code === 'DEST_NOT_EMPTY') {
|
|
43
|
+
// In this case, we know that tiged will suggest users
|
|
44
|
+
// provide a 'force' flag - this is a flag for tiged though
|
|
45
|
+
// and not CCA. So we swallow the details of this error
|
|
46
|
+
// to avoid confusing people.
|
|
47
|
+
throw new Error('Destination directory is not empty.');
|
|
60
48
|
}
|
|
61
|
-
|
|
49
|
+
throw e;
|
|
50
|
+
}
|
|
62
51
|
}
|
|
63
52
|
function validate(destination) {
|
|
64
53
|
const packageJSONLocation = `${destination}/package.json`;
|
|
@@ -76,19 +65,17 @@ function cleanUp(destination) {
|
|
|
76
65
|
(0, utils_1.rmIfExists)((0, path_1.resolve)(destination, 'package-lock.json'));
|
|
77
66
|
(0, utils_1.rmIfExists)((0, path_1.resolve)(destination, 'yarn.lock'));
|
|
78
67
|
}
|
|
79
|
-
function cloneTemplateIn(destination, source) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
cleanUp(destination);
|
|
92
|
-
});
|
|
68
|
+
async function cloneTemplateIn(destination, source) {
|
|
69
|
+
await clone(source, destination);
|
|
70
|
+
console.log((0, logger_1.success)('Done!'));
|
|
71
|
+
try {
|
|
72
|
+
validate(destination);
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
// cleanup in case of invalid example
|
|
76
|
+
rimraf.sync(destination);
|
|
77
|
+
throw e;
|
|
78
|
+
}
|
|
79
|
+
cleanUp(destination);
|
|
93
80
|
}
|
|
94
81
|
exports.cloneTemplateIn = cloneTemplateIn;
|
package/lib/utils/file.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -16,26 +7,22 @@ exports.exists = exports.mergeJsonIntoFile = exports.getJsonData = void 0;
|
|
|
16
7
|
const merge_options_1 = __importDefault(require("merge-options"));
|
|
17
8
|
const promises_1 = require("fs/promises");
|
|
18
9
|
const path_1 = require("path");
|
|
19
|
-
function getJsonData(path) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return JSON.parse(yield (0, promises_1.readFile)(normalizedPath, { encoding: 'utf-8' }));
|
|
29
|
-
});
|
|
10
|
+
async function getJsonData(path) {
|
|
11
|
+
if (!path) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
const normalizedPath = (0, path_1.resolve)(path);
|
|
15
|
+
if (!(await exists(normalizedPath))) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return JSON.parse(await (0, promises_1.readFile)(normalizedPath, { encoding: 'utf-8' }));
|
|
30
19
|
}
|
|
31
20
|
exports.getJsonData = getJsonData;
|
|
32
|
-
function mergeJsonIntoFile({ source, destination, mergeFn = merge_options_1.default.bind({ concatArrays: false }), }) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
yield (0, promises_1.writeFile)((0, path_1.resolve)(destination), JSON.stringify(mergedJson, null, ' '));
|
|
38
|
-
});
|
|
21
|
+
async function mergeJsonIntoFile({ source, destination, mergeFn = merge_options_1.default.bind({ concatArrays: false }), }) {
|
|
22
|
+
const sourceJson = await getJsonData(source);
|
|
23
|
+
const destinationJson = await getJsonData(destination);
|
|
24
|
+
const mergedJson = mergeFn(destinationJson, sourceJson);
|
|
25
|
+
await (0, promises_1.writeFile)((0, path_1.resolve)(destination), JSON.stringify(mergedJson, null, ' '));
|
|
39
26
|
}
|
|
40
27
|
exports.mergeJsonIntoFile = mergeJsonIntoFile;
|
|
41
28
|
function exists(path) {
|
package/lib/utils/package.js
CHANGED
|
@@ -7,8 +7,7 @@ exports.getAddBuildCommandFn = void 0;
|
|
|
7
7
|
const merge_options_1 = __importDefault(require("merge-options"));
|
|
8
8
|
function getAddBuildCommandFn({ name, command }) {
|
|
9
9
|
return (packageJson, additionalProperties) => {
|
|
10
|
-
|
|
11
|
-
let buildCommand = (_b = (_a = packageJson === null || packageJson === void 0 ? void 0 : packageJson.scripts) === null || _a === void 0 ? void 0 : _a.build) !== null && _b !== void 0 ? _b : '';
|
|
10
|
+
let buildCommand = packageJson?.scripts?.build ?? '';
|
|
12
11
|
const triggerCommand = `npm run ${name}`;
|
|
13
12
|
if (buildCommand === '') {
|
|
14
13
|
buildCommand = triggerCommand;
|
package/lib/utils.js
CHANGED
|
@@ -10,7 +10,7 @@ const constants_1 = require("./constants");
|
|
|
10
10
|
const MUTUALLY_EXCLUSIVE_OPTIONS = ['source', 'example', 'typescript', 'javascript'];
|
|
11
11
|
function exec(command, args, options) {
|
|
12
12
|
return new Promise((resolve, reject) => {
|
|
13
|
-
const process = (0, child_process_1.spawn)(command, args,
|
|
13
|
+
const process = (0, child_process_1.spawn)(command, args, { stdio: 'inherit', shell: true, ...options });
|
|
14
14
|
process.on('exit', (exitCode) => {
|
|
15
15
|
if (exitCode === 0) {
|
|
16
16
|
resolve();
|
|
@@ -40,7 +40,7 @@ function detectManager() {
|
|
|
40
40
|
}
|
|
41
41
|
exports.detectManager = detectManager;
|
|
42
42
|
function normalizeOptions(options) {
|
|
43
|
-
const normalizedOptions =
|
|
43
|
+
const normalizedOptions = { ...options };
|
|
44
44
|
if (normalizedOptions.npm && normalizedOptions.yarn) {
|
|
45
45
|
(0, logger_1.warn)(`Provided both ${(0, logger_1.highlight)('--yarn')} and ${(0, logger_1.highlight)('--npm')} flags, using ${(0, logger_1.choice)('--npm')}.`);
|
|
46
46
|
delete normalizedOptions.yarn;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/create-contentful-app",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.4",
|
|
4
4
|
"description": "A template for building Contentful Apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"contentful",
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"analytics-node": "^6.2.0",
|
|
41
41
|
"chalk": "4.1.2",
|
|
42
42
|
"commander": "12.0.0",
|
|
43
|
-
"degit": "2.8.4",
|
|
44
43
|
"inquirer": "8.2.6",
|
|
45
44
|
"merge-options": "^3.0.4",
|
|
46
45
|
"node-fetch": "2.6.7",
|
|
47
46
|
"rimraf": "5.0.5",
|
|
47
|
+
"tiged": "^2.12.7",
|
|
48
48
|
"tildify": "2.0.0",
|
|
49
49
|
"validate-npm-package-name": "5.0.0"
|
|
50
50
|
},
|
|
@@ -59,11 +59,10 @@
|
|
|
59
59
|
"access": "public"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@tsconfig/
|
|
62
|
+
"@tsconfig/node20": "^20.1.4",
|
|
63
63
|
"@types/analytics-node": "^3.1.9",
|
|
64
64
|
"@types/chai-as-promised": "^7.1.5",
|
|
65
65
|
"@types/chalk": "2.2.0",
|
|
66
|
-
"@types/degit": "2.8.6",
|
|
67
66
|
"@types/inquirer": "8.2.1",
|
|
68
67
|
"@types/mocha": "^10.0.1",
|
|
69
68
|
"@types/node": "14.18.63",
|
|
@@ -75,11 +74,11 @@
|
|
|
75
74
|
"@types/validate-npm-package-name": "4.0.2",
|
|
76
75
|
"chai": "^4.3.7",
|
|
77
76
|
"chai-as-promised": "^7.1.1",
|
|
78
|
-
"contentful-management": "11.25.
|
|
77
|
+
"contentful-management": "11.25.2",
|
|
79
78
|
"mocha": "^10.2.0",
|
|
80
79
|
"sinon": "^17.0.0",
|
|
81
80
|
"sinon-chai": "^3.7.0",
|
|
82
|
-
"ts-node": "^10.9.
|
|
81
|
+
"ts-node": "^10.9.2"
|
|
83
82
|
},
|
|
84
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "fd52872083e3f855f7ca1e01cd984c17d39edac0"
|
|
85
84
|
}
|