digitransit-ui/digitransit-store/scripts/create-new-module
2024-02-05 17:27:58 +02:00

274 lines
No EOL
7 KiB
JavaScript
Executable file

#!/usr/bin/env node
import { existsSync, mkdirSync, writeFileSync, copySync } from 'fs-extra';
import { join } from 'path';
import meow from 'meow';
import camelcase from 'camelcase';
import decamelize from 'decamelize';
const cli = meow(`
Usage:
$ ./scripts/create-new-module <module>
Examples:
$ ./scripts/create-new-module clone
`);
if (!cli.input.length) cli.showHelp();
let name = cli.input[0];
// Normalize module name
// digitransit-store-clone => clone
name = name.replace(/digitransit-store-/, '');
const camelcaseName = camelcase(name);
const decamelizeName = decamelize(name, '-');
const pascalCaseName = camelcase(name, {pascalCase: true});
// Create Folder
const folderPath = join(__dirname, '..', 'packages', `digitransit-store-${decamelizeName}`);
if (!existsSync(folderPath)) {
mkdirSync(folderPath);
mkdirSync(join(folderPath, 'src'));
}
// Create index.js
writeFileSync(join(folderPath, 'src', 'index.js'), `/* eslint class-methods-use-this: ["error", { "exceptMethods": ["saveStorage"] }] */
/* eslint-disable no-useless-constructor */
import Store from 'fluxible/addons/BaseStore';
import {
getItemAsJson,
setItem,
} from '@digitransit-store/digitransit-store-common-functions';
class ${pascalCaseName} extends Store {
static storeName = '${pascalCaseName}Store';
emptyData = {
items: [],
};
constructor() {
super();
}
getStorage() {
return getItemAsJson('${camelcaseName}s', JSON.stringify(this.emptyData));
}
saveStorage(data) {
setItem('${camelcaseName}s', data);
}
get${pascalCaseName}s() {
const storage = this.getStorage();
if (!storage) {
this.saveStorage(this.emptyData);
this.emitChange();
}
return storage;
}
save${pascalCaseName}(${camelcaseName}) {
const items = this.get${pascalCaseName}s();
const newItems = [...items, ${camelcaseName}];
const storage = {
items: newItems,
};
this.saveStorage(storage);
this.emitChange();
}
clear${pascalCaseName}s() {
this.saveStorage(this.emptyData);
this.emitChange();
}
static handlers = {
save${pascalCaseName}: 'save${pascalCaseName}',
};
}
const ${pascalCaseName}Store = ${pascalCaseName};
export default ${pascalCaseName}Store;
`);
// Create package.json
writeFileSync(join(folderPath, 'package.json'), `{
"name": "@digitransit-store/digitransit-store-${decamelizeName}",
"version": "0.0.1",
"description": "digitransit-store ${decamelizeName} module",
"main": "lib/index.js",
"publishConfig": {
"access": "public"
},
"scripts": {
"build:index": "ENV=production webpack --config webpack.config.babel.js && yarn run docs",
"build:test": "babel test.js --presets=@babel/preset-react,@babel/preset-env --plugins=@babel/plugin-transform-class-properties,@babel/plugin-transform-numeric-separator --out-file test.generated",
"watch": "ENV=development webpack --watch --config webpack.config.babel.js",
"clean": "rm -rf ./lib ./node_modules",
"test": "mocha -r esm -r mock-local-storage test.generated",
"docs": "node -r esm ../../scripts/generate-readmes"
},
"repository": {
"type": "git",
"url": "git://github.com/HSLdevcom/digitransit-ui.git"
},
"keywords": [
"digitransit-store",
"${pascalCaseName}"
],
"author": "Digitransit Authors",
"license": "(AGPL-3.0 OR EUPL-1.2)"
}
`);
// Create LICENSE-AGPL
const licenseAGPL = join(__dirname, '..', '..', 'LICENSE-AGPL.txt');
copySync(licenseAGPL, join(folderPath, 'LICENSE-AGPL.txt'));
// Create LICENSE-EUPL
const licenseEUPL = join(__dirname, '..', '..', 'LICENSE-EUPL.txt');
copySync(licenseEUPL, join(folderPath, 'LICENSE-EUPL.txt'));
// Create test.js
writeFileSync(join(folderPath, 'test.js'), `import { expect } from 'chai';
import { beforeEach, describe, it } from 'mocha';
import ${pascalCaseName}Store from '@digitransit-store/digitransit-store-${decamelizeName}';
import './mock-localstorage';
describe('Testing @digitransit-store/digitransit-store-${decamelizeName} module', () => {
let store;
beforeEach(() => {
store = new ${pascalCaseName}Store();
});
describe('get${pascalCaseName}s()', () => {
it('Property \'items\' should be found', () => {
const items = store.get${pascalCaseName}s();
expect(items).to.have.property('items').with.lengthOf(0);
});
});
});
`);
// Create README.md
writeFileSync(join(folderPath, 'README.md'), `# @digitransit-store/${decamelizeName}
# ${camelcaseName}
<DESCRIPTION>
**Parameters**
<PARAMETERS>
**Examples**
<!-- This file is automatically generated. Please don't edit it directly:
if you find an error, edit the source file (likely index.js), and re-run
./scripts/generate-readmes in the digitransit-store folder. -->
---
This module is part of the Digitransit project. It is maintained in the
[HSLdevcom/digitransit-ui](https://github.com/HSLdevcom/digitransit-ui) repository, where you can create
PRs and issues.
### Installation
Install this module individually:
\`\`\`sh
$ npm install @digitransit-store/${decamelizeName}
\`\`\`
Or install the digitransit-store module that includes it as a class:
\`\`\`sh
$ npm install @digitransit-store/digitransit-store
\`\`\`
`);
writeFileSync(join(folderPath, 'webpack.config.babel.js'), `const path = require('path');
const mode = process.env.ENV;
const isProduction = mode === 'production';
module.exports = {
mode,
devtool: isProduction ? 'source-map' : 'eval',
output: {
globalObject: "typeof self !== 'undefined' ? self : this",
filename: 'index.js',
path: path.join(__dirname, 'lib'),
libraryTarget: 'umd',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
configFile: false,
presets: [
[
'@babel/preset-env',
{
modules: false,
},
],
['@babel/preset-react', { useBuiltIns: true }],
],
plugins: [
[
'@babel/plugin-transform-runtime',
{
helpers: true,
regenerator: true,
useESModules: true,
},
],
'@babel/plugin-transform-class-properties',
'@babel/plugin-transform-numeric-separator',
['inline-react-svg'],
],
},
},
{
test: /\.s(a|c)ss$/,
use: [
'iso-morphic-style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true,
},
},
{
loader: 'sass-loader',
},
],
},
],
},
resolve: {
extensions: ['.js', '.scss'],
},
externals: [
{
react: 'umd react',
'react-dom': 'umd react-dom',
},
],
target: 'node',
};
`);
// Create mock-localstorage.js
writeFileSync(join(folderPath, 'mock-localstorage.js'), `import 'mock-local-storage';
global.window = {};
window.localStorage = global.localStorage;
`);