@shipengine/connect
Version:
The official developer tooling for building ShipEngine connect apps
373 lines • 14.5 kB
JavaScript
"use strict";
const tslib_1 = require("tslib");
const fs = tslib_1.__importStar(require("fs"));
const { readdirSync, statSync } = require('fs');
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const path_1 = require("path");
const uuid_1 = require("uuid");
const Generator = require("yeoman-generator");
const app_loader_1 = require("../app-loader");
const fixpack = require('@oclif/fixpack');
const sortPjson = require('sort-pjson');
class AppsNew extends Generator {
appId;
type;
path;
pjson;
logoColor;
githubUser;
answers;
ts;
useNativeRating;
constructor(args, opts) {
super(args, opts);
this.appId = (0, uuid_1.v4)();
this.path = opts.path;
this.type = app_loader_1.AppType.Carrier;
this.logoColor = logoColors[Math.floor(Math.random() * logoColors.length)];
}
async prompting() {
if (this.path) {
this.destinationRoot((0, path_1.resolve)(this.path));
process.chdir(this.destinationRoot());
}
try {
this.githubUser = await this.user.github.username();
}
catch {
this.githubUser = undefined;
}
this.pjson = {
appId: this.appId,
private: true,
engines: {},
devDependencies: {},
dependencies: {},
connect: {
version: 4,
},
...this.fs.readJSON('package.json', {}),
};
const defaults = {
name: this.determineAppname(),
type: 'carrier',
version: '1.0.0',
author: this.githubUser
? `${this.user.git.name()} @${this.githubUser}`
: this.user.git.name(),
dependencies: {},
...this.pjson,
engines: {
node: '>=14.0.0',
...this.pjson.engines,
},
typescript: true,
useNativeRating: false,
};
if (this.options.useDefaults) {
this.answers = defaults;
}
else {
this.answers = (await this.prompt([
{
type: 'input',
name: 'name',
message: 'npm package name',
default: defaults.name,
when: !this.pjson.name,
validate: (value) => {
const re = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
const pass = value.match(re);
if (pass) {
return true;
}
return 'please enter a valid npm package name';
},
},
{
type: 'list',
name: 'type',
message: 'what type of app are you building',
choices: [
{ name: 'Carrier app ', value: 'carrier' },
{ name: 'Freight app ', value: 'freight' },
{ name: 'Order app', value: 'order' },
{ name: 'Fulfillment app', value: 'fulfillment' },
],
default: defaults.type,
},
{
type: 'input',
name: 'description',
message: 'description',
default: defaults.description,
when: !this.pjson.description,
},
{
type: 'input',
name: 'author',
message: 'author',
default: defaults.author,
when: !this.pjson.author,
},
{
type: 'input',
name: 'version',
message: 'version',
default: defaults.version,
when: !this.pjson.version,
},
{
type: 'list',
name: 'typescript',
message: 'which language would you like to use',
choices: [
{
name: 'JavaScript',
value: false,
},
{
name: 'TypeScript',
value: true,
},
],
default: defaults.typescript,
},
{
type: 'confirm',
name: 'useNativeRating',
message: 'will this app use native rating',
when: (r) => r.type === 'carrier',
default: false,
},
]));
}
this.type = this.answers.type;
this.ts = this.answers.typescript;
this.useNativeRating = this.answers.useNativeRating;
this.pjson.name = this.answers.name || defaults.name;
this.pjson.description = this.answers.description || defaults.description;
this.pjson.version = this.answers.version || defaults.version;
this.pjson.engines.node = defaults.engines.node;
this.pjson.author = this.answers.author || defaults.author;
this.pjson.keywords = defaults.keywords || ['ShipEngine', `${this.type} app`];
this.pjson.main = this.pJsonMain();
this.pjson.scripts = {
test: 'exit 0',
};
if (this.ts) {
this.pjson.scripts.build = 'tsc';
this.pjson.scripts.watch = 'tsc --watch';
this.pjson.main = 'lib/index.js';
this.pjson.types = 'lib/index.ts';
}
else {
this.pjson.main = 'src/index.js';
}
this.pjson.scripts.start = 'connect start';
}
writing() {
const copyAllFilesTo = (root) => (templateName, fileExtension) => {
const getAllFiles = (template, type) => {
const getAllFiles = (filePath, arrayOfFiles) => {
const fullPath = this.templatePath(filePath);
const files = readdirSync(fullPath);
files.forEach((file) => {
if (statSync(fullPath + path_1.sep + file).isDirectory()) {
arrayOfFiles = getAllFiles((0, path_1.join)(filePath, file), arrayOfFiles);
}
else {
arrayOfFiles.push((0, path_1.join)(fullPath, file));
}
});
return arrayOfFiles;
};
const files = getAllFiles(template, []);
return files.filter((f) => f.endsWith(type));
};
const allFiles = getAllFiles(templateName, fileExtension);
const getPaths = (template, files) => {
return files.map((file) => {
const pathComponents = file.split(path_1.sep);
const indexOfPath = pathComponents.indexOf(template);
const newPath = [];
for (let index = indexOfPath + 1; index < pathComponents.length; index++) {
newPath.push(pathComponents[index]);
}
return newPath.join(path_1.sep);
});
};
const paths = getPaths(templateName, allFiles);
paths.forEach((filePath) => {
this.fs.copyTpl(this.templatePath(templateName, filePath), this.destinationPath((0, path_1.join)(root, filePath)), this);
});
};
const copyAllFilesToSource = copyAllFilesTo('src');
this.sourceRoot((0, path_1.join)(__dirname, '../../../templates'));
if (this.fs.exists(this.destinationPath('./package.json'))) {
fixpack(this.destinationPath('./package.json'), require('@oclif/fixpack/config.json'));
}
this.fs.copyTpl(this.templatePath('README.md.ejs'), this.destinationPath('README.md'), this);
this.fs.copyTpl(this.templatePath('CHANGELOG.md.ejs'), this.destinationPath('CHANGELOG.md'), this);
if (this.ts) {
this.fs.copyTpl(this.templatePath('.npmignore-ts'), this.destinationPath('.npmignore'), this);
}
else {
this.fs.copyTpl(this.templatePath('.npmignore-js'), this.destinationPath('.npmignore'), this);
}
this.fs.copyTpl(this.templatePath('assets/logo.svg.ejs'), this.destinationPath('assets/icon.svg'), this);
this.fs.copyTpl(this.templatePath('assets/logo.svg.ejs'), this.destinationPath('assets/logo.svg'), this);
if (this.ts) {
this.fs.copyTpl(this.templatePath(`tsconfig.json`), this.destinationPath('tsconfig.json'), this);
}
this.fs.write(this.destinationPath('.gitignore'), this._gitignore());
const projectType = this.ts ? 'ts' : 'js';
switch (this.type) {
case app_loader_1.AppType.Carrier:
if (!fs.existsSync('src')) {
copyAllFilesToSource('carrier-api', projectType);
if (this.useNativeRating) {
const copyAllFilesToRoot = copyAllFilesTo('.');
copyAllFilesToRoot('native-rating', projectType);
copyAllFilesToRoot('native-rating', 'json');
this.pjson.scripts.bundle = 'webpack --config webpack.config.js';
this.fs.copyTpl(this.templatePath('native-rating', `webpack.config.js`), this.destinationPath('webpack.config.js'), this);
this.fs.move(this.destinationPath('data', 'demo-carrier', '**'), this.destinationPath('data', this._appName), { globOptions: { dot: true } });
if (!this.ts) {
// It's simpler to copy all files and remove this one if it's not TS than it would be
// to only copy the appropriate files for each language
this.fs.delete(this.destinationPath('tsconfig.webpack.json'));
}
}
}
break;
case app_loader_1.AppType.Freight:
if (!fs.existsSync('src')) {
copyAllFilesToSource('freight-api', this.ts ? 'ts' : 'js');
}
break;
case app_loader_1.AppType.Order:
if (!fs.existsSync('src')) {
copyAllFilesToSource('order-source-api', this.ts ? 'ts' : 'js');
}
break;
case app_loader_1.AppType.Fulfillment:
if (!fs.existsSync('src')) {
copyAllFilesToSource('fulfillment-provider-api', this.ts ? 'ts' : 'js');
}
break;
}
this.fs.writeJSON(this.destinationPath('./package.json'), sortPjson(this.pjson));
}
async install() {
const dependencies = [];
const devDependencies = [];
const version = this.options.dependencyVersion || 'latest';
dependencies.push(`/connect-runtime@${version}`);
devDependencies.push(`/connect@${version}`);
switch (this.type) {
case app_loader_1.AppType.Carrier:
dependencies.push(`/connect-carrier-api@${version}`);
if (this.useNativeRating) {
devDependencies.push('webpack');
devDependencies.push('webpack-cli');
devDependencies.push('webpack-node-externals');
if (this.ts) {
devDependencies.push('ts-loader');
}
}
break;
case app_loader_1.AppType.Freight:
dependencies.push(`/connect-freight-api@${version}`);
break;
case app_loader_1.AppType.Order:
dependencies.push(`/connect-order-source-api@${version}`);
break;
case app_loader_1.AppType.Fulfillment:
dependencies.push(`/connect-fulfillment-provider-api@${version}`);
break;
}
if (this.answers.typescript) {
devDependencies.push('@types/node');
devDependencies.push('typescript');
}
this.spawnCommandSync('npm', [
'install',
'--save-dev',
'--ignore-scripts=true',
...devDependencies,
]);
this.spawnCommandSync('npm', ['install', '--save', ...dependencies]);
}
end() {
this.log(`\nCreated ${this.pjson.name} in ${this.destinationRoot()}`);
}
get _definitionExt() {
return this.ts ? 'ts' : 'js';
}
get _codeExt() {
return this.ts ? 'ts' : 'js';
}
get _uuidv4() {
return (0, uuid_1.v4)();
}
get _appName() {
const name = this.pjson.name.replace('@', '').replace('/', ' ');
return name;
}
get _appId() {
return this.appId;
}
get _ts() {
return this.ts;
}
get _useNativeRating() {
return this.useNativeRating;
}
_gitignore() {
const existing = this.fs.exists(this.destinationPath('.gitignore'))
? this.fs.read(this.destinationPath('.gitignore')).split('\n')
: [];
return ((0, lodash_1.default)([
'*-debug.log',
'*-error.log',
'node_modules',
'/tmp',
'/dist',
'/lib',
'/.nyc_output',
'.env.test',
'/data/**/*.js',
])
.concat(existing)
.compact()
.uniq()
.sort()
.join('\n') + '\n');
}
pJsonMain() {
return this.ts ? 'src/index.ts' : 'src/index.js';
}
}
const logoColors = [
'#f44336',
'#e91e63',
'#9c27b0',
'#673ab7',
'#3f51b5',
'#2196f3',
'#03a9f4',
'#00bcd4',
'#009688',
'#4caf50',
'#8bc34a',
'#cddc39',
'#ffeb3b',
'#ffc107',
'#ff9800',
'#ff5722',
'#795548',
'#607d8b', // blue grey
];
module.exports = AppsNew;
//# sourceMappingURL=apps-new.js.map