mirror of
https://github.com/unraid/api.git
synced 2026-01-02 06:30:02 -06:00
Compare commits
41 Commits
feat/loggi
...
v2.27.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b337dc286 | ||
|
|
2cb783f597 | ||
|
|
8bf89236cd | ||
|
|
9b3266a812 | ||
|
|
76115dee0b | ||
|
|
f6ea20a7c0 | ||
|
|
120fdbc33f | ||
|
|
31e1dd121a | ||
|
|
a192605d5c | ||
|
|
803f7cb9e8 | ||
|
|
d227905999 | ||
|
|
9b95cfc543 | ||
|
|
aad1595105 | ||
|
|
66c4ad0e03 | ||
|
|
9012891d26 | ||
|
|
c162b3d3b9 | ||
|
|
2bbfc6de62 | ||
|
|
0d4cd20ba3 | ||
|
|
0798f9a659 | ||
|
|
471c554a04 | ||
|
|
f21d54b533 | ||
|
|
c092890544 | ||
|
|
5077563acc | ||
|
|
2de938acd2 | ||
|
|
e9e0ebb63d | ||
|
|
63d7cafdc4 | ||
|
|
5b29bbbf69 | ||
|
|
1592f45da4 | ||
|
|
c41f708b94 | ||
|
|
60b4665dcc | ||
|
|
5a46501334 | ||
|
|
76389ea8af | ||
|
|
5ed2d619f6 | ||
|
|
0984477cc6 | ||
|
|
c061aeb9f2 | ||
|
|
467f74cd52 | ||
|
|
526efe6cae | ||
|
|
42051849d7 | ||
|
|
7d24bd24c5 | ||
|
|
5d40bd624f | ||
|
|
bcdb044cc9 |
28
.github/workflows/main.yml
vendored
28
.github/workflows/main.yml
vendored
@@ -133,6 +133,14 @@ jobs:
|
||||
- name: Clean node_modules
|
||||
run: npm run clean && curl -sf https://gobinaries.com/tj/node-prune | sh && node-prune
|
||||
|
||||
- name: Add commit hash to version
|
||||
if: startsWith(github.ref, 'refs/tags/v') == false
|
||||
run: |
|
||||
VERSION=$(jq -r .version package.json) && \
|
||||
SHORT_HASH=$(echo $GITHUB_SHA | cut -c 1-7) && \
|
||||
jq --arg version $VERSION-$SHORT_HASH '.version = $version' package.json > out.json && mv out.json package.json && \
|
||||
echo '✔ Version field updated'
|
||||
|
||||
- name: Pack source
|
||||
run: npm pack
|
||||
|
||||
@@ -172,6 +180,18 @@ jobs:
|
||||
with:
|
||||
name: unraid-api-source
|
||||
|
||||
- name: Pre-download node for nexe
|
||||
shell: bash
|
||||
run: mkdir -p /home/runner/.nexe && wget -O /home/runner/.nexe/linux-x64-14.15.3 -c https://github.com/nexe/nexe/releases/download/v3.3.3/linux-x64-14.15.3 && chmod +x /home/runner/.nexe/linux-x64-14.15.3
|
||||
|
||||
- name: Install upx
|
||||
shell: bash
|
||||
run: sudo apt-get install upx
|
||||
|
||||
- name: Reduce size of nexe node
|
||||
shell: bash
|
||||
run: upx /home/runner/.nexe/linux-x64-14.15.3
|
||||
|
||||
- name: Unpack unraid-api source tgz
|
||||
shell: bash
|
||||
run: tar xvzf ./unraid-api-*.tgz --strip 1 && rm ./unraid-api-*.tgz
|
||||
@@ -179,14 +199,6 @@ jobs:
|
||||
- name: Install nexe
|
||||
run: npm i -g nexe
|
||||
|
||||
- name: Add commit hash to version
|
||||
if: startsWith(github.ref, 'refs/tags/v') == false
|
||||
run: |
|
||||
VERSION=$(jq -r .version package.json) && \
|
||||
SHORT_HASH=$(echo $GITHUB_SHA | cut -c 1-7) && \
|
||||
jq --arg version $VERSION-$SHORT_HASH '.version = $version' package.json > out.json && mv out.json package.json && \
|
||||
echo '✔ Version field updated'
|
||||
|
||||
- name: Build binary
|
||||
run: npm run build-binary
|
||||
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -69,3 +69,6 @@ typescript
|
||||
|
||||
# Github actions
|
||||
RELEASE_NOTES.md
|
||||
|
||||
# Binary files
|
||||
bin
|
||||
33
CHANGELOG.md
33
CHANGELOG.md
@@ -2,6 +2,39 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
### [2.27.1](https://github.com/unraid/api/compare/v2.27.0...v2.27.1) (2021-10-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add no-daemon to args list ([f6ea20a](https://github.com/unraid/api/commit/f6ea20a7c0e1d6c622b1107c7855889d5da350f6))
|
||||
* allow skipping daemonization ([120fdbc](https://github.com/unraid/api/commit/120fdbc33f17784524fc92e995f50ae5ecb81824))
|
||||
* move config from vars.configValid/configError to config.valid/error ([8bf8923](https://github.com/unraid/api/commit/8bf89236cdd163959f551d0bdaf9a15fd93cc2ca))
|
||||
* when getting an unknown status code wait 60s before reconnecting instead of 0s ([9b3266a](https://github.com/unraid/api/commit/9b3266a81259bf7928831b5beb424350a29a78e2))
|
||||
|
||||
## [2.27.0](https://github.com/unraid/api/compare/v2.26.14...v2.27.0) (2021-09-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add 2fa support ([5d40bd6](https://github.com/unraid/api/commit/5d40bd624f1b3df4b1d6c0ae712cf31e740f089d))
|
||||
* add supervisor ([4205184](https://github.com/unraid/api/commit/42051849d7985326cbb33157c9afdb2c94cc7d27))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow TRAIL to be a registrationType ([bcdb044](https://github.com/unraid/api/commit/bcdb044cc9b8c6eb5d1a93fc72ba002fbe5477a5))
|
||||
* binary building ([c41f708](https://github.com/unraid/api/commit/c41f708b94df51d51946c3378c0d5b3b958b6fe4))
|
||||
* code->token and increase 2FA length to 64 chars ([7d24bd2](https://github.com/unraid/api/commit/7d24bd24c505da8a3e3ebe82d3e7933758b028c5))
|
||||
* ensure bin directory exists ([c061aeb](https://github.com/unraid/api/commit/c061aeb9f26828468baa03705599133718dc04d7))
|
||||
* ensure nexe uses correct entry ([9012891](https://github.com/unraid/api/commit/9012891d262dfbe4867b1baefb7fcf13b43d37bb))
|
||||
* ensure we always kill orphaned unraid-api processes ([9b95cfc](https://github.com/unraid/api/commit/9b95cfc543c516a2664cc10d8878d10bcff31e31))
|
||||
* ensure we get the correct path ([526efe6](https://github.com/unraid/api/commit/526efe6caefaa1ba4e7d421ac8b30325f3582e1f))
|
||||
* include .graphql files in bundle ([c162b3d](https://github.com/unraid/api/commit/c162b3d3b994c82aa917dc649cc5ba338f6e8520))
|
||||
* kill all old processes before starting ([a192605](https://github.com/unraid/api/commit/a192605d5ca1c0b2b001265f999bc6bcea293561))
|
||||
* modclean being run twice ([1592f45](https://github.com/unraid/api/commit/1592f45da43ceaaab1a819ad1eb7512d68fde1b5))
|
||||
* use new bin directory for OS ([5ed2d61](https://github.com/unraid/api/commit/5ed2d619f68ec47191476d9c4095133aef544904))
|
||||
|
||||
### [2.26.14](https://github.com/unraid/api/compare/v2.26.13...v2.26.14) (2021-09-22)
|
||||
|
||||
|
||||
|
||||
10
app/cli.ts
10
app/cli.ts
@@ -25,6 +25,7 @@ interface Flags {
|
||||
command?: string;
|
||||
help?: boolean;
|
||||
debug?: boolean;
|
||||
'no-daemon'?: boolean;
|
||||
port?: string;
|
||||
'log-level'?: string;
|
||||
'log-transport'?: string;
|
||||
@@ -35,7 +36,8 @@ interface Flags {
|
||||
const args: ArgumentConfig<Flags> = {
|
||||
command: { type: String, defaultOption: true, optional: true },
|
||||
help: { type: Boolean, optional: true, alias: 'h', description: 'Prints this usage guide.' },
|
||||
debug: { type: Boolean, optional: true, alias: 'd', description: 'Enabled debug mode.' },
|
||||
debug: { type: Boolean, optional: true, alias: 'd', description: 'Enable debug mode.' },
|
||||
'no-daemon': { type: Boolean, optional: true, description: 'Prevent process being daemonized.' },
|
||||
port: { type: String, optional: true, alias: 'p', description: 'Set the graphql port.' },
|
||||
environment: { type: String, typeLabel: '{underline production/staging/development}', optional: true, description: 'Set the working environment.' },
|
||||
'log-level': { type: (level?: string) => {
|
||||
@@ -136,6 +138,12 @@ const commands = {
|
||||
const indexPath = './index.js';
|
||||
require(indexPath);
|
||||
|
||||
// Skip daemonizing
|
||||
if (mainOptions['no-daemon']) {
|
||||
console.info('Skipping daemonizing process.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mainOptions.debug) {
|
||||
if ('_DAEMONIZE_PROCESS' in process.env) {
|
||||
// In the child, clean up the tracking environment variable
|
||||
|
||||
@@ -8,6 +8,7 @@ export const admin = {
|
||||
{ resource: 'apikey', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'array', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'cpu', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'config', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'crash-reporting-enabled', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'device', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'device/unassigned', action: 'read:any', attributes: '*' },
|
||||
@@ -57,6 +58,7 @@ export const upc = {
|
||||
extends: 'guest',
|
||||
permissions: [
|
||||
{ resource: 'apikey', action: 'read:own', attributes: '*' },
|
||||
{ resource: 'config', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'permission', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'registration', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'owner', action: 'read:any', attributes: '*' },
|
||||
@@ -74,6 +76,7 @@ export const my_servers = {
|
||||
extends: 'guest',
|
||||
permissions: [
|
||||
{ resource: 'array', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'config', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'display', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'docker/container', action: 'read:any', attributes: '*' },
|
||||
{ resource: 'docker/network', action: 'read:any', attributes: '*' },
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { ensurePermission } from '../../utils';
|
||||
import { CoreContext, CoreResult } from '../../types';
|
||||
import packageJson from '../../../../package.json';
|
||||
import { version } from '../../../../package.json';
|
||||
|
||||
interface Result extends CoreResult {
|
||||
json: {
|
||||
@@ -45,7 +45,7 @@ export const getUnraidApiService = async (context: CoreContext): Promise<Result>
|
||||
timestamp: uptimeTimestamp,
|
||||
seconds: uptimeSeconds
|
||||
},
|
||||
version: packageJson.version
|
||||
version
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
import path from 'path';
|
||||
import { paths } from '../paths';
|
||||
import { ConfigErrorState, Var } from '../types/states';
|
||||
import { Var } from '../types/states';
|
||||
import { IniStringBooleanOrAuto, IniStringBoolean } from '../types/ini';
|
||||
import { State } from './state';
|
||||
import { toNumber } from '../utils/casting';
|
||||
import { parseConfig } from '../utils/misc';
|
||||
|
||||
const iniBooleanToJsBoolean = (value: IniStringBoolean | string, defaultValue?: any) => {
|
||||
export const iniBooleanToJsBoolean = (value: IniStringBoolean | string, defaultValue?: any) => {
|
||||
if (value === 'no') {
|
||||
return false;
|
||||
}
|
||||
@@ -27,7 +27,7 @@ const iniBooleanToJsBoolean = (value: IniStringBoolean | string, defaultValue?:
|
||||
throw new Error(`Value "${value}" is not no/yes.`);
|
||||
};
|
||||
|
||||
const iniBooleanOrAutoToJsBoolean = (value: IniStringBooleanOrAuto | string) => {
|
||||
export const iniBooleanOrAutoToJsBoolean = (value: IniStringBooleanOrAuto | string) => {
|
||||
try {
|
||||
// Either it'll return true/false or throw
|
||||
return iniBooleanToJsBoolean((value as IniStringBoolean));
|
||||
@@ -95,6 +95,7 @@ interface VarIni {
|
||||
cacheSbNumDisks: string;
|
||||
comment: string;
|
||||
configValid: string;
|
||||
configState: string;
|
||||
csrfToken: string;
|
||||
defaultFormat: string;
|
||||
defaultFsType: string;
|
||||
@@ -233,12 +234,7 @@ const parse = (state: VarIni): Var => {
|
||||
cacheNumDevices: toNumber(state.cacheNumDevices),
|
||||
cacheSbNumDisks: toNumber(state.cacheSbNumDisks),
|
||||
configValid,
|
||||
configError: configValid === false ? (({
|
||||
error: 'UNKNOWN_ERROR',
|
||||
invalid: 'INVALID',
|
||||
nokeyserver: 'NO_KEY_SERVER',
|
||||
withdrawn: 'WITHDRAWN'
|
||||
}[state.configValid] ?? 'UNKNOWN_ERROR') as ConfigErrorState) : undefined,
|
||||
configState: state.configValid,
|
||||
deviceCount: toNumber(state.deviceCount),
|
||||
fsCopyPrcnt: toNumber(state.fsCopyPrcnt),
|
||||
fsNumMounted: toNumber(state.fsNumMounted),
|
||||
|
||||
@@ -3,17 +3,9 @@
|
||||
* Written by: Alexis Tyler
|
||||
*/
|
||||
|
||||
// @todo: remove string and add rest of the options
|
||||
type FsType = 'xfs' | string;
|
||||
type RegistrationCheck = 'Error' | 'Valid';
|
||||
type RegistrationType = 'INVALID' | 'TRIAL' | 'BASIC' | 'PLUS' | 'PRO' | string;
|
||||
|
||||
export type ConfigErrorState =
|
||||
'UNKNOWN_ERROR' |
|
||||
'INVALID' |
|
||||
'NO_KEY_SERVER' |
|
||||
'WITHDRAWN';
|
||||
|
||||
/**
|
||||
* Global vars
|
||||
*/
|
||||
@@ -25,8 +17,8 @@ export interface Var {
|
||||
comment: string;
|
||||
/** Is the array's config valid. */
|
||||
configValid: boolean;
|
||||
/** If the array's config isn't valid this is the reason. */
|
||||
configError?: ConfigErrorState;
|
||||
/** @internal used to hold the value for config.error */
|
||||
configState: string;
|
||||
/** Current CSRF token for HTTP requests with emhttpd. */
|
||||
csrfToken: string;
|
||||
defaultFormat: string;
|
||||
|
||||
@@ -19,7 +19,7 @@ import * as resolvers from './resolvers';
|
||||
import { wsHasConnected, wsHasDisconnected } from '../ws';
|
||||
import { MOTHERSHIP_RELAY_WS_LINK } from '../consts';
|
||||
import { isNodeError } from '../core/utils';
|
||||
import { User } from '../core/types';
|
||||
import { User, Var } from '../core/types';
|
||||
|
||||
const internalServiceUser: User = { id: '-1', description: 'Internal service account', name: 'internal', role: 'admin', password: false };
|
||||
|
||||
@@ -354,29 +354,44 @@ bus.on('slots', async () => {
|
||||
});
|
||||
});
|
||||
|
||||
let hostname: string;
|
||||
const localCache: {
|
||||
hostname?: string;
|
||||
} = {};
|
||||
|
||||
// Update info/hostname when hostname changes
|
||||
bus.on('var', async data => {
|
||||
bus.on('var', async (data: { var: { node: Var } }) => {
|
||||
// Publish var changes
|
||||
await pubsub.publish('vars', {
|
||||
vars: data.var.node
|
||||
});
|
||||
|
||||
// Hostname changed
|
||||
if (hostname !== data.var.node.name) {
|
||||
if (localCache.hostname !== data.var.node.name) {
|
||||
// Update cache
|
||||
hostname = data.var.node.name;
|
||||
localCache.hostname = data.var.node.name;
|
||||
|
||||
// Publish new hostname
|
||||
await pubsub.publish('info', {
|
||||
info: {
|
||||
os: {
|
||||
hostname
|
||||
hostname: localCache.hostname
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Config
|
||||
await pubsub.publish('config', {
|
||||
config: {
|
||||
valid: data.var.node.configValid,
|
||||
error: data.var.node.configValid ? undefined : ({
|
||||
error: 'UNKNOWN_ERROR',
|
||||
invalid: 'INVALID',
|
||||
nokeyserver: 'NO_KEY_SERVER',
|
||||
withdrawn: 'WITHDRAWN'
|
||||
}[data.var.node.configState] ?? 'UNKNOWN_ERROR')
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// On Docker event update info with { apps: { installed, started } }
|
||||
|
||||
26
app/graphql/resolvers/query/config.ts
Normal file
26
app/graphql/resolvers/query/config.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* Copyright 2021 Lime Technology Inc. All rights reserved.
|
||||
* Written by: Alexis Tyler
|
||||
*/
|
||||
|
||||
import { varState } from '../../../core/states';
|
||||
import { ensurePermission } from '../../../core/utils';
|
||||
import { Context } from '../../schema/utils';
|
||||
|
||||
export default async (_: unknown, __: unknown, context: Context) => {
|
||||
ensurePermission(context.user, {
|
||||
resource: 'config',
|
||||
action: 'read',
|
||||
possession: 'any'
|
||||
});
|
||||
|
||||
return {
|
||||
valid: varState.data.configValid,
|
||||
error: varState.data.configValid ? undefined : ({
|
||||
error: 'UNKNOWN_ERROR',
|
||||
invalid: 'INVALID',
|
||||
nokeyserver: 'NO_KEY_SERVER',
|
||||
withdrawn: 'WITHDRAWN'
|
||||
}[varState.data.configState] ?? 'UNKNOWN_ERROR')
|
||||
};
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright 2019-2020 Lime Technology Inc. All rights reserved.
|
||||
* Written by: Alexis Tyler
|
||||
*/
|
||||
import config from './config';
|
||||
import crashReportingEnabled from './crash-reporting-enabled';
|
||||
import display from './display';
|
||||
import disks from './disks';
|
||||
@@ -15,6 +16,7 @@ import servers from './servers';
|
||||
import vms from './vms';
|
||||
|
||||
export const Query = {
|
||||
config,
|
||||
crashReportingEnabled,
|
||||
disks,
|
||||
display,
|
||||
|
||||
@@ -10,6 +10,7 @@ const files = [
|
||||
'./dist/types/graphql/schema/types/apikeys/apikey.graphql',
|
||||
'./dist/types/graphql/schema/types/array/array.graphql',
|
||||
'./dist/types/graphql/schema/types/array/parity.graphql',
|
||||
'./dist/types/graphql/schema/types/config/config.graphql',
|
||||
'./dist/types/graphql/schema/types/crash-reporting-enabled/crash-reporting-enabled.graphql',
|
||||
'./dist/types/graphql/schema/types/devices/device.graphql',
|
||||
'./dist/types/graphql/schema/types/disks/disk.graphql',
|
||||
|
||||
19
app/graphql/schema/types/config/config.graphql
Normal file
19
app/graphql/schema/types/config/config.graphql
Normal file
@@ -0,0 +1,19 @@
|
||||
enum ConfigErrorState {
|
||||
UNKNOWN_ERROR
|
||||
INVALID
|
||||
NO_KEY_SERVER
|
||||
WITHDRAWN
|
||||
}
|
||||
|
||||
type Config {
|
||||
valid: boolean;
|
||||
error: ConfigErrorState;
|
||||
}
|
||||
|
||||
type Query {
|
||||
config: Config!
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
config: Config!
|
||||
}
|
||||
@@ -6,13 +6,6 @@ type Subscription {
|
||||
vars: Vars!
|
||||
}
|
||||
|
||||
enum ConfigErrorState {
|
||||
UNKNOWN_ERROR
|
||||
INVALID
|
||||
NO_KEY_SERVER
|
||||
WITHDRAWN
|
||||
}
|
||||
|
||||
type Vars {
|
||||
"""Unraid version"""
|
||||
version: String
|
||||
@@ -109,8 +102,6 @@ type Vars {
|
||||
shareAvahiAfpModel: String
|
||||
safeMode: Boolean
|
||||
startMode: String
|
||||
configValid: Boolean
|
||||
configError: ConfigErrorState
|
||||
joinStatus: String
|
||||
deviceCount: Int
|
||||
flashGuid: String
|
||||
@@ -182,14 +173,16 @@ enum mdState {
|
||||
}
|
||||
|
||||
enum registrationType {
|
||||
"""Invalid"""
|
||||
INVALID
|
||||
"""Trial"""
|
||||
TRIAL
|
||||
"""Basic"""
|
||||
BASIC
|
||||
"""Plus"""
|
||||
PLUS
|
||||
"""Pro"""
|
||||
PRO
|
||||
"""Invalid"""
|
||||
INVALID
|
||||
}
|
||||
|
||||
enum registrationState {
|
||||
|
||||
@@ -13,9 +13,7 @@ import { server } from './server';
|
||||
import { mothership } from './mothership/subscribe-to-servers';
|
||||
import { startInternal, sockets } from './mothership';
|
||||
import { sleep } from './core/utils';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { version } = require('../package.json') as { version: string };
|
||||
import { version } from '../package.json';
|
||||
|
||||
// Send errors to server if enabled
|
||||
Sentry.init({
|
||||
|
||||
@@ -5,7 +5,7 @@ import { INTERNAL_WS_LINK, MOTHERSHIP_RELAY_WS_LINK } from '../consts';
|
||||
import { apiManager } from '../core/api-manager';
|
||||
import { log } from '../core/log';
|
||||
import { varState } from '../core/states/var';
|
||||
import packageJson from '../../package.json';
|
||||
import { version } from '../../package.json';
|
||||
import { paths } from '../core/paths';
|
||||
import { loadState } from '../core/utils/misc/load-state';
|
||||
import { subscribeToServers } from './subscribe-to-servers';
|
||||
@@ -16,17 +16,9 @@ export const sockets = {
|
||||
internal: null as GracefulWebSocket | null,
|
||||
relay: null as GracefulWebSocket | null
|
||||
};
|
||||
let isLocalConnecting = false;
|
||||
let isRelayConnecting = false;
|
||||
|
||||
export const startInternal = (apiKey: string) => {
|
||||
// Another process has already kicked this off
|
||||
if (isLocalConnecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the connection
|
||||
isLocalConnecting = true;
|
||||
log.debug('⌨️ INTERNAL:CONNECTING');
|
||||
sockets.internal = new GracefulWebSocket(INTERNAL_WS_LINK, ['graphql-ws'], {
|
||||
headers: {
|
||||
@@ -36,7 +28,6 @@ export const startInternal = (apiKey: string) => {
|
||||
|
||||
sockets.internal.on('connected', () => {
|
||||
log.debug('⌨️ INTERNAL:CONNECTED');
|
||||
isLocalConnecting = false;
|
||||
sockets.internal?.send(JSON.stringify({
|
||||
type: 'connection_init',
|
||||
payload: {
|
||||
@@ -67,11 +58,9 @@ export const startInternal = (apiKey: string) => {
|
||||
|
||||
sockets.internal.on('disconnected', () => {
|
||||
log.debug('⌨️ INTERNAL:DISCONNECTED');
|
||||
isLocalConnecting = false;
|
||||
});
|
||||
|
||||
sockets.internal.on('killed', () => {
|
||||
isLocalConnecting = false;
|
||||
log.debug('☁️ INTERNAL:KILLED');
|
||||
});
|
||||
|
||||
@@ -105,7 +94,7 @@ const getRelayHeaders = () => {
|
||||
'x-api-key': apiKey,
|
||||
'x-flash-guid': varState.data?.flashGuid ?? '',
|
||||
'x-server-name': serverName,
|
||||
'x-unraid-api-version': packageJson.version
|
||||
'x-unraid-api-version': version
|
||||
};
|
||||
};
|
||||
|
||||
@@ -119,13 +108,6 @@ const serializer = new IniSerializer({
|
||||
});
|
||||
|
||||
export const startRelay = () => {
|
||||
// Another process has already kicked this off
|
||||
if (isRelayConnecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the connection
|
||||
isRelayConnecting = true;
|
||||
log.debug('☁️ RELAY:CONNECTING');
|
||||
sockets.relay = new GracefulWebSocket(MOTHERSHIP_RELAY_WS_LINK, ['graphql-ws'], {
|
||||
headers: getRelayHeaders()
|
||||
@@ -133,19 +115,16 @@ export const startRelay = () => {
|
||||
|
||||
// Connection-state related events
|
||||
sockets.relay.on('connected', () => {
|
||||
isRelayConnecting = false;
|
||||
log.debug('☁️ RELAY:CONNECTED');
|
||||
});
|
||||
|
||||
sockets.relay.on('disconnected', () => {
|
||||
log.debug('☁️ RELAY:DISCONNECTED');
|
||||
isRelayConnecting = false;
|
||||
sockets.internal?.close();
|
||||
sockets.internal?.start();
|
||||
});
|
||||
|
||||
sockets.relay.on('killed', () => {
|
||||
isRelayConnecting = false;
|
||||
log.debug('☁️ RELAY:KILLED');
|
||||
});
|
||||
|
||||
@@ -198,7 +177,6 @@ export const startRelay = () => {
|
||||
// Retry in 30s
|
||||
setTimeout(() => {
|
||||
// Restart relay connection
|
||||
isRelayConnecting = true;
|
||||
log.debug(`☁️ RELAY:${message ?? 'API_KEY_IN_USE'}:RECONNECTING:NOW`);
|
||||
sockets.relay?.start();
|
||||
}, 30_000);
|
||||
@@ -211,7 +189,6 @@ export const startRelay = () => {
|
||||
// Retry in 60s
|
||||
setTimeout(() => {
|
||||
// Restart relay connection
|
||||
isRelayConnecting = true;
|
||||
log.debug(`☁️ RELAY:${message ?? 'INTERNAL_SERVER_ERROR'}:RECONNECTING:NOW`);
|
||||
sockets.relay?.start();
|
||||
}, 60_000);
|
||||
@@ -224,7 +201,6 @@ export const startRelay = () => {
|
||||
// Retry in 60s
|
||||
setTimeout(() => {
|
||||
// Restart relay connection
|
||||
isRelayConnecting = true;
|
||||
log.debug(`☁️ RELAY:${message ?? 'GATEWAY_DOWN'}:RECONNECTING:NOW`);
|
||||
sockets.relay?.start();
|
||||
}, 60_000);
|
||||
@@ -232,10 +208,15 @@ export const startRelay = () => {
|
||||
break;
|
||||
|
||||
default:
|
||||
// Restart relay connection
|
||||
isRelayConnecting = true;
|
||||
log.debug(`☁️ RELAY:${code}:${message}:RECONNECTING:NOW`);
|
||||
sockets.relay?.start();
|
||||
log.debug(`☁️ RELAY:${code}:${message ?? 'UNKNOWN_ERROR'}:RECONNECTING:60_000`);
|
||||
|
||||
// Retry in 60s
|
||||
setTimeout(() => {
|
||||
// Restart relay connection
|
||||
log.debug(`☁️ RELAY:${message ?? 'UNKNOWN_ERROR'}:RECONNECTING:NOW`);
|
||||
sockets.relay?.start();
|
||||
}, 60_000);
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import fs from 'fs';
|
||||
import net from 'net';
|
||||
import crypto from 'crypto';
|
||||
import path from 'path';
|
||||
import execa from 'execa';
|
||||
import cors from 'cors';
|
||||
@@ -18,7 +19,7 @@ import { ApolloServer } from 'apollo-server-express';
|
||||
import { log, config, paths, pubsub, coreLogger } from './core';
|
||||
import { getEndpoints, globalErrorHandler, exitApp, cleanStdout, sleep, loadState, attemptReadFileSync, attemptJSONParse } from './core/utils';
|
||||
import { graphql } from './graphql';
|
||||
import packageJson from '../package.json';
|
||||
import { version } from '../package.json';
|
||||
import display from './graphql/resolvers/query/display';
|
||||
import { networkState, varState } from './core/states';
|
||||
|
||||
@@ -140,7 +141,7 @@ app.use(cors({
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug(`📒 Checking "${origin.toLowerCase()}" for CORS access.`);
|
||||
log.trace(`📒 Checking "${origin.toLowerCase()}" for CORS access.`);
|
||||
|
||||
// Only allow known origins
|
||||
if (!allowedOrigins.includes(origin.toLowerCase())) {
|
||||
@@ -149,7 +150,7 @@ app.use(cors({
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug('✔️ Origin check passed, granting CORS!');
|
||||
log.trace('✔️ Origin check passed, granting CORS!');
|
||||
callback(null, true);
|
||||
}
|
||||
}));
|
||||
@@ -159,7 +160,7 @@ app.use(async (_req, res, next) => {
|
||||
// Only get the machine ID on first request
|
||||
// We do this to avoid using async in the main server function
|
||||
if (!app.get('x-unraid-api-version')) {
|
||||
app.set('x-unraid-api-version', packageJson.version);
|
||||
app.set('x-unraid-api-version', version);
|
||||
}
|
||||
|
||||
// Update header with unraid API version
|
||||
@@ -194,6 +195,26 @@ app.get('/', (_, res) => {
|
||||
return res.send(getEndpoints(app));
|
||||
});
|
||||
|
||||
const generateTwoFactorToken = () => crypto.randomBytes(256).toString('hex').substring(0, 64);
|
||||
|
||||
// Either use the env passed in or generate a fresh one on app load
|
||||
let twoFactorToken = process.env.TWO_FACTOR_TOKEN ?? generateTwoFactorToken();
|
||||
app.post('/verify', (req, res) => {
|
||||
// Check token matches existing one
|
||||
if (req.query.token === twoFactorToken) {
|
||||
// Generate a new token
|
||||
twoFactorToken = generateTwoFactorToken();
|
||||
|
||||
// Allow the user to pass
|
||||
res.sendStatus(204);
|
||||
return;
|
||||
}
|
||||
|
||||
// User failed verification
|
||||
res.status(401);
|
||||
res.send('Invalid 2FA token.');
|
||||
});
|
||||
|
||||
// Handle errors by logging them and returning a 500.
|
||||
app.use((error, _, res, __) => {
|
||||
// Don't log CORS errors
|
||||
|
||||
222
app/supervisor.ts
Normal file
222
app/supervisor.ts
Normal file
@@ -0,0 +1,222 @@
|
||||
import { join as joinPath, resolve as resolveToAbsolutePath } from 'path';
|
||||
import { createWriteStream, mkdirSync, existsSync, lstatSync } from 'fs';
|
||||
import { spawn as spawnProcess, ChildProcess } from 'child_process';
|
||||
import locatePath from 'locate-path';
|
||||
import psList from 'ps-list';
|
||||
import { cyan, green, red } from 'nanocolors';
|
||||
import intervalToHuman from 'interval-to-human';
|
||||
import killProcess from 'fkill';
|
||||
import cleanStack from 'clean-stack';
|
||||
|
||||
const createLogger = (namespace: string) => {
|
||||
const ns = namespace.toUpperCase();
|
||||
return {
|
||||
info(message: string, ...args: any[]) {
|
||||
console.info(`${cyan(`[${ns}]`)} ${message}`, ...args);
|
||||
},
|
||||
debug(message: string, ...args: any[]) {
|
||||
if (!isDebug) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.debug(`${green(`[${ns}]`)} ${message}`, ...args);
|
||||
},
|
||||
error(message: string, ...args: any[]) {
|
||||
console.error(`${red(`[${ns}][ERROR]`)} ${message}`, ...args);
|
||||
},
|
||||
print(message: string, ...args: any[]) {
|
||||
console.log(message, ...args);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const isDebug = process.env.DEBUG !== undefined;
|
||||
const appName = 'unraid-api';
|
||||
const logsPath = process.env.API_LOGS_PATH ?? '/var/log/unraid-api/';
|
||||
const maxRestarts = 100;
|
||||
const logger = createLogger('supervisor');
|
||||
|
||||
const isProcessRunning = async (name: string) => {
|
||||
const list = await psList();
|
||||
const runningProcesses = list
|
||||
// Don't return the process that ran this
|
||||
.filter(_process => _process.pid !== process.pid)
|
||||
.filter(process => {
|
||||
return name.startsWith(process.name) || process.name.endsWith(name) || (process.name === 'node' && process.cmd?.split(' ')[1]?.endsWith(name));
|
||||
});
|
||||
|
||||
return {
|
||||
isRunning: runningProcesses.length !== 0,
|
||||
pids: runningProcesses.map(process => process.pid)
|
||||
};
|
||||
};
|
||||
|
||||
const sleep = async (ms: number) => new Promise<void>(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, ms);
|
||||
});
|
||||
|
||||
// Save the child process outside of startApi
|
||||
// This is to allow us to kill it on exit
|
||||
// and/or if the timeout happens when starting it
|
||||
let apiProcess: ChildProcess;
|
||||
|
||||
const killOldProcesses = async (name: string, processName: string) => {
|
||||
const { isRunning, pids } = await isProcessRunning(processName);
|
||||
if (isRunning && pids.length !== 0) {
|
||||
logger.debug('Killing old %s process with pids %s', name, pids);
|
||||
await killProcess(pids);
|
||||
|
||||
// Wait 1s for the old process to die
|
||||
await sleep(1_000);
|
||||
|
||||
// Should be killed by now
|
||||
const isRunning = await isProcessRunning(processName);
|
||||
// If this is still somehow running then we need to bail.
|
||||
// This should only happen if you're running supervisor as a
|
||||
// user with less privileges then the one who started
|
||||
// the unraid-api process we're trying to kill.
|
||||
if (isRunning) {
|
||||
process.exitCode = 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const startApi = async (restarts = 0, shouldRestart = true) => {
|
||||
// Get an absolute path to the API binary
|
||||
const apiPath = resolveToAbsolutePath(process.env.UNRAID_API_BINARY_LOCATION ?? await locatePath([
|
||||
// Local dev
|
||||
resolveToAbsolutePath('./bin/unraid-api'),
|
||||
// Unraid OS
|
||||
'/usr/local/bin/unraid-api/bin/unraid-api'
|
||||
]) ?? '') ?? undefined;
|
||||
|
||||
// If the unraid-api we found isn't a file then bail
|
||||
if (!lstatSync(apiPath).isFile()) {
|
||||
throw new Error('unraid-api binary couldn\'t be located.');
|
||||
}
|
||||
|
||||
// Ensure the directories exist for the log files
|
||||
if (!existsSync(logsPath)) {
|
||||
logger.debug('Creating log directory %s', logsPath);
|
||||
mkdirSync(logsPath, { recursive: true });
|
||||
}
|
||||
|
||||
// Either the new process will spawn
|
||||
// or it'll timeout/disconnect/exit
|
||||
logger.debug('Starting %s', appName);
|
||||
await Promise.race([
|
||||
new Promise<void>((resolve, reject) => {
|
||||
logger.debug('Spawning %s from %s', appName, apiPath);
|
||||
|
||||
// Fork the child process
|
||||
const args = process.argv.slice(2);
|
||||
apiProcess = spawnProcess(apiPath, args, {
|
||||
stdio: 'pipe',
|
||||
env: {
|
||||
...process.env,
|
||||
DEBUG: undefined
|
||||
}
|
||||
});
|
||||
|
||||
// Create stdout and stderr log files
|
||||
const logConsoleStream = createWriteStream(joinPath(logsPath, `${appName}.stdout.log`), { flags: 'a' });
|
||||
const logErrorStream = createWriteStream(joinPath(logsPath, `${appName}.stderr.log`), { flags: 'a' });
|
||||
|
||||
// Redirect stdout and stderr to log files
|
||||
apiProcess.stdout?.pipe(logConsoleStream);
|
||||
apiProcess.stderr?.pipe(logErrorStream);
|
||||
|
||||
// App has started
|
||||
apiProcess.stdout?.once('data', () => {
|
||||
logger.debug('%s has started', appName);
|
||||
resolve();
|
||||
});
|
||||
|
||||
// App has thrown an error
|
||||
apiProcess.stderr?.once('data', (data: Buffer) => {
|
||||
logger.debug('%s threw an error %s', appName, data);
|
||||
reject(new Error(data.toString()));
|
||||
});
|
||||
|
||||
// App has exited
|
||||
apiProcess.once('exit', async code => {
|
||||
const exitCode = code ?? 0;
|
||||
logger.debug('%s exited with code %s', appName, exitCode);
|
||||
|
||||
// Increase timeout by 30s for every restart
|
||||
const initialTimeoutLength = restarts === 0 ? 30_000 : 30_000 * restarts;
|
||||
// Reset the timeout to 30s if it gets above 5 minutes
|
||||
const timeoutLength = initialTimeoutLength >= (60_000 * 5) ? 30_000 : initialTimeoutLength;
|
||||
|
||||
// Wait for timer before restarting
|
||||
logger.info('Restarting %s in %s %s/%s', appName, intervalToHuman(timeoutLength), restarts + 1, maxRestarts);
|
||||
await sleep(timeoutLength);
|
||||
|
||||
// Restart the app
|
||||
if (shouldRestart && restarts < maxRestarts) {
|
||||
logger.info('Restarting %s now %s/%s', appName, restarts + 1, maxRestarts);
|
||||
await startApi(restarts + 1).catch(error => {
|
||||
logger.error('Failed restarting %s with %s', appName, error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
logger.debug('Waiting for %s to start', appName);
|
||||
}),
|
||||
new Promise<void>((_resolve, reject) => {
|
||||
// Increase timeout by 30s for every restart
|
||||
const initialTimeoutLength = restarts === 0 ? 30_000 : 30_000 * restarts;
|
||||
// Reset the timeout to 30s if it gets above 5 minutes
|
||||
const timeoutLength = initialTimeoutLength >= (60_000 * 5) ? 30_000 : initialTimeoutLength;
|
||||
setTimeout(() => {
|
||||
reject(new Error(`Timed-out starting \`${appName}\`.`));
|
||||
}, timeoutLength);
|
||||
})
|
||||
]).catch((error: unknown) => {
|
||||
logger.error('Failed spawning %s with %s', appName, error);
|
||||
apiProcess?.kill();
|
||||
});
|
||||
};
|
||||
|
||||
// On exit
|
||||
const bindExitHook = async () => {
|
||||
let isExiting = false;
|
||||
const onExit = (shouldBail: boolean, signal: number) => {
|
||||
if (isExiting) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Kill api if it's still running
|
||||
if (apiProcess) {
|
||||
logger.debug('Killing %s process with pid %s', appName, apiProcess.pid);
|
||||
apiProcess.kill('SIGTERM');
|
||||
}
|
||||
|
||||
isExiting = true;
|
||||
const exitCode = 128 + signal;
|
||||
logger.debug('Supervisor exited with code %s', exitCode);
|
||||
|
||||
if (shouldBail) {
|
||||
process.exit(exitCode);
|
||||
}
|
||||
};
|
||||
|
||||
process.once('exit', onExit);
|
||||
process.once('SIGINT', onExit.bind(undefined, true, 2));
|
||||
process.once('SIGTERM', onExit.bind(undefined, true, 15));
|
||||
};
|
||||
|
||||
const startSupervisor = async () => {
|
||||
logger.debug('Starting supervisor');
|
||||
await bindExitHook();
|
||||
await killOldProcesses('supervisor', 'unsupervisor');
|
||||
await killOldProcesses('unraid-api', 'unraid-api');
|
||||
await startApi();
|
||||
};
|
||||
|
||||
// Start supervisor
|
||||
startSupervisor().catch(error => {
|
||||
logger.error('Failed starting %s with %s', appName, isDebug ? cleanStack(error) : error.message);
|
||||
});
|
||||
1
app/types/index.d.ts
vendored
1
app/types/index.d.ts
vendored
@@ -1 +0,0 @@
|
||||
declare module '*.json';
|
||||
@@ -2,14 +2,14 @@ import fetch from 'cross-fetch';
|
||||
import * as Sentry from '@sentry/node';
|
||||
import { MOTHERSHIP_GRAPHQL_LINK } from './consts';
|
||||
import { CachedServer } from './cache';
|
||||
import packageJson from '../package.json';
|
||||
import { version } from '../package.json';
|
||||
|
||||
export const getServers = async (apiKey: string) => fetch(MOTHERSHIP_GRAPHQL_LINK, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
'x-unraid-api-version': packageJson.version
|
||||
'x-unraid-api-version': version
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: 'query($apiKey: String!) { servers @auth(apiKey: $apiKey) { owner { username url avatar } guid apikey name status wanip lanip localurl remoteurl } }',
|
||||
|
||||
@@ -8,19 +8,19 @@ const subscriptions: Record<string, subscription> = {};
|
||||
/**
|
||||
* Return current ws connection count.
|
||||
*/
|
||||
export const getWsConectionCount = () => {
|
||||
export const getWsConnectionCount = () => {
|
||||
return Object.values(subscriptions).filter(subscription => subscription.total >= 1).length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return current ws connection count in channel.
|
||||
*/
|
||||
export const getWsConectionCountInChannel = (channel: string) => {
|
||||
export const getWsConnectionCountInChannel = (channel: string) => {
|
||||
return Object.values(subscriptions).filter(subscription => subscription.channels.includes(channel)).length;
|
||||
};
|
||||
|
||||
export const hasSubscribedToChannel = (id: string, channel: string) => {
|
||||
// Setup inital object
|
||||
// Setup initial object
|
||||
if (subscriptions[id] === undefined) {
|
||||
subscriptions[id] = {
|
||||
total: 1,
|
||||
@@ -34,7 +34,7 @@ export const hasSubscribedToChannel = (id: string, channel: string) => {
|
||||
};
|
||||
|
||||
export const hasUnsubscribedFromChannel = (id: string, channel: string) => {
|
||||
// Setup inital object
|
||||
// Setup initial object
|
||||
if (subscriptions[id] === undefined) {
|
||||
subscriptions[id] = {
|
||||
total: 0,
|
||||
|
||||
430
package-lock.json
generated
430
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@unraid/api",
|
||||
"version": "2.26.14",
|
||||
"version": "2.27.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -1447,14 +1447,6 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/fs-extra": {
|
||||
"version": "9.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.12.tgz",
|
||||
"integrity": "sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/http-assert": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz",
|
||||
@@ -1543,32 +1535,17 @@
|
||||
"integrity": "sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/ms": {
|
||||
"version": "0.7.31",
|
||||
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz",
|
||||
"integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz",
|
||||
"integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g=="
|
||||
},
|
||||
"@types/node-fetch": {
|
||||
"version": "2.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz",
|
||||
"integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==",
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"form-data": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"form-data": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
|
||||
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/normalize-package-data": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
|
||||
@@ -1991,6 +1968,13 @@
|
||||
"requires": {
|
||||
"clean-stack": "^2.0.0",
|
||||
"indent-string": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"clean-stack": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ain2": {
|
||||
@@ -3688,9 +3672,21 @@
|
||||
}
|
||||
},
|
||||
"clean-stack": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.1.0.tgz",
|
||||
"integrity": "sha512-dxXQYI7mfQVcaF12s6sjNFoZ6ZPDQuBBLp3QJ5156k9EvUFClUoZ11fo8HnLQO241DDVntHEug8MOuFO5PSfRg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escape-string-regexp": "5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"escape-string-regexp": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
||||
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"clean-yaml-object": {
|
||||
"version": "0.1.0",
|
||||
@@ -3841,7 +3837,8 @@
|
||||
"command-exists": {
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
|
||||
"integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w=="
|
||||
"integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
|
||||
"dev": true
|
||||
},
|
||||
"command-line-args": {
|
||||
"version": "5.1.1",
|
||||
@@ -5216,7 +5213,8 @@
|
||||
"crypto-random-string": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
||||
"integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA=="
|
||||
"integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
|
||||
"dev": true
|
||||
},
|
||||
"cssfilter": {
|
||||
"version": "0.0.10",
|
||||
@@ -5392,7 +5390,8 @@
|
||||
"dedent-tabs": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/dedent-tabs/-/dedent-tabs-0.9.0.tgz",
|
||||
"integrity": "sha512-XpJr3b3pX6XHK0MDE9/hF2AxAIqzeBhBWqQ22PlzEZFqR31N8x44+e/iML76cwVvhjVqk1BqZeTBS9BrccMJlA=="
|
||||
"integrity": "sha512-XpJr3b3pX6XHK0MDE9/hF2AxAIqzeBhBWqQ22PlzEZFqR31N8x44+e/iML76cwVvhjVqk1BqZeTBS9BrccMJlA==",
|
||||
"dev": true
|
||||
},
|
||||
"deep-equal": {
|
||||
"version": "1.1.1",
|
||||
@@ -5513,6 +5512,7 @@
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz",
|
||||
"integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"globby": "^11.0.1",
|
||||
"graceful-fs": "^4.2.4",
|
||||
@@ -5528,6 +5528,7 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
|
||||
"integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aggregate-error": "^3.0.0"
|
||||
}
|
||||
@@ -5810,7 +5811,8 @@
|
||||
"duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="
|
||||
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
|
||||
"dev": true
|
||||
},
|
||||
"duplexer3": {
|
||||
"version": "0.1.4",
|
||||
@@ -5984,6 +5986,12 @@
|
||||
"event-emitter": "~0.3.5"
|
||||
}
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||
"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
|
||||
"dev": true
|
||||
},
|
||||
"es6-set": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
|
||||
@@ -6017,9 +6025,9 @@
|
||||
}
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.12.17",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.17.tgz",
|
||||
"integrity": "sha512-GshKJyVYUnlSXIZj/NheC2O0Kblh42CS7P1wJyTbbIHevTG4jYMS9NNw8EOd8dDWD0dzydYHS01MpZoUcQXB4g==",
|
||||
"version": "0.12.29",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.29.tgz",
|
||||
"integrity": "sha512-w/XuoBCSwepyiZtIRsKsetiLDUVGPVw1E/R3VTFSecIy8UR7Cq3SOtwKHJMFoVqqVG36aGkzh4e8BvpO1Fdc7g==",
|
||||
"dev": true
|
||||
},
|
||||
"escalade": {
|
||||
@@ -6346,30 +6354,6 @@
|
||||
"es5-ext": "~0.10.14"
|
||||
}
|
||||
},
|
||||
"event-stream": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
|
||||
"integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
|
||||
"requires": {
|
||||
"duplexer": "~0.1.1",
|
||||
"from": "~0",
|
||||
"map-stream": "~0.1.0",
|
||||
"pause-stream": "0.0.11",
|
||||
"split": "0.3",
|
||||
"stream-combiner": "~0.0.4",
|
||||
"through": "~2.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"split": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
|
||||
"integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
|
||||
"requires": {
|
||||
"through": "2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"eventemitter3": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
|
||||
@@ -6846,6 +6830,29 @@
|
||||
"resolve-dir": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"fkill": {
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/fkill/-/fkill-7.2.1.tgz",
|
||||
"integrity": "sha512-eN9cmsIlRdq06wu3m01OOEgQf5Xh/M7REm0jfZ4eL3V3XisjXzfRq3iyqtKS+FhO6wB36FvWRiRGdeSx5KpLAQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aggregate-error": "^3.1.0",
|
||||
"arrify": "^2.0.1",
|
||||
"execa": "^5.0.0",
|
||||
"pid-port": "^0.1.0",
|
||||
"process-exists": "^4.0.0",
|
||||
"ps-list": "^7.2.0",
|
||||
"taskkill": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"arrify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
|
||||
"integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"flat-cache": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
||||
@@ -6939,11 +6946,6 @@
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
||||
},
|
||||
"from": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
|
||||
"integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4="
|
||||
},
|
||||
"fromentries": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
|
||||
@@ -8131,6 +8133,12 @@
|
||||
"kind-of": "^6.0.2"
|
||||
}
|
||||
},
|
||||
"interval-to-human": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/interval-to-human/-/interval-to-human-0.1.1.tgz",
|
||||
"integrity": "sha1-TF/91qV1oMUvAcqm2oz+sDJoXFA=",
|
||||
"dev": true
|
||||
},
|
||||
"ip": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
||||
@@ -8396,12 +8404,14 @@
|
||||
"is-path-cwd": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
||||
"integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ=="
|
||||
"integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-path-inside": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
|
||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="
|
||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-plain-obj": {
|
||||
"version": "1.1.0",
|
||||
@@ -9268,11 +9278,6 @@
|
||||
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.1.tgz",
|
||||
"integrity": "sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ=="
|
||||
},
|
||||
"map-stream": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
|
||||
"integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ="
|
||||
},
|
||||
"map-visit": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
|
||||
@@ -9858,6 +9863,12 @@
|
||||
"remove-array-items": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"nanocolors": {
|
||||
"version": "0.2.12",
|
||||
"resolved": "https://registry.npmjs.org/nanocolors/-/nanocolors-0.2.12.tgz",
|
||||
"integrity": "sha512-SFNdALvzW+rVlzqexid6epYdt8H9Zol7xDoQarioEFcFN0JHo4CYNztAxmtfgGTVRCmFlEOqqhBpoFGKqSAMug==",
|
||||
"dev": true
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
|
||||
@@ -10721,14 +10732,6 @@
|
||||
"integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==",
|
||||
"dev": true
|
||||
},
|
||||
"pause-stream": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
|
||||
"integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
|
||||
"requires": {
|
||||
"through": "~2.3"
|
||||
}
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
@@ -10739,6 +10742,15 @@
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
|
||||
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw=="
|
||||
},
|
||||
"pid-port": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/pid-port/-/pid-port-0.1.1.tgz",
|
||||
"integrity": "sha512-boqPJtSgZC6KOgXKNPC+/XR3xwVtpOtaLa7JLcdf8jfVe0ZM2TwllBXxxLUO8GQbOLJ4/hEtf2+L1QCKbaoHUg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"execa": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"pidusage": {
|
||||
"version": "2.0.21",
|
||||
"resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz",
|
||||
@@ -10750,7 +10762,8 @@
|
||||
"pify": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz",
|
||||
"integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA=="
|
||||
"integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==",
|
||||
"dev": true
|
||||
},
|
||||
"pirates": {
|
||||
"version": "4.0.1",
|
||||
@@ -10890,6 +10903,23 @@
|
||||
"parse-ms": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"process-exists": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/process-exists/-/process-exists-4.1.0.tgz",
|
||||
"integrity": "sha512-BBJoiorUKoP2AuM5q/yKwIfT1YWRHsaxjW+Ayu9erLhqKOfnXzzVVML0XTYoQZuI1YvcWKmc1dh06DEy4+KzfA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ps-list": "^6.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ps-list": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ps-list/-/ps-list-6.3.0.tgz",
|
||||
"integrity": "sha512-qau0czUSB0fzSlBOQt0bo+I2v6R+xiQdj78e1BR/Qjfl5OHWJ/urXi8+ilw1eHe+5hSeDI1wrwVTgDp2wst4oA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
@@ -10928,13 +10958,11 @@
|
||||
"ipaddr.js": "1.9.1"
|
||||
}
|
||||
},
|
||||
"ps-tree": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz",
|
||||
"integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==",
|
||||
"requires": {
|
||||
"event-stream": "=3.3.4"
|
||||
}
|
||||
"ps-list": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ps-list/-/ps-list-7.2.0.tgz",
|
||||
"integrity": "sha512-v4Bl6I3f2kJfr5o80ShABNHAokIgY+wFDTQfE+X3zWYgSGQOCBeYptLZUpoOALBqO5EawmDN/tjTldJesd0ujQ==",
|
||||
"dev": true
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.8.0",
|
||||
@@ -11562,9 +11590,9 @@
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.55.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.55.1.tgz",
|
||||
"integrity": "sha512-1P9w5fpb6b4qroePh8vHKGIvPNxwoCQhjJpIqfZGHLKpZ0xcU2/XBmFxFbc9697/6bmHpmFTLk5R1dAQhFSo0g==",
|
||||
"version": "2.57.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.57.0.tgz",
|
||||
"integrity": "sha512-bKQIh1rWKofRee6mv8SrF2HdP6pea5QkwBZSMImJysFj39gQuiV8MEPBjXOCpzk3wSYp63M2v2wkWBmFC8O/rg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "~2.3.2"
|
||||
@@ -12473,14 +12501,6 @@
|
||||
"resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz",
|
||||
"integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw=="
|
||||
},
|
||||
"stream-combiner": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
|
||||
"integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=",
|
||||
"requires": {
|
||||
"duplexer": "~0.1.1"
|
||||
}
|
||||
},
|
||||
"stream-shift": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
|
||||
@@ -12593,14 +12613,6 @@
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es6-promise": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"es6-promise": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||
"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"subscriptions-transport-ws": {
|
||||
@@ -12623,9 +12635,9 @@
|
||||
}
|
||||
},
|
||||
"sucrase": {
|
||||
"version": "3.20.0",
|
||||
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.20.0.tgz",
|
||||
"integrity": "sha512-Rsp+BX7DRuCleJvBAHN7gQ3ddk7U0rJev19XlIBF6dAq9vX4Tr5mHk4E7+ig/I7BM3DLYotCmm20lfBElT2XtQ==",
|
||||
"version": "3.20.1",
|
||||
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.20.1.tgz",
|
||||
"integrity": "sha512-BIG59HaJOxNct9Va6KvT5yzBA/rcMGetzvZyTx0ZdCcspIbpJTPS64zuAfYlJuOj+3WaI5JOdA+F0bJQQi8ZiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "^4.0.0",
|
||||
@@ -12873,15 +12885,80 @@
|
||||
"xtend": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"taskkill": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/taskkill/-/taskkill-3.1.0.tgz",
|
||||
"integrity": "sha512-5KcOFzPvd1nGFVrmB7H4+QAWVjYOf//+QTbOj0GpXbqtqbKGWVczG+rq6VhXAtdtlKLTs16NAmHRyF5vbggQ2w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"arrify": "^2.0.1",
|
||||
"execa": "^3.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"arrify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
|
||||
"integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
|
||||
"dev": true
|
||||
},
|
||||
"execa": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz",
|
||||
"integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"get-stream": "^5.0.0",
|
||||
"human-signals": "^1.1.1",
|
||||
"is-stream": "^2.0.0",
|
||||
"merge-stream": "^2.0.0",
|
||||
"npm-run-path": "^4.0.0",
|
||||
"onetime": "^5.1.0",
|
||||
"p-finally": "^2.0.0",
|
||||
"signal-exit": "^3.0.2",
|
||||
"strip-final-newline": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"human-signals": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
|
||||
"integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
|
||||
"dev": true
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||
"dev": true
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz",
|
||||
"integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"temp-dir": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
|
||||
"integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg=="
|
||||
"integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==",
|
||||
"dev": true
|
||||
},
|
||||
"tempy": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz",
|
||||
"integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"del": "^6.0.0",
|
||||
"is-stream": "^2.0.0",
|
||||
@@ -12893,12 +12970,14 @@
|
||||
"is-stream": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||
"dev": true
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.16.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz",
|
||||
"integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg=="
|
||||
"integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -12955,7 +13034,8 @@
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
||||
"dev": true
|
||||
},
|
||||
"through2": {
|
||||
"version": "2.0.5",
|
||||
@@ -13164,23 +13244,23 @@
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"tsup": {
|
||||
"version": "4.12.5",
|
||||
"resolved": "https://registry.npmjs.org/tsup/-/tsup-4.12.5.tgz",
|
||||
"integrity": "sha512-3f0StcX+trOZvgaY/iU11U8HvvQ4v/LLgoP9OmxtOQVXP8e/Q8FSk69d0bXFb2pHB77CmVxvqiWdwybELQfx1A==",
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tsup/-/tsup-5.2.1.tgz",
|
||||
"integrity": "sha512-eQmRfKoHIiTFg38Dh2MARCx3J0+P+wbwB5iSHcXTwsnVR9csGLpln5qqBjdgyAGV1VTbOmyU37veCi2eA+wuqA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cac": "^6.7.2",
|
||||
"chalk": "^4.1.0",
|
||||
"chokidar": "^3.5.1",
|
||||
"debug": "^4.3.1",
|
||||
"esbuild": "^0.12.9",
|
||||
"esbuild": "^0.12.28",
|
||||
"execa": "^5.0.0",
|
||||
"globby": "^11.0.3",
|
||||
"joycon": "^3.0.1",
|
||||
"postcss-load-config": "^3.0.1",
|
||||
"resolve-from": "^5.0.0",
|
||||
"rollup": "^2.45.2",
|
||||
"sucrase": "^3.18.1",
|
||||
"rollup": "^2.56.1",
|
||||
"sucrase": "^3.20.1",
|
||||
"tree-kill": "^1.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -13387,6 +13467,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
|
||||
"integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"crypto-random-string": "^2.0.0"
|
||||
}
|
||||
@@ -13905,107 +13986,6 @@
|
||||
"tslib": "^1.9.3",
|
||||
"zen-observable": "^0.8.0"
|
||||
}
|
||||
},
|
||||
"zx": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/zx/-/zx-4.2.0.tgz",
|
||||
"integrity": "sha512-/4f7FaJecA9I655KXKXIHO3CFNYjAz2uSmTz6v2eNlKdrQKyz4VyF3RjqFuP6nQG+Hd3+NjOvrVNBkv8Ne9d4Q==",
|
||||
"requires": {
|
||||
"@types/fs-extra": "^9.0.12",
|
||||
"@types/minimist": "^1.2.2",
|
||||
"@types/node": "^16.6",
|
||||
"@types/node-fetch": "^2.5.12",
|
||||
"chalk": "^4.1.2",
|
||||
"fs-extra": "^10.0.0",
|
||||
"globby": "^12.0.1",
|
||||
"minimist": "^1.2.5",
|
||||
"node-fetch": "^2.6.1",
|
||||
"ps-tree": "^1.2.0",
|
||||
"which": "^2.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/minimist": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
|
||||
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ=="
|
||||
},
|
||||
"array-union": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz",
|
||||
"integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw=="
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"fast-glob": {
|
||||
"version": "3.2.7",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
|
||||
"integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==",
|
||||
"requires": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
"@nodelib/fs.walk": "^1.2.3",
|
||||
"glob-parent": "^5.1.2",
|
||||
"merge2": "^1.3.0",
|
||||
"micromatch": "^4.0.4"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
||||
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"globby": {
|
||||
"version": "12.0.2",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-12.0.2.tgz",
|
||||
"integrity": "sha512-lAsmb/5Lww4r7MM9nCCliDZVIKbZTavrsunAsHLr9oHthrZP1qi7/gAnHOsUs9bLvEt2vKVJhHmxuL7QbDuPdQ==",
|
||||
"requires": {
|
||||
"array-union": "^3.0.1",
|
||||
"dir-glob": "^3.0.1",
|
||||
"fast-glob": "^3.2.7",
|
||||
"ignore": "^5.1.8",
|
||||
"merge2": "^1.4.1",
|
||||
"slash": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"slash": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
|
||||
"integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew=="
|
||||
},
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
37
package.json
37
package.json
@@ -1,17 +1,18 @@
|
||||
{
|
||||
"name": "@unraid/api",
|
||||
"version": "2.26.14",
|
||||
"main": "dist/index.js",
|
||||
"version": "2.27.1",
|
||||
"repository": "git@github.com:unraid/api.git",
|
||||
"author": "Alexis Tyler <xo@wvvw.me> (https://wvvw.me/)",
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"build": "npm run build-app && npm run build-cli && npm run copy-schemas",
|
||||
"build": "npm run build-app && npm run build-cli && npm run build-supervisor && npm run copy-schemas",
|
||||
"build-app": "npx tsup ./app/index.ts",
|
||||
"build-cli": "npx tsup ./app/cli.ts",
|
||||
"build-binary-step-1": "nexe ./dist/cli.js --make=\"-j$(nproc 2> /dev/null || echo 1)\" -r './dist/**/*' -r './node_modules' && mv ./cli ./unraid-api && echo '✔ Binary built: ./unraid-api'",
|
||||
"build-binary-step-2": "rm -rf ./node_modules && rm -rf ./dist && echo '✔ Source files deleted'",
|
||||
"build-binary": "npm run build-binary-step-1 && npm run build-binary-step-2",
|
||||
"build-supervisor": "npx tsup ./app/supervisor.ts",
|
||||
"build-binary-step-1": "nexe --input ./dist/cli.js --output ./bin/unraid-api --make=\"-j$(nproc 2> /dev/null || echo 1)\" -r './dist/**/*' -r './node_modules/**/*' && echo '✔ Binary built: ./bin/unraid-api'",
|
||||
"build-binary-step-2": "nexe --input ./dist/supervisor.js --output ./bin/unsupervisor --make=\"-j$(nproc 2> /dev/null || echo 1)\" && echo '✔ Binary built: ./bin/unsupervisor'",
|
||||
"build-binary-step-3": "rm -rf ./node_modules && rm -rf ./dist && echo '✔ Source files deleted'",
|
||||
"build-binary": "npm run build-binary-step-1 && npm run build-binary-step-2 && npm run build-binary-step-3",
|
||||
"copy-schemas": "cpx app/**/*.graphql dist/types",
|
||||
"clean": "modclean --no-progress --run --path .",
|
||||
"commit": "npx git-cz",
|
||||
@@ -29,10 +30,10 @@
|
||||
"update-bundle-dependencies": "bundle-dependencies update"
|
||||
},
|
||||
"files": [
|
||||
".env.staging",
|
||||
".env.production",
|
||||
"dist",
|
||||
"unraid-api"
|
||||
"bin",
|
||||
".env.staging",
|
||||
".env.production"
|
||||
],
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.3.17",
|
||||
@@ -58,9 +59,7 @@
|
||||
"clean-cache": "github:OmgImAlexis/clean-cache#master",
|
||||
"clear-module": "^4.1.1",
|
||||
"cli-table": "^0.3.4",
|
||||
"command-exists": "^1.2.9",
|
||||
"cross-fetch": "^3.1.4",
|
||||
"dedent-tabs": "^0.9.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"dl-tgz": "^0.7.1",
|
||||
"dockerode": "^3.3.0",
|
||||
@@ -93,7 +92,6 @@
|
||||
"map-obj": "^4.2.1",
|
||||
"micromongo": "^0.3.1",
|
||||
"mqtt": "github:OmgImAlexis/MQTT.js#master",
|
||||
"ms": "^2.1.3",
|
||||
"multi-ini": "^2.1.2",
|
||||
"mustache": "^4.2.0",
|
||||
"nanobus": "^4.5.0",
|
||||
@@ -108,7 +106,6 @@
|
||||
"package-json": "^7.0.0",
|
||||
"path-exists": "^4.0.0",
|
||||
"pidusage": "^2.0.21",
|
||||
"pify": "^5.0.0",
|
||||
"pretty-bytes": "^5.6.0",
|
||||
"pretty-ms": "^7.0.1",
|
||||
"redact-secrets": "OmgImAlexis/redact-secrets#master",
|
||||
@@ -121,7 +118,6 @@
|
||||
"stoppable": "^1.1.0",
|
||||
"subscriptions-transport-ws": "^0.9.18",
|
||||
"systeminformation": "^5.6.20",
|
||||
"tempy": "^1.0.1",
|
||||
"ts-command-line-args": "^2.1.0",
|
||||
"upcast": "^4.0.0",
|
||||
"uuid": "^8.3.2",
|
||||
@@ -135,6 +131,7 @@
|
||||
"@types/cli-table": "^0.3.0",
|
||||
"@types/dockerode": "^3.2.7",
|
||||
"@types/lodash.get": "^4.4.6",
|
||||
"@types/ms": "^0.7.31",
|
||||
"@types/node": "^16.6.1",
|
||||
"@types/pify": "^5.0.1",
|
||||
"@types/semver-regex": "^3.1.0",
|
||||
@@ -145,20 +142,30 @@
|
||||
"ava": "^3.15.0",
|
||||
"ava-env": "^2.0.2",
|
||||
"bundle-dependencies": "^1.0.2",
|
||||
"clean-stack": "^4.1.0",
|
||||
"command-exists": "^1.2.9",
|
||||
"cpx": "1.5.0",
|
||||
"cz-conventional-changelog": "3.3.0",
|
||||
"dedent-tabs": "^0.9.0",
|
||||
"eslint": "^7.32.0",
|
||||
"fkill": "^7.2.1",
|
||||
"interval-to-human": "^0.1.1",
|
||||
"modclean": "^3.0.0-beta.1",
|
||||
"ms": "^2.1.3",
|
||||
"nanocolors": "^0.2.12",
|
||||
"node-env-run": "^4.0.2",
|
||||
"nyc": "^15.1.0",
|
||||
"p-each-series": "^3.0.0",
|
||||
"p-props": "^5.0.0",
|
||||
"path-type": "^5.0.0",
|
||||
"pify": "^5.0.0",
|
||||
"ps-list": "^7.2.0",
|
||||
"source-map-support": "0.5.19",
|
||||
"standard-version": "^9.1.1",
|
||||
"supertest": "^6.1.3",
|
||||
"tempy": "^1.0.1",
|
||||
"ts-node": "10.1.0",
|
||||
"tsup": "^4.12.5",
|
||||
"tsup": "^5.2.1",
|
||||
"typescript": "4.3.5",
|
||||
"typescript-coverage-report": "^0.6.0"
|
||||
},
|
||||
|
||||
@@ -1,78 +1,29 @@
|
||||
{
|
||||
"include": [
|
||||
"app/**/*",
|
||||
"test/**/*"
|
||||
"test/**/*",
|
||||
"package.json"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||
"allowJs": false, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./dist", /* Redirect output structure to the directory. */
|
||||
"rootDir": "./app", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
"removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
"strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
"noUnusedLocals": false, /* Report errors on unused locals. */
|
||||
"noUnusedParameters": false, /* Report errors on unused parameters. */
|
||||
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
"noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
"typeRoots": [
|
||||
"node_modules/@types/",
|
||||
"./app/types/"
|
||||
], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
|
||||
/* Advanced Options */
|
||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
|
||||
"resolveJsonModule": false
|
||||
}
|
||||
}
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
"target": "es2020",
|
||||
"module": "commonjs",
|
||||
"allowJs": false,
|
||||
"outDir": "./dist",
|
||||
"rootDir": ".",
|
||||
"removeComments": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"strictNullChecks": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user