Update lodash types

Change-type: patch
This commit is contained in:
Pagan Gazzard 2020-01-17 13:50:25 +00:00
parent 0ef9cc189b
commit 1a393dbb19
5 changed files with 78 additions and 56 deletions

6
package-lock.json generated
View File

@ -352,9 +352,9 @@
"dev": true
},
"@types/lodash": {
"version": "4.14.122",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.122.tgz",
"integrity": "sha512-9IdED8wU93ty8gP06ninox+42SBSJHp2IAamsSYMUY76mshRTeUsid/gtbl8ovnOwy8im41ib4cxTiIYMXGKew==",
"version": "4.14.149",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz",
"integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==",
"dev": true
},
"@types/lodash.memoize": {

View File

@ -47,7 +47,7 @@
"@types/express": "^4.17.2",
"@types/knex": "^0.14.14",
"@types/lockfile": "^1.0.1",
"@types/lodash": "4.14.122",
"@types/lodash": "^4.14.149",
"@types/memoizee": "^0.4.3",
"@types/mkdirp": "^0.5.2",
"@types/mocha": "^5.2.7",

View File

@ -53,10 +53,6 @@ export interface Image {
downloadProgress: Nullable<number>;
}
// TODO: This is necessary for the format() method, but I'm not sure
// why, and it seems like a bad idea as it is. Fix the need for this.
type MaybeImage = { [key in keyof Image]: Image[key] | null };
// TODO: Remove the need for this type...
type NormalisedDockerImage = Docker.ImageInfo & {
NormalisedRepoTags: string[];
@ -336,11 +332,11 @@ export class Images extends (EventEmitter as new () => ImageEventEmitter) {
}
public async update(image: Image): Promise<void> {
image = this.format(image);
const formattedImage = this.format(image);
await this.db
.models('image')
.update(image)
.where({ name: image.name });
.update(formattedImage)
.where({ name: formattedImage.name });
}
public async save(image: Image): Promise<void> {
@ -577,17 +573,17 @@ export class Images extends (EventEmitter as new () => ImageEventEmitter) {
}
private async markAsSupervised(image: Image): Promise<void> {
image = this.format(image);
// TODO: Get rid of this janky cast once the database is
// more strongly typed
const formattedImage = this.format(image);
await this.db.upsertModel(
'image',
image,
(image as unknown) as Dictionary<unknown>,
formattedImage,
// TODO: Upsert to new values only when they already match? This is likely a bug
// and currently acts like an "insert if not exists"
formattedImage,
);
}
private format(image: MaybeImage): Image {
private format(image: Image): Omit<Image, 'id'> {
return _(image)
.defaults({
serviceId: null,
@ -598,7 +594,7 @@ export class Images extends (EventEmitter as new () => ImageEventEmitter) {
dockerImageId: null,
})
.omit('id')
.value() as Image;
.value();
}
private async fetchDelta(

View File

@ -1,6 +1,7 @@
import * as _ from 'lodash';
import { inspect } from 'util';
import { TargetState } from '../types/state';
import { EnvVarObject, LabelObject } from './types';
import log from './supervisor-console';
@ -206,7 +207,7 @@ function undefinedOrValidEnv(val: EnvVarObject): boolean {
*
* TODO: Type the input
*/
export function isValidDependentAppsObject(apps: any): boolean {
export function isValidDependentAppsObject(apps: unknown): boolean {
if (!_.isObject(apps)) {
log.debug(
'Non-object passed to validation.isValidDependentAppsObject\nApps:',
@ -215,8 +216,8 @@ export function isValidDependentAppsObject(apps: any): boolean {
return false;
}
return _.every(apps, (val, appId) => {
val = _.defaults(_.clone(val), {
return _.every(apps, (v, appId) => {
const val: TargetState['dependent']['apps'][any] = _.defaults(_.clone(v), {
config: undefined,
environment: undefined,
commit: undefined,
@ -366,7 +367,7 @@ export function isValidAppsObject(obj: any): boolean {
return false;
}
return _.every(obj, (val, appId) => {
return _.every(obj, (v, appId) => {
if (!isValidShortText(appId) || !checkInt(appId)) {
log.debug(
'Invalid appId passed to validation.isValidAppsObject\nApp ID:',
@ -375,7 +376,13 @@ export function isValidAppsObject(obj: any): boolean {
return false;
}
return _.conformsTo(_.defaults(_.clone(val), { releaseId: undefined }), {
// TODO: Remove this partial and validate the extra fields
const val: Partial<TargetState['local']['apps'][any]> = _.defaults(
_.clone(v),
{ releaseId: undefined },
);
return _.conformsTo(val, {
name: (n: any) => {
if (!isValidShortText(n)) {
log.debug(
@ -443,7 +450,7 @@ export function isValidDependentDevicesObject(devices: any): boolean {
return false;
}
return _.conformsTo(val, {
return _.conformsTo(val as TargetState['dependent']['devices'][any], {
name: (n: any) => {
if (!isValidShortText(n)) {
log.debug(
@ -470,34 +477,37 @@ export function isValidDependentDevicesObject(devices: any): boolean {
return false;
}
return _.every(a, app => {
app = _.defaults(_.clone(app), {
config: undefined,
environment: undefined,
});
return _.conformsTo(app, {
config: (c: any) => {
if (!undefinedOrValidEnv(c)) {
log.debug(
'Invalid config passed to validation.isValidDependentDevicesObject\nConfig:',
inspect(c),
);
return false;
}
return true;
},
environment: (e: any) => {
if (!undefinedOrValidEnv(e)) {
log.debug(
'Invalid environment passed to validation.isValidDependentDevicesObject\nConfig:',
inspect(e),
);
return false;
}
return true;
},
});
});
return _.every(
a as TargetState['dependent']['devices'][any]['apps'],
app => {
app = _.defaults(_.clone(app), {
config: undefined,
environment: undefined,
});
return _.conformsTo(app, {
config: (c: any) => {
if (!undefinedOrValidEnv(c)) {
log.debug(
'Invalid config passed to validation.isValidDependentDevicesObject\nConfig:',
inspect(c),
);
return false;
}
return true;
},
environment: (e: any) => {
if (!undefinedOrValidEnv(e)) {
log.debug(
'Invalid environment passed to validation.isValidDependentDevicesObject\nConfig:',
inspect(e),
);
return false;
}
return true;
},
});
},
);
},
});
});

View File

@ -1,6 +1,7 @@
import { ComposeNetworkConfig } from '../compose/types/network';
import { ServiceComposeConfig } from '../compose/types/service';
import { ComposeVolumeConfig } from '../compose/volume';
import { EnvVarObject, LabelObject } from '../lib/types';
export interface DeviceApplicationState {
local?: {
@ -27,7 +28,7 @@ export interface DeviceApplicationState {
export interface TargetState {
local: {
name: string;
config: Dictionary<string>;
config: EnvVarObject;
apps: {
[appId: string]: {
name: string;
@ -35,12 +36,12 @@ export interface TargetState {
releaseId: number;
services: {
[serviceId: string]: {
labels: Dictionary<string>;
labels: LabelObject;
imageId: number;
serviceName: string;
image: string;
running: boolean;
environment: Dictionary<string>;
environment: EnvVarObject;
} & ServiceComposeConfig;
};
volumes: Dictionary<Partial<ComposeVolumeConfig>>;
@ -50,7 +51,22 @@ export interface TargetState {
};
// TODO: Correctly type this once dependent devices are
// actually properly supported
dependent: Dictionary<any>;
dependent: {
apps: Dictionary<{
name?: string;
image?: string;
commit?: string;
config?: EnvVarObject;
environment?: EnvVarObject;
}>;
devices: Dictionary<{
name?: string;
apps?: Dictionary<{
config?: EnvVarObject;
environment?: EnvVarObject;
}>;
}>;
};
}
export type LocalTargetState = TargetState['local'];