promisify, multi-argument interactive mode commands, readme, license
This commit is contained in:
parent
7633dda7a5
commit
037ccb62c4
19
LICENSE.txt
Normal file
19
LICENSE.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright © 2020 Evert "Diamond" Prants <evert@lunasqu.ee>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||||
|
software and associated documentation files (the “Software”), to deal in the Software
|
||||||
|
without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||||
|
to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
63
README.md
Normal file
63
README.md
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# Squeebot CLI
|
||||||
|
This package provides the runtime and tooling for Squeebot 3.x.x!
|
||||||
|
This package provides two binaries via npm: `squeebot` and `squeebotd`.
|
||||||
|
|
||||||
|
## Running Squeebot
|
||||||
|
1. Create an environment: `$ squeebot new <name> [<path>]`
|
||||||
|
2. Execute the environment in interactive mode using `squeebotd`: `$ squeebotd -i <path>/<name>.json`
|
||||||
|
3. Install plugins (documented below)
|
||||||
|
|
||||||
|
`squeebotd` just takes the path to the generated json file and creates all other necessary files and directories by itself.
|
||||||
|
The primary configuration will be located in `<path>/configs/squeebot.json`.
|
||||||
|
|
||||||
|
## Installing plugins
|
||||||
|
In order to install plugins, you have to add a repository. Repositories are JSON files served over HTTP.
|
||||||
|
|
||||||
|
For example, installing core plugins (Interactive mode `-i` on `squeebotd`):
|
||||||
|
1. `repository install https://(TODO)/repository.json`
|
||||||
|
2. `plugin install control mqtt`
|
||||||
|
3. `plugin list`
|
||||||
|
|
||||||
|
## Interactive mode commands
|
||||||
|
The following commands are available when starting in interactive mode:
|
||||||
|
* `repository help`
|
||||||
|
* `plugin help`
|
||||||
|
* `channel help`
|
||||||
|
* `quit`
|
||||||
|
|
||||||
|
## Creating a repository
|
||||||
|
In order to create a repository, you need to do the following:
|
||||||
|
1. Create a new repository: `$ squeebot repository new <name> [<path>]`
|
||||||
|
2. Build your new repository: `$ squeebot repository build <path>`
|
||||||
|
3. Your built plugins, both archived and unarchived, are in `<path>/.out`.
|
||||||
|
|
||||||
|
Repositories are created with a TypeScript build environment by default. If you do not wish to use TypeScript (not recommended) for your plugins,
|
||||||
|
add the `-t` flag to `squeebot repository new` command.
|
||||||
|
|
||||||
|
The build command supports a `-w` argument which will execute the entire build command again when you make changes (watch mode).
|
||||||
|
**Including deployments, if `-d` is present!**
|
||||||
|
|
||||||
|
### Creating plugins
|
||||||
|
Within your new repository, each directory you make will be a plugin. The plugin **must** contain the following:
|
||||||
|
1. `plugin.json` - Manifest for your plugin.
|
||||||
|
2. `plugin.js` - Has to be a JavaScript file which exports a class inherited from `Plugin` at `@squeebot/core/lib/plugin`.
|
||||||
|
|
||||||
|
**Note:** `plugin.js` only has to exist in the distribution, so `.ts` is fine, but you have to use `$ squeebot repository build <path>`
|
||||||
|
to build them into JavaScript files.
|
||||||
|
|
||||||
|
Plugin manifest (`plugin.json`) example:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"name": "plugin-name", // The name of your plugin, must match the name of the directory
|
||||||
|
"version": "0.0.0", // The version of your plugin, must be semantic versioning!
|
||||||
|
"description": "", // Optional description for this plugin
|
||||||
|
"dependencies": [], // List of plugins this plugin depends on
|
||||||
|
"npmDependencies": [], // List of npm modules this plugin depends on. Supports versions, example 'thing@1.0.0'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploying the repository
|
||||||
|
You can configure deployment options using a file called `deployment.json` in your repository root. Currently supported deployment methods:
|
||||||
|
1. TODO!
|
||||||
|
|
||||||
|
In order to activate your configured deployment, use the `-d` flag when building your repository. `-o` flag skips build and deploys immediately.
|
158
src/cli.ts
158
src/cli.ts
@ -6,18 +6,17 @@ import { Squeebot } from './core';
|
|||||||
export class SqueebotCLI {
|
export class SqueebotCLI {
|
||||||
constructor(private bot: Squeebot) {}
|
constructor(private bot: Squeebot) {}
|
||||||
|
|
||||||
private checkUpdate(repo: IRepository): void {
|
private async checkUpdate(repo: IRepository): Promise<void> {
|
||||||
this.bot.repositoryManager.checkForUpdates(repo).then((updatable) => {
|
const updatable = await this.bot.repositoryManager.checkForUpdates(repo);
|
||||||
if (updatable.length) {
|
if (updatable.length) {
|
||||||
logger.log('[%s] The following plugins can be updated:', repo.name,
|
logger.log('[%s] The following plugins can be updated:', repo.name,
|
||||||
updatable.map((u) => u.name).join(', '));
|
updatable.map((u) => u.name).join(', '));
|
||||||
} else {
|
} else {
|
||||||
logger.log('[%s] All plugins are up-to-date!', repo.name);
|
logger.log('[%s] All plugins are up-to-date!', repo.name);
|
||||||
}
|
}
|
||||||
}, (e) => logger.error(e.message));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private repositoryCommand(...args: any[]): void {
|
private async repositoryCommand(...args: any[]): Promise<void> {
|
||||||
const help = 'repository add <url> | update <name> | remove <name>';
|
const help = 'repository add <url> | update <name> | remove <name>';
|
||||||
if (!args[0] || args[0] === 'help') {
|
if (!args[0] || args[0] === 'help') {
|
||||||
logger.log(help);
|
logger.log(help);
|
||||||
@ -34,9 +33,10 @@ export class SqueebotCLI {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bot.repositoryManager.installRepository(args[1]).then((repo) => {
|
for (const urlp of args.slice(1)) {
|
||||||
|
const repo = await this.bot.repositoryManager.installRepository(urlp);
|
||||||
logger.log('Installed repository %s!', repo.name);
|
logger.log('Installed repository %s!', repo.name);
|
||||||
}, (e) => logger.error(e.message));
|
}
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
case 'rem':
|
case 'rem':
|
||||||
@ -47,9 +47,10 @@ export class SqueebotCLI {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bot.repositoryManager.uninstallRepository(args[1]).then(() => {
|
for (const namep of args.slice(1)) {
|
||||||
logger.log('Installed repository %s.', args[1]);
|
await this.bot.repositoryManager.uninstallRepository(namep);
|
||||||
}, (e) => logger.error(e.message));
|
logger.log('Installed repository %s.', namep);
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
case 'upd':
|
case 'upd':
|
||||||
@ -57,25 +58,27 @@ export class SqueebotCLI {
|
|||||||
if (!args[1]) {
|
if (!args[1]) {
|
||||||
const repos = this.bot.repositoryManager.getAll();
|
const repos = this.bot.repositoryManager.getAll();
|
||||||
for (const repo of repos) {
|
for (const repo of repos) {
|
||||||
this.checkUpdate(repo);
|
await this.checkUpdate(repo);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const repo = this.bot.repositoryManager.getRepoByName(args[1]);
|
for (const namep of args.slice(1)) {
|
||||||
|
const repo = this.bot.repositoryManager.getRepoByName(namep);
|
||||||
if (!repo) {
|
if (!repo) {
|
||||||
logger.error('No such repository found.');
|
logger.error('No such repository "%s" found.', namep);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkUpdate(repo);
|
await this.checkUpdate(repo);
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.log(help);
|
logger.log(help);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private pluginCommand(...args: any[]): void {
|
private async pluginCommand(...args: any[]): Promise<void> {
|
||||||
const help = 'plugin install | update | uninstall | enable | disable | start | stop | list | running [<name>]';
|
const help = 'plugin install | update | uninstall | enable | disable | start | stop | list | running [<name>]';
|
||||||
if (!args[0] || args[0] === 'help' || (!args[1] && args[0] !== 'list' && args[0] !== 'running')) {
|
if (!args[0] || args[0] === 'help' || (!args[1] && args[0] !== 'list' && args[0] !== 'running')) {
|
||||||
logger.log(help);
|
logger.log(help);
|
||||||
@ -87,17 +90,18 @@ export class SqueebotCLI {
|
|||||||
case 'u':
|
case 'u':
|
||||||
case 'install':
|
case 'install':
|
||||||
case 'update':
|
case 'update':
|
||||||
this.bot.repositoryManager.installPlugin(args[1]).then((mf) => {
|
for (const name of args.slice(1)) {
|
||||||
|
const mf = await this.bot.repositoryManager.installPlugin(name);
|
||||||
logger.log('Installed plugin %s version %s!', mf.name, mf.version);
|
logger.log('Installed plugin %s version %s!', mf.name, mf.version);
|
||||||
}, (e) => console.error(e.message));
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'uninst':
|
case 'uninst':
|
||||||
case 'remove':
|
case 'remove':
|
||||||
case 'uninstall':
|
case 'uninstall':
|
||||||
this.bot.repositoryManager.uninstallPlugin(args[1]).then(() => {
|
for (const name of args.slice(1)) {
|
||||||
logger.log('Uninstalled plugin %s.', args[1]);
|
await this.bot.repositoryManager.uninstallPlugin(name)
|
||||||
}, (e) => console.error(e.message));
|
logger.log('Uninstalled plugin %s.', name);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'list':
|
case 'list':
|
||||||
logger.log('Installed plugins:',
|
logger.log('Installed plugins:',
|
||||||
@ -111,73 +115,79 @@ export class SqueebotCLI {
|
|||||||
case 'run':
|
case 'run':
|
||||||
case 'load':
|
case 'load':
|
||||||
case 'start':
|
case 'start':
|
||||||
const plugin = this.bot.pluginManager.getAvailableByName(args[1]);
|
for (const name of args.slice(1)) {
|
||||||
|
const plugin = this.bot.pluginManager.getAvailableByName(name);
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
logger.error('No such plugin is available. Maybe try installing it? plugin install', args[1]);
|
logger.error('"%s" is not available. Maybe try installing it? plugin install', name, name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bot.pluginManager.load(plugin).then((p) => {
|
await this.bot.pluginManager.load(plugin);
|
||||||
logger.log('Started plugin "%s" successfully.', args[1]);
|
logger.log('Started plugin "%s" successfully.', name);
|
||||||
}, (e) => logger.error(e.stack));
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'stop':
|
case 'stop':
|
||||||
case 'kill':
|
case 'kill':
|
||||||
if (!this.bot.pluginManager.getAvailableByName(args[1])) {
|
for (const name of args.slice(1)) {
|
||||||
|
if (!this.bot.pluginManager.getAvailableByName(name)) {
|
||||||
logger.error('No such plugin is available.');
|
logger.error('No such plugin is available.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log('Stopping plugin', args[1]);
|
logger.log('Stopping plugin', name);
|
||||||
|
|
||||||
this.bot.stream.emitTo(args[1], 'pluginUnload', args[1]);
|
this.bot.stream.emitTo(name, 'pluginUnload', name);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'enable':
|
case 'enable':
|
||||||
if (!this.bot.pluginManager.getAvailableByName(args[1])) {
|
for (const name of args.slice(1)) {
|
||||||
logger.error('No such plugin is available.');
|
if (!this.bot.pluginManager.getAvailableByName(name)) {
|
||||||
|
logger.error('No such plugin "%s" is available.', name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log('Enabling plugin', args[1]);
|
logger.log('Enabling plugin', name);
|
||||||
|
|
||||||
if (!this.bot.config.config.enabled) {
|
if (!this.bot.config.config.enabled) {
|
||||||
this.bot.config.config.enabled = [args[1]];
|
this.bot.config.config.enabled = [name];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.bot.config.config.enabled.indexOf(args[1]) === -1) {
|
if (this.bot.config.config.enabled.indexOf(name) === -1) {
|
||||||
this.bot.config.config.enabled.push(args[1]);
|
this.bot.config.config.enabled.push(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bot.config.save();
|
await this.bot.config.save();
|
||||||
break;
|
break;
|
||||||
case 'disable':
|
case 'disable':
|
||||||
if (!this.bot.pluginManager.getAvailableByName(args[1])) {
|
for (const name of args.slice(1)) {
|
||||||
logger.error('No such plugin is available.');
|
if (!this.bot.pluginManager.getAvailableByName(name)) {
|
||||||
|
logger.error('No such plugin "%s" is available.', name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log('Disabling plugin', args[1]);
|
logger.log('Disabling plugin', name);
|
||||||
|
|
||||||
if (!this.bot.config.config.enabled) {
|
if (!this.bot.config.config.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const indx = this.bot.config.config.enabled.indexOf(args[1]);
|
const indx = this.bot.config.config.enabled.indexOf(name);
|
||||||
if (indx > -1) {
|
if (indx > -1) {
|
||||||
this.bot.config.config.enabled.splice(indx, 1);
|
this.bot.config.config.enabled.splice(indx, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.bot.config.save();
|
await this.bot.config.save();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.log(help);
|
logger.log(help);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private channelCommand(...args: any[]): void {
|
private async channelCommand(...args: any[]): Promise<void> {
|
||||||
const help = 'channel new | del | addplugin | delplugin [<name>] [<plugin>]';
|
const help = 'channel new | del | list | addplugin | delplugin [<name>] [<plugin>]';
|
||||||
if (!args[0] || args[0] === 'help' || (!args[1] && args[0] !== 'list')) {
|
if (!args[0] || args[0] === 'help' || (!args[1] && args[0] !== 'list')) {
|
||||||
logger.log(help);
|
logger.log(help);
|
||||||
return;
|
return;
|
||||||
@ -201,15 +211,17 @@ export class SqueebotCLI {
|
|||||||
case 'del':
|
case 'del':
|
||||||
case 'delete':
|
case 'delete':
|
||||||
case 'remove':
|
case 'remove':
|
||||||
const chan = this.bot.channelManager.getChannelByName(args[1]);
|
for (const name of args.slice(1)) {
|
||||||
|
const chan = this.bot.channelManager.getChannelByName(name);
|
||||||
if (!chan) {
|
if (!chan) {
|
||||||
logger.error('No such channel exists!');
|
logger.error('No such channel "%s" exists!', name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bot.channelManager.removeChannel(chan);
|
this.bot.channelManager.removeChannel(chan);
|
||||||
|
|
||||||
logger.log('Channel removed!');
|
logger.log('Channel "%s" removed!', name);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'addp':
|
case 'addp':
|
||||||
case 'addplugin':
|
case 'addplugin':
|
||||||
@ -224,11 +236,18 @@ export class SqueebotCLI {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan1.plugins.indexOf(args[2]) !== -1) {
|
for (const name of args.slice(2)) {
|
||||||
chan1.plugins.push(args[2]);
|
if (chan1.plugins.indexOf(name) === -1) {
|
||||||
|
chan1.plugins.push(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log('Plugin added to channel!');
|
logger.log('Plugin "%s" added to channel!', name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'list':
|
||||||
|
logger.log('Channels:\n', this.bot.channelManager.getAll().map((chan) => {
|
||||||
|
return ` => ${chan.name}: ${chan.plugins.join(', ')} (${chan.enabled ? 'enabled' : 'disabled'})`;
|
||||||
|
}).join('\n'));
|
||||||
break;
|
break;
|
||||||
case 'remp':
|
case 'remp':
|
||||||
case 'delp':
|
case 'delp':
|
||||||
@ -245,37 +264,43 @@ export class SqueebotCLI {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const name of args.slice(2)) {
|
||||||
const idx = chan2.plugins.indexOf(args[2]);
|
const idx = chan2.plugins.indexOf(args[2]);
|
||||||
if (idx !== -1) {
|
if (idx !== -1) {
|
||||||
chan2.plugins.splice(idx, 1);
|
chan2.plugins.splice(idx, 1);
|
||||||
}
|
}
|
||||||
|
logger.log('Plugin "%s" added to channel!', name);
|
||||||
|
}
|
||||||
|
|
||||||
logger.log('Plugin added to channel!');
|
|
||||||
break;
|
break;
|
||||||
case 'enable':
|
case 'enable':
|
||||||
const chan3 = this.bot.channelManager.getChannelByName(args[1]);
|
for (const name of args.slice(1)) {
|
||||||
if (!chan3) {
|
const chan = this.bot.channelManager.getChannelByName(name);
|
||||||
logger.error('No such channel exists!');
|
if (!chan) {
|
||||||
|
logger.error('No such channel "%s" exists!', name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
chan3.enabled = true;
|
chan.enabled = true;
|
||||||
logger.log('Channel enabled!');
|
logger.log('Channel "%s" enabled!', name);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'disable':
|
case 'disable':
|
||||||
const chan4 = this.bot.channelManager.getChannelByName(args[1]);
|
for (const name of args.slice(1)) {
|
||||||
if (!chan4) {
|
const chan = this.bot.channelManager.getChannelByName(name);
|
||||||
logger.error('No such channel exists!');
|
if (!chan) {
|
||||||
|
logger.error('No such channel "%s" exists!', name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
chan4.enabled = false;
|
chan.enabled = false;
|
||||||
logger.log('Channel disabled!');
|
logger.log('Channel "%s" disabled!', name);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bot.config.config.channels = this.bot.channelManager.getAll();
|
this.bot.config.config.channels = this.bot.channelManager.getAll();
|
||||||
this.bot.config.save();
|
await this.bot.config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public attach(rl: ReadLine) {
|
public attach(rl: ReadLine) {
|
||||||
@ -290,17 +315,20 @@ export class SqueebotCLI {
|
|||||||
case 'r':
|
case 'r':
|
||||||
case 'repo':
|
case 'repo':
|
||||||
case 'repository':
|
case 'repository':
|
||||||
this.repositoryCommand(...split.slice(1));
|
this.repositoryCommand(...split.slice(1)).catch(
|
||||||
|
e => logger.error(e.message));
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
case 'pl':
|
case 'pl':
|
||||||
case 'plugin':
|
case 'plugin':
|
||||||
this.pluginCommand(...split.slice(1));
|
this.pluginCommand(...split.slice(1)).catch(
|
||||||
|
e => logger.error(e.message));
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
case 'chan':
|
case 'chan':
|
||||||
case 'channel':
|
case 'channel':
|
||||||
this.channelCommand(...split.slice(1));
|
this.channelCommand(...split.slice(1)).catch(
|
||||||
|
e => logger.error(e.message));
|
||||||
break;
|
break;
|
||||||
case 'stop':
|
case 'stop':
|
||||||
case 'exit':
|
case 'exit':
|
||||||
@ -309,6 +337,6 @@ export class SqueebotCLI {
|
|||||||
this.bot.shutdown();
|
this.bot.shutdown();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,6 +26,7 @@ const tsConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const gitignore = `/node_modules/
|
const gitignore = `/node_modules/
|
||||||
|
/.out/
|
||||||
deployment.json`;
|
deployment.json`;
|
||||||
|
|
||||||
function dummyEnvironment(location: string): IEnvironment {
|
function dummyEnvironment(location: string): IEnvironment {
|
||||||
@ -108,6 +109,7 @@ async function newRepository(
|
|||||||
await fs.writeJson(path.join(location, 'tsconfig.json'), tsConfig);
|
await fs.writeJson(path.join(location, 'tsconfig.json'), tsConfig);
|
||||||
gitIgnore += '\n*.js';
|
gitIgnore += '\n*.js';
|
||||||
gitIgnore += '\n*.d.ts';
|
gitIgnore += '\n*.d.ts';
|
||||||
|
gitIgnore += '\n*.tsbuildinfo';
|
||||||
|
|
||||||
console.log('Adding TypeScript scripts to package.json');
|
console.log('Adding TypeScript scripts to package.json');
|
||||||
const pkgjson = path.join(location, 'package.json');
|
const pkgjson = path.join(location, 'package.json');
|
||||||
|
Loading…
Reference in New Issue
Block a user