@contentful/create-contentful-app 0.15.12 → 1.1.0-alpha.10
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 +76 -13
- package/lib/index.js +123 -125
- package/lib/logger.js +34 -0
- package/lib/template.js +95 -0
- package/lib/types.js +7 -0
- package/lib/utils.js +74 -0
- package/package.json +27 -17
package/README.md
CHANGED
|
@@ -1,26 +1,89 @@
|
|
|
1
|
+
<!-- Don't forget to also update the corresponding README.md of the create-contentful-app package -->
|
|
2
|
+
|
|
1
3
|
# Create Contentful App
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
`create-contentful-app` is a command line interface to easily bootstrap [Contentful Apps](https://www.contentful.com/developers/docs/extensibility/app-framework/).
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
# Requirements
|
|
6
8
|
|
|
7
|
-
- Node.js v14 or v16
|
|
8
|
-
-
|
|
9
|
+
- Node.js v14.15 or v16
|
|
10
|
+
- npm v6 or later
|
|
9
11
|
|
|
10
|
-
#
|
|
12
|
+
# Usage
|
|
11
13
|
|
|
12
|
-
To start developing your app:
|
|
14
|
+
To start developing your first app, run:
|
|
13
15
|
|
|
16
|
+
```bash
|
|
17
|
+
npx create-contentful-app my-first-app
|
|
14
18
|
```
|
|
15
|
-
npx @contentful/create-contentful-app init my-first-app
|
|
16
|
-
cd my-first-app
|
|
17
|
-
npm start
|
|
18
|
-
```
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+

|
|
21
|
+
|
|
22
|
+
## Bootstrap
|
|
23
|
+
|
|
24
|
+
You can run `create-contentful-app` using one of the following commands:
|
|
21
25
|
|
|
26
|
+
```bash
|
|
27
|
+
# npx
|
|
28
|
+
npx create-contentful-app <app-name>
|
|
29
|
+
|
|
30
|
+
# npm
|
|
31
|
+
npm init contentful-app <app-name>
|
|
32
|
+
|
|
33
|
+
# Yarn
|
|
34
|
+
yarn create contentful-app <app-name>
|
|
22
35
|
```
|
|
23
|
-
|
|
36
|
+
|
|
37
|
+
## CLI Options
|
|
38
|
+
|
|
39
|
+
### Package Manager
|
|
40
|
+
|
|
41
|
+
`--npm` or `--yarn`
|
|
42
|
+
|
|
43
|
+
Use npm or Yarn to manage dependencies. If omitted, defaults to the manager used to run `create-contentful-app`.
|
|
44
|
+
|
|
45
|
+
Both flags are mutually exclusive.
|
|
46
|
+
|
|
47
|
+
### Template
|
|
48
|
+
|
|
49
|
+
Select between predefined and custom templates:
|
|
50
|
+
|
|
51
|
+
- `-ts, --typescript`: Use TypeScript template (default)
|
|
52
|
+
- `-js, --javascript`: Use JavaScript template
|
|
53
|
+
- `-e, --example <example-name>`: Select a predefined template from https://github.com/contentful/apps/tree/master/examples
|
|
54
|
+
- `-s, --source <url>`: Use a custom template. Format: URL (HTTPS or SSH) or vendor:user/repo (e.g., github:user/repo)
|
|
55
|
+
|
|
56
|
+
These flags are mutually exclusive. If no flag is provided, the TypeScript template is used.
|
|
57
|
+
|
|
58
|
+
### Help
|
|
59
|
+
|
|
60
|
+
`--help`
|
|
61
|
+
|
|
62
|
+
Shows all available CLI options:
|
|
63
|
+
|
|
24
64
|
```
|
|
65
|
+
Usage: npx create-contentful-app [options] [app-name]
|
|
66
|
+
|
|
67
|
+
Bootstrap your app inside a new folder `my-app`
|
|
25
68
|
|
|
26
|
-
|
|
69
|
+
create-contentful-app my-app
|
|
70
|
+
|
|
71
|
+
or specify your own template
|
|
72
|
+
|
|
73
|
+
create-contentful-app my-app --source "github:user/repo"
|
|
74
|
+
|
|
75
|
+
Official Contentful templates are hosted at https://github.com/contentful/apps/tree/master/examples.
|
|
76
|
+
|
|
77
|
+
Arguments:
|
|
78
|
+
app-name app name
|
|
79
|
+
|
|
80
|
+
Options:
|
|
81
|
+
--npm use npm
|
|
82
|
+
--yarn use Yarn
|
|
83
|
+
-js, --javascript use default JavaScript template
|
|
84
|
+
-ts, --typescript use default TypeScript template
|
|
85
|
+
-e, --example <example-name> bootstrap an example app from https://github.com/contentful/apps/tree/master/examples
|
|
86
|
+
-s, --source <url> provide a template by its source repository.
|
|
87
|
+
format: URL (HTTPS or SSH) or vendor:user/repo (e.g., github:user/repo)
|
|
88
|
+
-h, --help shows all available CLI options
|
|
89
|
+
```
|
package/lib/index.js
CHANGED
|
@@ -1,133 +1,131 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
const fs_1 = require("fs");
|
|
17
|
+
const path_1 = require("path");
|
|
18
|
+
const os_1 = require("os");
|
|
19
|
+
const validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
|
|
20
|
+
const commander_1 = require("commander");
|
|
21
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
22
|
+
const tildify_1 = __importDefault(require("tildify"));
|
|
23
|
+
const template_1 = require("./template");
|
|
24
|
+
const utils_1 = require("./utils");
|
|
25
|
+
const logger_1 = require("./logger");
|
|
26
|
+
const DEFAULT_APP_NAME = 'contentful-app';
|
|
27
|
+
function successMessage(folder) {
|
|
28
|
+
console.log(`
|
|
29
|
+
${(0, logger_1.success)('Success!')} Created a new Contentful app in ${(0, logger_1.highlight)((0, tildify_1.default)(folder))}.
|
|
2
30
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const chalk = require('chalk');
|
|
6
|
-
const spawn = require('cross-spawn');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const tildify = require('tildify');
|
|
9
|
-
const { createAppDefinition } = require('@contentful/app-scripts');
|
|
10
|
-
const packageJson = require('../package.json');
|
|
11
|
-
|
|
12
|
-
const command = process.argv[2];
|
|
13
|
-
const appFolder = process.argv[3];
|
|
14
|
-
|
|
15
|
-
const localCommand = '@contentful/create-contentful-app';
|
|
16
|
-
const mainCommand = `npx ${localCommand}`;
|
|
17
|
-
|
|
18
|
-
function getTemplate() {
|
|
19
|
-
const templatePkg = '@contentful/cra-template-create-contentful-app';
|
|
20
|
-
|
|
21
|
-
if (!process.env.USE_LINKED_TEMPLATE) {
|
|
22
|
-
const templateVersion =
|
|
23
|
-
packageJson.dependencies['@contentful/cra-template-create-contentful-app'].slice(1);
|
|
24
|
-
return `${templatePkg}@${templateVersion}`;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const linkedTemplatePath = path.relative(
|
|
28
|
-
process.cwd(),
|
|
29
|
-
path.dirname(require.resolve(templatePkg))
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
console.log();
|
|
33
|
-
console.log(chalk.dim('> Using linked template at %s'), chalk.blueBright(linkedTemplatePath));
|
|
34
|
-
console.log();
|
|
35
|
-
|
|
36
|
-
return `file:${linkedTemplatePath}`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function onSuccess(folder) {
|
|
40
|
-
console.log(`
|
|
41
|
-
${chalk.cyan('Success!')} Created a new Contentful app in ${chalk.bold(
|
|
42
|
-
tildify(path.resolve(process.cwd(), folder))
|
|
43
|
-
)}.
|
|
44
|
-
|
|
45
|
-
We suggest that you begin by running:
|
|
31
|
+
Now kick it off by running
|
|
46
32
|
|
|
47
|
-
${
|
|
48
|
-
${
|
|
33
|
+
${(0, logger_1.code)(`cd ${(0, tildify_1.default)(folder)}`)}
|
|
34
|
+
${(0, logger_1.code)(`npm start`)}
|
|
49
35
|
`);
|
|
50
|
-
|
|
51
|
-
process.exit();
|
|
52
36
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const args = [createReactApp, appFolder, '--template', template, '--use-npm'];
|
|
70
|
-
|
|
71
|
-
console.log(
|
|
72
|
-
`Creating a Contentful app in ${chalk.bold(tildify(path.resolve(process.cwd(), appFolder)))}.`
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
const appCreateProcess = spawn(initCommand, args, { stdio: 'inherit' });
|
|
76
|
-
appCreateProcess.on('exit', (exitCode) => {
|
|
77
|
-
if (exitCode === 0) {
|
|
78
|
-
onSuccess(appFolder);
|
|
79
|
-
} else {
|
|
80
|
-
process.exit(exitCode);
|
|
81
|
-
}
|
|
37
|
+
function updatePackageName(appFolder) {
|
|
38
|
+
const packageJsonPath = (0, path_1.resolve)(appFolder, 'package.json');
|
|
39
|
+
const packageJson = JSON.parse((0, fs_1.readFileSync)(packageJsonPath, { encoding: 'utf-8' }));
|
|
40
|
+
packageJson.name = (0, path_1.basename)(appFolder);
|
|
41
|
+
(0, fs_1.writeFileSync)(packageJsonPath, JSON.stringify(packageJson, null, 2) + os_1.EOL);
|
|
42
|
+
}
|
|
43
|
+
function promptAppName() {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
return yield inquirer_1.default.prompt([
|
|
46
|
+
{
|
|
47
|
+
name: 'name',
|
|
48
|
+
message: 'App name',
|
|
49
|
+
default: DEFAULT_APP_NAME,
|
|
50
|
+
},
|
|
51
|
+
]);
|
|
82
52
|
});
|
|
83
|
-
} catch (err) {
|
|
84
|
-
console.log(`${chalk.red('Error:')} Failed to create ${appFolder}:
|
|
85
|
-
|
|
86
|
-
${err}
|
|
87
|
-
`);
|
|
88
|
-
process.exit(1);
|
|
89
|
-
}
|
|
90
53
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Validates the user input and ensures it can be used as app name. If no app name is provided, shows a prompt.
|
|
56
|
+
*
|
|
57
|
+
* @param appName App name entered by the user
|
|
58
|
+
* @returns Valid app name
|
|
59
|
+
*/
|
|
60
|
+
function validateAppName(appName) {
|
|
61
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
if (appName === 'create-definition') {
|
|
63
|
+
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.`);
|
|
64
|
+
}
|
|
65
|
+
if (appName === 'init') {
|
|
66
|
+
(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.`);
|
|
67
|
+
appName = '';
|
|
68
|
+
}
|
|
69
|
+
if (!appName) {
|
|
70
|
+
const prompt = yield promptAppName();
|
|
71
|
+
appName = prompt.name;
|
|
72
|
+
}
|
|
73
|
+
if (!(0, validate_npm_package_name_1.default)(appName).validForNewPackages) {
|
|
74
|
+
throw new Error(`Cannot create an app named "${appName}". Please choose a different name for your app.`);
|
|
75
|
+
}
|
|
76
|
+
return appName;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function initProject(appName, options) {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
const normalizedOptions = (0, utils_1.normalizeOptions)(options);
|
|
82
|
+
try {
|
|
83
|
+
appName = yield 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
|
+
yield (0, template_1.cloneTemplateIn)(fullAppFolder, normalizedOptions);
|
|
87
|
+
updatePackageName(fullAppFolder);
|
|
88
|
+
if (normalizedOptions.yarn || (0, utils_1.detectManager)() === 'yarn') {
|
|
89
|
+
yield (0, utils_1.exec)('yarn', [], { cwd: fullAppFolder });
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
yield (0, utils_1.exec)('npm', ['install', '--no-audit', '--no-fund'], { cwd: fullAppFolder });
|
|
93
|
+
}
|
|
94
|
+
successMessage(fullAppFolder);
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
(0, logger_1.error)(`Failed to create ${appName}`, String(err));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
(function main() {
|
|
103
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
commander_1.program
|
|
105
|
+
.name(`npx ${(0, logger_1.code)('create-contentful-app')}`)
|
|
106
|
+
.helpOption(true, 'shows all available CLI options')
|
|
107
|
+
.description([
|
|
108
|
+
'Bootstrap your app inside a new folder `my-app`',
|
|
109
|
+
'',
|
|
110
|
+
(0, logger_1.code)(' create-contentful-app my-app'),
|
|
111
|
+
'',
|
|
112
|
+
'or specify your own template',
|
|
113
|
+
'',
|
|
114
|
+
(0, logger_1.code)(' create-contentful-app my-app --source "github:user/repo"'),
|
|
115
|
+
'',
|
|
116
|
+
`Official Contentful templates are hosted at ${(0, logger_1.highlight)('https://github.com/contentful/apps/tree/master/examples')}.`,
|
|
117
|
+
].join('\n'))
|
|
118
|
+
.argument('[app-name]', 'app name')
|
|
119
|
+
.option('--npm', 'use npm')
|
|
120
|
+
.option('--yarn', 'use Yarn')
|
|
121
|
+
.option('-ts, --typescript', 'use TypeScript template (default)')
|
|
122
|
+
.option('-js, --javascript', 'use JavaScript template')
|
|
123
|
+
.option('-e, --example <example-name>', 'bootstrap an example app from https://github.com/contentful/apps/tree/master/examples')
|
|
124
|
+
.option('-s, --source <url>', [
|
|
125
|
+
`provide a template by its source repository.`,
|
|
126
|
+
`format: URL (HTTPS or SSH) or ${(0, logger_1.code)('vendor:user/repo')} (e.g., ${(0, logger_1.code)('github:user/repo')})`,
|
|
127
|
+
].join('\n'))
|
|
128
|
+
.action(initProject);
|
|
129
|
+
yield commander_1.program.parseAsync();
|
|
130
|
+
});
|
|
133
131
|
})();
|
package/lib/logger.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
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.code = exports.success = exports.choice = exports.highlight = exports.error = exports.warn = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
function warn(message) {
|
|
9
|
+
console.log(`${chalk_1.default.yellow('Warning:')} ${message}`);
|
|
10
|
+
}
|
|
11
|
+
exports.warn = warn;
|
|
12
|
+
function error(message, error) {
|
|
13
|
+
console.log(`${chalk_1.default.red('Error:')} ${message}
|
|
14
|
+
|
|
15
|
+
${error.startsWith('Error: ') ? error.substring(7) : error}
|
|
16
|
+
`);
|
|
17
|
+
}
|
|
18
|
+
exports.error = error;
|
|
19
|
+
function highlight(str) {
|
|
20
|
+
return chalk_1.default.bold(str);
|
|
21
|
+
}
|
|
22
|
+
exports.highlight = highlight;
|
|
23
|
+
function choice(str) {
|
|
24
|
+
return chalk_1.default.cyan(str);
|
|
25
|
+
}
|
|
26
|
+
exports.choice = choice;
|
|
27
|
+
function success(str) {
|
|
28
|
+
return chalk_1.default.greenBright(str);
|
|
29
|
+
}
|
|
30
|
+
exports.success = success;
|
|
31
|
+
function code(str) {
|
|
32
|
+
return chalk_1.default.bold(str);
|
|
33
|
+
}
|
|
34
|
+
exports.code = code;
|
package/lib/template.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.cloneTemplateIn = void 0;
|
|
16
|
+
const path_1 = require("path");
|
|
17
|
+
const fs_1 = require("fs");
|
|
18
|
+
const degit_1 = __importDefault(require("degit"));
|
|
19
|
+
const rimraf_1 = __importDefault(require("rimraf"));
|
|
20
|
+
const types_1 = require("./types");
|
|
21
|
+
const logger_1 = require("./logger");
|
|
22
|
+
const utils_1 = require("./utils");
|
|
23
|
+
const EXAMPLES_PATH = 'contentful/apps/examples/';
|
|
24
|
+
function isContentfulTemplate(url) {
|
|
25
|
+
return Object.values(types_1.ContentfulExample).some(t => url.includes(EXAMPLES_PATH + t));
|
|
26
|
+
}
|
|
27
|
+
function makeContentfulExampleSource(options) {
|
|
28
|
+
if (options.example) {
|
|
29
|
+
return EXAMPLES_PATH + options.example;
|
|
30
|
+
}
|
|
31
|
+
if (options.javascript) {
|
|
32
|
+
return EXAMPLES_PATH + types_1.ContentfulExample.Javascript;
|
|
33
|
+
}
|
|
34
|
+
return EXAMPLES_PATH + types_1.ContentfulExample.Typescript;
|
|
35
|
+
}
|
|
36
|
+
function getTemplateSource(options) {
|
|
37
|
+
var _a;
|
|
38
|
+
const source = (_a = options.source) !== null && _a !== void 0 ? _a : makeContentfulExampleSource(options);
|
|
39
|
+
if (options.source && !isContentfulTemplate(source)) {
|
|
40
|
+
(0, logger_1.warn)(`Template at ${(0, logger_1.highlight)(source)} is not an official Contentful app template!`);
|
|
41
|
+
}
|
|
42
|
+
return source;
|
|
43
|
+
}
|
|
44
|
+
function clone(source, destination) {
|
|
45
|
+
var _a;
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
const d = (0, degit_1.default)(source, { mode: 'tar', cache: false });
|
|
48
|
+
try {
|
|
49
|
+
yield d.clone(destination);
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
let message = (_a = e.message) !== null && _a !== void 0 ? _a : 'Unknown error';
|
|
53
|
+
if (e.code === 'DEST_NOT_EMPTY') {
|
|
54
|
+
message = 'Destination directory is not empty.';
|
|
55
|
+
}
|
|
56
|
+
throw new Error(message);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function validate(destination) {
|
|
61
|
+
const packageJSONLocation = `${destination}/package.json`;
|
|
62
|
+
if (!(0, fs_1.existsSync)(packageJSONLocation)) {
|
|
63
|
+
throw new Error(`Invalid template: missing "${packageJSONLocation}".`);
|
|
64
|
+
}
|
|
65
|
+
let packageJSON;
|
|
66
|
+
try {
|
|
67
|
+
packageJSON = JSON.parse((0, fs_1.readFileSync)(packageJSONLocation, 'utf-8'));
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
throw new Error(`Invalid template: invalid "${packageJSONLocation}".`);
|
|
71
|
+
}
|
|
72
|
+
if (!Object.keys(packageJSON.dependencies).includes('@contentful/app-sdk')) {
|
|
73
|
+
throw new Error(`Invalid template: missing "@contentful/app-sdk" in "${packageJSONLocation}".`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function cleanUp(destination) {
|
|
77
|
+
(0, utils_1.rmIfExists)((0, path_1.resolve)(destination, 'package-lock.json'));
|
|
78
|
+
(0, utils_1.rmIfExists)((0, path_1.resolve)(destination, 'yarn.lock'));
|
|
79
|
+
}
|
|
80
|
+
function cloneTemplateIn(destination, options) {
|
|
81
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
const source = getTemplateSource(options);
|
|
83
|
+
yield clone(source, destination);
|
|
84
|
+
try {
|
|
85
|
+
validate(destination);
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
// cleanup in case of invalid example
|
|
89
|
+
rimraf_1.default.sync(destination);
|
|
90
|
+
throw e;
|
|
91
|
+
}
|
|
92
|
+
cleanUp(destination);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
exports.cloneTemplateIn = cloneTemplateIn;
|
package/lib/types.js
ADDED
package/lib/utils.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeOptions = exports.detectManager = exports.rmIfExists = exports.exec = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const logger_1 = require("./logger");
|
|
8
|
+
const MUTUALLY_EXCLUSIVE_OPTIONS = ['source', 'example', 'javascript', 'typescript'];
|
|
9
|
+
function exec(command, args, options) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const process = (0, child_process_1.spawn)(command, args, Object.assign({ stdio: 'inherit' }, options));
|
|
12
|
+
process.on('exit', (exitCode) => {
|
|
13
|
+
if (exitCode === 0) {
|
|
14
|
+
resolve();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
reject();
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
exports.exec = exec;
|
|
23
|
+
function rmIfExists(path) {
|
|
24
|
+
if ((0, fs_1.existsSync)(path)) {
|
|
25
|
+
(0, fs_1.rmSync)(path);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.rmIfExists = rmIfExists;
|
|
29
|
+
function detectManager() {
|
|
30
|
+
switch ((0, path_1.basename)(process.env.npm_execpath || '')) {
|
|
31
|
+
case 'yarn.js':
|
|
32
|
+
return 'yarn';
|
|
33
|
+
case 'npx-cli.js':
|
|
34
|
+
case 'npm-cli.js':
|
|
35
|
+
default:
|
|
36
|
+
return 'npm';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.detectManager = detectManager;
|
|
40
|
+
function normalizeOptions(options) {
|
|
41
|
+
const normalizedOptions = Object.assign({}, options);
|
|
42
|
+
if (normalizedOptions.npm && normalizedOptions.yarn) {
|
|
43
|
+
(0, logger_1.warn)(`Provided both ${(0, logger_1.highlight)('--yarn')} and ${(0, logger_1.highlight)('--npm')} flags, using ${(0, logger_1.choice)('--npm')}.`);
|
|
44
|
+
delete normalizedOptions.yarn;
|
|
45
|
+
}
|
|
46
|
+
if (!normalizedOptions.yarn) {
|
|
47
|
+
normalizedOptions.npm = true;
|
|
48
|
+
}
|
|
49
|
+
let fallbackOption = '--typescript';
|
|
50
|
+
const currentMutuallyExclusiveOptions = MUTUALLY_EXCLUSIVE_OPTIONS.filter((option) => normalizedOptions[option]);
|
|
51
|
+
if (normalizedOptions.source) {
|
|
52
|
+
fallbackOption = '--source';
|
|
53
|
+
delete normalizedOptions.example;
|
|
54
|
+
delete normalizedOptions.typescript;
|
|
55
|
+
delete normalizedOptions.javascript;
|
|
56
|
+
}
|
|
57
|
+
if (normalizedOptions.example) {
|
|
58
|
+
fallbackOption = '--example';
|
|
59
|
+
delete normalizedOptions.typescript;
|
|
60
|
+
delete normalizedOptions.javascript;
|
|
61
|
+
}
|
|
62
|
+
if (normalizedOptions.typescript) {
|
|
63
|
+
fallbackOption = '--typescript';
|
|
64
|
+
delete normalizedOptions.javascript;
|
|
65
|
+
}
|
|
66
|
+
if (!normalizedOptions.javascript) {
|
|
67
|
+
normalizedOptions.typescript = true;
|
|
68
|
+
}
|
|
69
|
+
if (currentMutuallyExclusiveOptions.length > 1) {
|
|
70
|
+
(0, logger_1.warn)(`Options ${(0, logger_1.highlight)('--source')}, ${(0, logger_1.highlight)('--example')}, ${(0, logger_1.highlight)('--typescript')} and ${(0, logger_1.highlight)('--javascript')} are mutually exclusive, using ${(0, logger_1.choice)(fallbackOption)}.`);
|
|
71
|
+
}
|
|
72
|
+
return normalizedOptions;
|
|
73
|
+
}
|
|
74
|
+
exports.normalizeOptions = normalizeOptions;
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/create-contentful-app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.1.0-alpha.10",
|
|
4
4
|
"description": "A template for building Contentful Apps",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"contentful",
|
|
7
|
+
"create-contentful-app"
|
|
8
|
+
],
|
|
5
9
|
"author": "Contentful GmbH",
|
|
6
10
|
"license": "MIT",
|
|
7
11
|
"repository": {
|
|
@@ -10,7 +14,7 @@
|
|
|
10
14
|
"directory": "packages/contentful--create-contentful-app"
|
|
11
15
|
},
|
|
12
16
|
"engines": {
|
|
13
|
-
"node": ">=
|
|
17
|
+
"node": ">=14.15.0",
|
|
14
18
|
"npm": ">=6"
|
|
15
19
|
},
|
|
16
20
|
"main": "lib/index.js",
|
|
@@ -25,34 +29,40 @@
|
|
|
25
29
|
},
|
|
26
30
|
"scripts": {
|
|
27
31
|
"prettier": "prettier **/*.js --write --ignore-path .gitignore",
|
|
28
|
-
"lint": "eslint ./
|
|
32
|
+
"lint": "eslint ./src",
|
|
29
33
|
"lint:fix": "npm run lint -- --fix",
|
|
30
|
-
"pre-commit": "lint-staged"
|
|
34
|
+
"pre-commit": "lint-staged",
|
|
35
|
+
"build": "tsc"
|
|
31
36
|
},
|
|
32
37
|
"dependencies": {
|
|
33
|
-
"@contentful/app-scripts": "^0.
|
|
34
|
-
"@contentful/cra-template-create-contentful-app": "^0.15.4",
|
|
38
|
+
"@contentful/app-scripts": "^0.16.0-alpha.3",
|
|
35
39
|
"chalk": "^4.1.0",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
40
|
+
"commander": "^9.0.0",
|
|
41
|
+
"degit": "2.8.4",
|
|
42
|
+
"inquirer": "^8.2.1",
|
|
43
|
+
"rimraf": "^3.0.2",
|
|
44
|
+
"tildify": "^2.0.0",
|
|
45
|
+
"validate-npm-package-name": "^3.0.0"
|
|
42
46
|
},
|
|
43
47
|
"bugs": {
|
|
44
48
|
"url": "https://github.com/contentful/create-contentful-app/issues"
|
|
45
49
|
},
|
|
46
50
|
"homepage": "https://github.com/contentful/create-contentful-app#readme",
|
|
47
|
-
"directories": {
|
|
48
|
-
"lib": "lib",
|
|
49
|
-
"test": "test"
|
|
50
|
-
},
|
|
51
51
|
"files": [
|
|
52
52
|
"lib"
|
|
53
53
|
],
|
|
54
54
|
"publishConfig": {
|
|
55
55
|
"access": "public"
|
|
56
56
|
},
|
|
57
|
-
"
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@tsconfig/node16": "^1.0.2",
|
|
59
|
+
"@types/chalk": "^2.2.0",
|
|
60
|
+
"@types/degit": "^2.8.3",
|
|
61
|
+
"@types/inquirer": "^8.2.0",
|
|
62
|
+
"@types/node": "^14.14.31",
|
|
63
|
+
"@types/rimraf": "^3.0.2",
|
|
64
|
+
"@types/tildify": "^2.0.2",
|
|
65
|
+
"@types/validate-npm-package-name": "^3.0.3"
|
|
66
|
+
},
|
|
67
|
+
"gitHead": "fb5a4faf89f78af13da791f60f549a27d416359a"
|
|
58
68
|
}
|