@balena/pinejs 15.3.6-build-fixes-expand-on-parent-resource-34e60c2a2921e971b04422e7901f4dbc4df2dde7-1 → 15.3.6-build-balena-lint-v7-c974ff49f97ca861665e55cf2f024372c46006b9-1
Sign up to get free protection for your applications and to get access to all the features.
- package/.versionbot/CHANGELOG.yml +55 -4
- package/CHANGELOG.md +9 -3
- package/Gruntfile.ts +4 -1
- package/README.md +1 -0
- package/out/bin/abstract-sql-compiler.js +1 -1
- package/out/bin/abstract-sql-compiler.js.map +1 -1
- package/out/bin/odata-compiler.js +1 -1
- package/out/bin/odata-compiler.js.map +1 -1
- package/out/bin/sbvr-compiler.js +1 -1
- package/out/bin/sbvr-compiler.js.map +1 -1
- package/out/bin/utils.js.map +1 -1
- package/out/config-loader/config-loader.js +2 -2
- package/out/config-loader/config-loader.js.map +1 -1
- package/out/data-server/sbvr-server.d.ts +1 -1
- package/out/data-server/sbvr-server.js +3 -1
- package/out/data-server/sbvr-server.js.map +1 -1
- package/out/database-layer/db.js +10 -10
- package/out/database-layer/db.js.map +1 -1
- package/out/express-emulator/express.js +4 -2
- package/out/express-emulator/express.js.map +1 -1
- package/out/http-transactions/transactions.d.ts +1 -1
- package/out/http-transactions/transactions.js +10 -5
- package/out/http-transactions/transactions.js.map +1 -1
- package/out/migrator/utils.d.ts +2 -2
- package/out/passport-pinejs/passport-pinejs.d.ts +1 -1
- package/out/passport-pinejs/passport-pinejs.js +4 -1
- package/out/passport-pinejs/passport-pinejs.js.map +1 -1
- package/out/pinejs-session-store/pinejs-session-store.js +6 -6
- package/out/pinejs-session-store/pinejs-session-store.js.map +1 -1
- package/out/sbvr-api/abstract-sql.js +1 -1
- package/out/sbvr-api/abstract-sql.js.map +1 -1
- package/out/sbvr-api/cached-compile.js.map +1 -1
- package/out/sbvr-api/hooks.js +3 -4
- package/out/sbvr-api/hooks.js.map +1 -1
- package/out/sbvr-api/odata-response.d.ts +1 -1
- package/out/sbvr-api/odata-response.js +2 -9
- package/out/sbvr-api/odata-response.js.map +1 -1
- package/out/sbvr-api/permissions.d.ts +4 -5
- package/out/sbvr-api/permissions.js +6 -4
- package/out/sbvr-api/permissions.js.map +1 -1
- package/out/sbvr-api/sbvr-utils.d.ts +1 -1
- package/out/sbvr-api/sbvr-utils.js +4 -2
- package/out/sbvr-api/sbvr-utils.js.map +1 -1
- package/out/sbvr-api/uri-parser.js +1 -1
- package/out/sbvr-api/uri-parser.js.map +1 -1
- package/out/server-glue/global-ext.d.ts +2 -1
- package/out/server-glue/module.js.map +1 -1
- package/out/webresource-handler/handlers/NoopHandler.d.ts +1 -1
- package/out/webresource-handler/handlers/NoopHandler.js +1 -1
- package/out/webresource-handler/handlers/NoopHandler.js.map +1 -1
- package/out/webresource-handler/index.d.ts +0 -4
- package/out/webresource-handler/index.js +30 -20
- package/out/webresource-handler/index.js.map +1 -1
- package/package.json +8 -8
- package/src/bin/abstract-sql-compiler.ts +1 -1
- package/src/bin/odata-compiler.ts +1 -1
- package/src/bin/sbvr-compiler.ts +1 -1
- package/src/bin/utils.ts +1 -1
- package/src/config-loader/config-loader.ts +2 -3
- package/src/data-server/sbvr-server.js +3 -1
- package/src/database-layer/db.ts +18 -14
- package/src/express-emulator/express.js +4 -2
- package/src/extended-sbvr-parser/extended-sbvr-parser.ts +1 -1
- package/src/http-transactions/transactions.js +10 -5
- package/src/migrator/sync.ts +1 -1
- package/src/migrator/utils.ts +2 -2
- package/src/odata-metadata/odata-metadata-generator.ts +1 -1
- package/src/passport-pinejs/passport-pinejs.ts +7 -3
- package/src/pinejs-session-store/pinejs-session-store.ts +6 -6
- package/src/sbvr-api/abstract-sql.ts +1 -1
- package/src/sbvr-api/cached-compile.ts +0 -1
- package/src/sbvr-api/express-extension.ts +4 -2
- package/src/sbvr-api/hooks.ts +3 -4
- package/src/sbvr-api/odata-response.ts +10 -19
- package/src/sbvr-api/permissions.ts +20 -14
- package/src/sbvr-api/sbvr-utils.ts +8 -4
- package/src/sbvr-api/uri-parser.ts +1 -1
- package/src/server-glue/global-ext.d.ts +2 -1
- package/src/server-glue/module.ts +1 -0
- package/src/server-glue/sbvr-loader.ts +1 -1
- package/src/server-glue/server.ts +2 -2
- package/src/webresource-handler/handlers/NoopHandler.ts +1 -1
- package/src/webresource-handler/index.ts +47 -28
- package/tsconfig.dev.json +2 -1
- package/typings/lf-to-abstract-sql.d.ts +1 -1
- package/typings/memoizee.d.ts +3 -4
@@ -32,7 +32,6 @@ import {
|
|
32
32
|
getUploaderMiddlware,
|
33
33
|
WebResourceHandler,
|
34
34
|
setupUploadHooks,
|
35
|
-
setupWebresourceHandler,
|
36
35
|
} from '../webresource-handler';
|
37
36
|
import { AliasValidNodeType } from '../sbvr-api/translations';
|
38
37
|
|
@@ -206,7 +205,6 @@ export const setup = (app: Express.Application) => {
|
|
206
205
|
const webResourceHandler =
|
207
206
|
data.webResourceHandler ?? getDefaultHandler();
|
208
207
|
|
209
|
-
setupWebresourceHandler(webResourceHandler);
|
210
208
|
const fileUploadMiddleware =
|
211
209
|
getUploaderMiddlware(webResourceHandler);
|
212
210
|
app
|
@@ -379,7 +377,7 @@ export const setup = (app: Express.Application) => {
|
|
379
377
|
switch (fileExtension) {
|
380
378
|
case '.coffee':
|
381
379
|
case '.ts':
|
382
|
-
case '.js':
|
380
|
+
case '.js': {
|
383
381
|
const loadeMigration = nodeRequire(filePath);
|
384
382
|
const migration = loadeMigration.default ?? loadeMigration;
|
385
383
|
|
@@ -394,6 +392,7 @@ export const setup = (app: Express.Application) => {
|
|
394
392
|
|
395
393
|
assignMigrationWithCategory(migrationKey, migration);
|
396
394
|
break;
|
395
|
+
}
|
397
396
|
case '.sql':
|
398
397
|
if (migrationCategory === MigrationCategories.async) {
|
399
398
|
console.error(
|
@@ -48,7 +48,7 @@ const serverIsOnAir = async (_req, _res, next) => {
|
|
48
48
|
};
|
49
49
|
|
50
50
|
/** @type {import('../config-loader/config-loader').Config} */
|
51
|
-
export
|
51
|
+
export const config = {
|
52
52
|
models: [
|
53
53
|
{
|
54
54
|
modelName: 'ui',
|
@@ -267,6 +267,8 @@ export async function setup(app, sbvrUtils, db) {
|
|
267
267
|
try {
|
268
268
|
await tx.executeSql(query);
|
269
269
|
} catch (err) {
|
270
|
+
// TODO: Consider changing this to a custom Error
|
271
|
+
// eslint-disable-next-line no-throw-literal
|
270
272
|
throw [query, err];
|
271
273
|
}
|
272
274
|
}
|
package/src/database-layer/db.ts
CHANGED
@@ -168,7 +168,7 @@ const atomicExecuteSql: Database['executeSql'] = async function (
|
|
168
168
|
};
|
169
169
|
|
170
170
|
const asyncTryFn = (fn: () => any) => {
|
171
|
-
Promise.resolve().then(fn);
|
171
|
+
void Promise.resolve().then(fn);
|
172
172
|
};
|
173
173
|
|
174
174
|
type RejectedFunctions = (message: string) => {
|
@@ -215,7 +215,10 @@ class AutomaticClose {
|
|
215
215
|
private automaticCloseTimeout: ReturnType<typeof setTimeout>;
|
216
216
|
private automaticClose: () => void;
|
217
217
|
private pending: false | number = 0;
|
218
|
-
constructor(
|
218
|
+
constructor(
|
219
|
+
tx: Tx,
|
220
|
+
private stackTraceErr?: Error,
|
221
|
+
) {
|
219
222
|
this.automaticClose = () => {
|
220
223
|
console.error(
|
221
224
|
`Transaction still open after ${env.db.timeoutMS}ms without an execute call.`,
|
@@ -223,7 +226,7 @@ class AutomaticClose {
|
|
223
226
|
if (this.stackTraceErr) {
|
224
227
|
console.error(this.stackTraceErr.stack);
|
225
228
|
}
|
226
|
-
tx.rollback();
|
229
|
+
void tx.rollback();
|
227
230
|
};
|
228
231
|
this.automaticCloseTimeout = setTimeout(
|
229
232
|
this.automaticClose,
|
@@ -400,10 +403,13 @@ export abstract class Tx {
|
|
400
403
|
protected abstract _rollback(): Promise<void>;
|
401
404
|
protected abstract _commit(): Promise<void>;
|
402
405
|
|
406
|
+
// TODO: Re-enable the lint rule once eslint properly supports abstract class base implementations
|
403
407
|
public async getTxLevelLock(
|
408
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
404
409
|
_namespaceKey: string,
|
405
410
|
_key: number,
|
406
411
|
_blocking: boolean = true,
|
412
|
+
/* eslint-enable @typescript-eslint/no-unused-vars */
|
407
413
|
): Promise<boolean> {
|
408
414
|
throw new Error(
|
409
415
|
'The getTxLevelLock method is not implemented for the current engine.',
|
@@ -462,7 +468,6 @@ const createTransaction = (createFunc: CreateTransactionFn): TransactionFn => {
|
|
462
468
|
|
463
469
|
let maybePg: typeof Pg | undefined;
|
464
470
|
try {
|
465
|
-
// tslint:disable-next-line:no-var-requires
|
466
471
|
maybePg = require('pg');
|
467
472
|
} catch (e) {
|
468
473
|
// Ignore errors
|
@@ -497,7 +502,7 @@ if (maybePg != null) {
|
|
497
502
|
const p = new pg.Pool(config);
|
498
503
|
if (PG_SCHEMA != null) {
|
499
504
|
p.on('connect', (client) => {
|
500
|
-
client.query({ text: `SET search_path TO "${PG_SCHEMA}"` });
|
505
|
+
void client.query({ text: `SET search_path TO "${PG_SCHEMA}"` });
|
501
506
|
});
|
502
507
|
}
|
503
508
|
p.on('connect', (client) => {
|
@@ -519,6 +524,7 @@ if (maybePg != null) {
|
|
519
524
|
let pool: Pg.Pool;
|
520
525
|
let replica: Pg.Pool;
|
521
526
|
if (typeof connectString === 'string') {
|
527
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
522
528
|
const pgConnectionString: typeof PgConnectionString = require('pg-connection-string');
|
523
529
|
// We have to cast because of the use of null vs undefined
|
524
530
|
const config = pgConnectionString.parse(connectString) as Pg.PoolConfig;
|
@@ -617,9 +623,9 @@ if (maybePg != null) {
|
|
617
623
|
);
|
618
624
|
this.db.release();
|
619
625
|
} catch (err: any) {
|
620
|
-
|
621
|
-
this.db.release(
|
622
|
-
throw
|
626
|
+
const errorToReturn = wrapDatabaseError(err);
|
627
|
+
this.db.release(errorToReturn);
|
628
|
+
throw errorToReturn;
|
623
629
|
}
|
624
630
|
}
|
625
631
|
|
@@ -686,13 +692,13 @@ if (maybePg != null) {
|
|
686
692
|
transaction: createTransaction(async (stackTraceErr) => {
|
687
693
|
const client = await pool.connect();
|
688
694
|
const tx = new PostgresTx(client, false, stackTraceErr);
|
689
|
-
tx.executeSql('START TRANSACTION;');
|
695
|
+
void tx.executeSql('START TRANSACTION;');
|
690
696
|
return tx;
|
691
697
|
}),
|
692
698
|
readTransaction: createTransaction(async (stackTraceErr) => {
|
693
699
|
const client = await replica.connect();
|
694
700
|
const tx = new PostgresTx(client, false, stackTraceErr);
|
695
|
-
tx.executeSql('START TRANSACTION READ ONLY;');
|
701
|
+
void tx.executeSql('START TRANSACTION READ ONLY;');
|
696
702
|
return tx.asReadOnly();
|
697
703
|
}),
|
698
704
|
...alwaysExport,
|
@@ -702,7 +708,6 @@ if (maybePg != null) {
|
|
702
708
|
|
703
709
|
let maybeMysql: typeof Mysql | undefined;
|
704
710
|
try {
|
705
|
-
// tslint:disable-next-line:no-var-requires
|
706
711
|
maybeMysql = require('mysql');
|
707
712
|
} catch (e) {
|
708
713
|
// Ignore errors
|
@@ -809,14 +814,14 @@ if (maybeMysql != null) {
|
|
809
814
|
const client = await getConnectionAsync();
|
810
815
|
const close = () => client.release();
|
811
816
|
const tx = new MySqlTx(client, close, false, stackTraceErr);
|
812
|
-
tx.executeSql('START TRANSACTION;');
|
817
|
+
void tx.executeSql('START TRANSACTION;');
|
813
818
|
return tx;
|
814
819
|
}),
|
815
820
|
readTransaction: createTransaction(async (stackTraceErr) => {
|
816
821
|
const client = await getConnectionAsync();
|
817
822
|
const close = () => client.release();
|
818
823
|
const tx = new MySqlTx(client, close, false, stackTraceErr);
|
819
|
-
tx.executeSql('START TRANSACTION READ ONLY;');
|
824
|
+
void tx.executeSql('START TRANSACTION READ ONLY;');
|
820
825
|
return tx.asReadOnly();
|
821
826
|
}),
|
822
827
|
...alwaysExport,
|
@@ -935,7 +940,6 @@ if (typeof window !== 'undefined' && window.openDatabase != null) {
|
|
935
940
|
// allowing us to use async calls within the API.
|
936
941
|
private asyncRecurse = () => {
|
937
942
|
let args: AsyncQuery | undefined;
|
938
|
-
// tslint:disable-next-line no-conditional-assignment
|
939
943
|
while ((args = this.queue.pop())) {
|
940
944
|
console.debug('Running', args[0]);
|
941
945
|
this.tx.executeSql(args[0], args[1], args[2], args[3]);
|
@@ -34,10 +34,10 @@ const app = (function () {
|
|
34
34
|
/** @type {string} */ match,
|
35
35
|
/** @type import('express').Handler[] */ ...middleware
|
36
36
|
) {
|
37
|
-
//Strip wildcard
|
37
|
+
// Strip wildcard
|
38
38
|
let paramName;
|
39
39
|
match = match.toLowerCase();
|
40
|
-
const newMatch = match.replace(/[
|
40
|
+
const newMatch = match.replace(/[/*]*$/, '');
|
41
41
|
if (newMatch !== match) {
|
42
42
|
match = newMatch;
|
43
43
|
paramName = '*';
|
@@ -59,6 +59,8 @@ const app = (function () {
|
|
59
59
|
/** @type any */ body = '',
|
60
60
|
) {
|
61
61
|
if (!handlers[method]) {
|
62
|
+
// TODO: Consider changing this to a custom Error
|
63
|
+
// eslint-disable-next-line no-throw-literal
|
62
64
|
throw [404, null, null];
|
63
65
|
}
|
64
66
|
const req = {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { SBVRParser } from '@balena/sbvr-parser';
|
2
|
-
//
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
3
3
|
const Types: string = require('@balena/sbvr-types/Type.sbvr');
|
4
4
|
import { version as sbvrParserVersion } from '@balena/sbvr-parser/package.json';
|
5
5
|
import { version } from '@balena/sbvr-parser/package.json';
|
@@ -1,10 +1,10 @@
|
|
1
|
-
import * as _ from 'lodash';
|
2
1
|
import { odataNameToSqlName } from '@balena/odata-to-abstract-sql';
|
3
|
-
// @ts-
|
2
|
+
// @ts-expect-error b/c TS doesn't know what the result of requiring an sbvr file would be
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
4
4
|
const transactionModel = require('./transaction.sbvr');
|
5
5
|
|
6
6
|
/** @type {import('../config-loader/config-loader').Config} */
|
7
|
-
export
|
7
|
+
export const config = {
|
8
8
|
models: [
|
9
9
|
{
|
10
10
|
apiRoot: 'transaction',
|
@@ -130,7 +130,12 @@ WHERE "conditional field"."conditional resource" = ?;`,
|
|
130
130
|
modelField.dataType === 'ForeignKey' &&
|
131
131
|
Number.isNaN(Number(fieldValue))
|
132
132
|
) {
|
133
|
-
if (
|
133
|
+
if (
|
134
|
+
!Object.prototype.hasOwnProperty.call(
|
135
|
+
placeholders,
|
136
|
+
fieldValue,
|
137
|
+
)
|
138
|
+
) {
|
134
139
|
throw new Error('Cannot resolve placeholder' + fieldValue);
|
135
140
|
} else {
|
136
141
|
try {
|
@@ -170,7 +175,7 @@ WHERE "conditional resource"."transaction" = ?;\
|
|
170
175
|
resolve = $resolve;
|
171
176
|
reject = $reject;
|
172
177
|
});
|
173
|
-
// @ts-
|
178
|
+
// @ts-expect-error we use resolve & reject before they are assigned b/c we treat them as a deferred.
|
174
179
|
placeholders[placeholder] = { promise, resolve, reject };
|
175
180
|
}
|
176
181
|
}
|
package/src/migrator/sync.ts
CHANGED
@@ -15,7 +15,7 @@ import type { Config, Model } from '../config-loader/config-loader';
|
|
15
15
|
import * as _ from 'lodash';
|
16
16
|
import * as sbvrUtils from '../sbvr-api/sbvr-utils';
|
17
17
|
|
18
|
-
//
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
19
19
|
const modelText = require('./migrations.sbvr');
|
20
20
|
|
21
21
|
type ApiRootModel = Model & { apiRoot: string };
|
package/src/migrator/utils.ts
CHANGED
@@ -32,12 +32,12 @@ export type AsyncMigrationFn = (
|
|
32
32
|
sbvrUtils: SbvrUtils,
|
33
33
|
) => Resolvable<number>;
|
34
34
|
|
35
|
-
type AddFn<T extends
|
35
|
+
type AddFn<T extends object, x extends 'sync' | 'async'> = T & {
|
36
36
|
[key in `${x}Fn`]: key extends 'syncFn' ? MigrationFn : AsyncMigrationFn;
|
37
37
|
} & {
|
38
38
|
[key in `${x}Sql`]?: undefined;
|
39
39
|
};
|
40
|
-
type AddSql<T extends
|
40
|
+
type AddSql<T extends object, x extends 'sync' | 'async'> = T & {
|
41
41
|
[key in `${x}Fn`]?: undefined;
|
42
42
|
} & {
|
43
43
|
[key in `${x}Sql`]: string;
|
@@ -5,7 +5,7 @@ import type {
|
|
5
5
|
|
6
6
|
import sbvrTypes, { SbvrType } from '@balena/sbvr-types';
|
7
7
|
|
8
|
-
//
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
9
9
|
const { version }: { version: string } = require('../../package.json');
|
10
10
|
|
11
11
|
const getResourceName = (resourceName: string): string =>
|
@@ -10,7 +10,7 @@ import * as permissions from '../sbvr-api/permissions';
|
|
10
10
|
export let login: (
|
11
11
|
fn: (
|
12
12
|
err: any,
|
13
|
-
user:
|
13
|
+
user: object | null | false | undefined,
|
14
14
|
req: Express.Request,
|
15
15
|
res: Express.Response,
|
16
16
|
next: Express.NextFunction,
|
@@ -35,12 +35,13 @@ export const checkPassword: PassportLocal.VerifyFunction = async (
|
|
35
35
|
|
36
36
|
const setup: ConfigLoader.SetupFunction = async (app: Express.Application) => {
|
37
37
|
if (!process.browser) {
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
38
39
|
const passport: typeof Passport = require('passport');
|
39
40
|
app.use(passport.initialize());
|
40
41
|
app.use(passport.session());
|
41
42
|
|
42
43
|
const {
|
43
|
-
Strategy: LocalStrategy,
|
44
|
+
Strategy: LocalStrategy, // eslint-disable-next-line @typescript-eslint/no-var-requires
|
44
45
|
}: typeof PassportLocal = require('passport-local');
|
45
46
|
|
46
47
|
passport.serializeUser((user, done) => {
|
@@ -66,7 +67,10 @@ const setup: ConfigLoader.SetupFunction = async (app: Express.Application) => {
|
|
66
67
|
|
67
68
|
logout = (req, _res, next) => {
|
68
69
|
req.logout((error) => {
|
69
|
-
|
70
|
+
if (error) {
|
71
|
+
return next(error);
|
72
|
+
}
|
73
|
+
next();
|
70
74
|
});
|
71
75
|
};
|
72
76
|
} else {
|
@@ -50,7 +50,7 @@ const asCallback = async <T>(
|
|
50
50
|
|
51
51
|
export class PinejsSessionStore extends Store {
|
52
52
|
public get = ((sid, callback) => {
|
53
|
-
asCallback(
|
53
|
+
void asCallback(
|
54
54
|
callback,
|
55
55
|
api.session
|
56
56
|
.get({
|
@@ -77,7 +77,7 @@ export class PinejsSessionStore extends Store {
|
|
77
77
|
data,
|
78
78
|
expiry_time: data?.cookie?.expires ?? null,
|
79
79
|
};
|
80
|
-
asCallback(
|
80
|
+
void asCallback(
|
81
81
|
callback,
|
82
82
|
api.session.put({
|
83
83
|
resource: 'session',
|
@@ -91,7 +91,7 @@ export class PinejsSessionStore extends Store {
|
|
91
91
|
}) as Store['set'];
|
92
92
|
|
93
93
|
public destroy = ((sid, callback) => {
|
94
|
-
asCallback(
|
94
|
+
void asCallback(
|
95
95
|
callback,
|
96
96
|
api.session.delete({
|
97
97
|
resource: 'session',
|
@@ -104,7 +104,7 @@ export class PinejsSessionStore extends Store {
|
|
104
104
|
}) as Store['destroy'];
|
105
105
|
|
106
106
|
public all = ((callback) => {
|
107
|
-
asCallback(
|
107
|
+
void asCallback(
|
108
108
|
callback,
|
109
109
|
api.session
|
110
110
|
.get({
|
@@ -124,7 +124,7 @@ export class PinejsSessionStore extends Store {
|
|
124
124
|
}) as Store['all'];
|
125
125
|
|
126
126
|
public clear = ((callback) => {
|
127
|
-
asCallback(
|
127
|
+
void asCallback(
|
128
128
|
callback,
|
129
129
|
// TODO: Use a truncate
|
130
130
|
api.session.delete({
|
@@ -137,7 +137,7 @@ export class PinejsSessionStore extends Store {
|
|
137
137
|
}) as Store['clear'];
|
138
138
|
|
139
139
|
public length = ((callback) => {
|
140
|
-
asCallback(
|
140
|
+
void asCallback(
|
141
141
|
callback,
|
142
142
|
api.session.get({
|
143
143
|
resource: 'session/',
|
@@ -116,7 +116,7 @@ export const getAndCheckBindValues = async (
|
|
116
116
|
[dataType, value] = odataBinds[bindValue];
|
117
117
|
field = { dataType };
|
118
118
|
} else if (typeof bindValue === 'string') {
|
119
|
-
if (!
|
119
|
+
if (!Object.prototype.hasOwnProperty.call(odataBinds, bindValue)) {
|
120
120
|
console.error(
|
121
121
|
`Invalid binding '${bindValue}' for binds: `,
|
122
122
|
odataBinds,
|
@@ -1,11 +1,13 @@
|
|
1
1
|
// Augment express.js with pinejs-specific attributes via declaration merging.
|
2
2
|
|
3
|
-
//
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace, @typescript-eslint/no-unused-vars
|
4
4
|
declare namespace Express {
|
5
5
|
type PineUser = import('./sbvr-utils').User;
|
6
6
|
|
7
|
-
//
|
7
|
+
// Augment Express.User to include the props of our PineUser.
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
8
9
|
interface User extends PineUser {}
|
10
|
+
|
9
11
|
interface Request {
|
10
12
|
user?: User;
|
11
13
|
apiKey?: import('./sbvr-utils').ApiKey;
|
package/src/sbvr-api/hooks.ts
CHANGED
@@ -101,7 +101,7 @@ class SideEffectHook<T extends HookFn> extends Hook<T> {
|
|
101
101
|
|
102
102
|
public registerRollback(fn: RollbackAction): void {
|
103
103
|
if (this.rolledBack) {
|
104
|
-
(async () => {
|
104
|
+
void (async () => {
|
105
105
|
try {
|
106
106
|
await fn();
|
107
107
|
} catch {
|
@@ -140,7 +140,7 @@ export const rollbackRequestHooks = <T extends InstantiatedHooks>(
|
|
140
140
|
if (sideEffectHooks.length === 0) {
|
141
141
|
return;
|
142
142
|
}
|
143
|
-
settleMapSeries(sideEffectHooks, async (hook) => {
|
143
|
+
void settleMapSeries(sideEffectHooks, async (hook) => {
|
144
144
|
await hook.rollback();
|
145
145
|
});
|
146
146
|
};
|
@@ -391,8 +391,7 @@ const getReadOnlyArgs = <T extends keyof Hooks>(
|
|
391
391
|
// If we don't have a tx then read-only/writable is irrelevant
|
392
392
|
return args;
|
393
393
|
}
|
394
|
-
|
395
|
-
readOnlyArgs = { ...args, tx: args.tx.asReadOnly() };
|
394
|
+
const readOnlyArgs: typeof args = { ...args, tx: args.tx.asReadOnly() };
|
396
395
|
if ((args as HookArgs).request != null) {
|
397
396
|
defineApi(modelName, readOnlyArgs as HookArgs);
|
398
397
|
}
|
@@ -1,5 +1,11 @@
|
|
1
|
+
import type {
|
2
|
+
AbstractSqlModel,
|
3
|
+
AbstractSqlTable,
|
4
|
+
} from '@balena/abstract-sql-compiler';
|
5
|
+
|
6
|
+
// Augment express.js with pinejs-specific attributes via declaration merging.
|
1
7
|
declare module '@balena/abstract-sql-compiler' {
|
2
|
-
interface AbstractSqlTable {
|
8
|
+
export interface AbstractSqlTable {
|
3
9
|
fetchProcessingFields?: {
|
4
10
|
[field: string]: NonNullable<SbvrType['fetchProcessing']>;
|
5
11
|
};
|
@@ -9,20 +15,12 @@ declare module '@balena/abstract-sql-compiler' {
|
|
9
15
|
}
|
10
16
|
}
|
11
17
|
|
12
|
-
import type {
|
13
|
-
AbstractSqlModel,
|
14
|
-
AbstractSqlTable,
|
15
|
-
} from '@balena/abstract-sql-compiler';
|
16
18
|
import type { Result, Row } from '../database-layer/db';
|
17
19
|
|
18
20
|
import { sqlNameToODataName } from '@balena/odata-to-abstract-sql';
|
19
21
|
import sbvrTypes, { SbvrType } from '@balena/sbvr-types';
|
20
22
|
import * as _ from 'lodash';
|
21
23
|
import { resolveNavigationResource, resolveSynonym } from './sbvr-utils';
|
22
|
-
import {
|
23
|
-
getWebresourceHandler,
|
24
|
-
isWebResourceField,
|
25
|
-
} from '../webresource-handler';
|
26
24
|
|
27
25
|
const checkForExpansion = async (
|
28
26
|
vocab: string,
|
@@ -148,28 +146,21 @@ export const process = async (
|
|
148
146
|
|
149
147
|
const fetchProcessingFields = getFetchProcessingFields(table);
|
150
148
|
const processedFields = fieldNames.filter((fieldName) =>
|
151
|
-
|
149
|
+
Object.prototype.hasOwnProperty.call(fetchProcessingFields, fieldName),
|
152
150
|
);
|
153
151
|
|
154
152
|
const localFields = getLocalFields(table);
|
155
153
|
// We check that it's not a local field, rather than that it is a foreign key because of the case where the foreign key is on the other resource
|
156
154
|
// and hence not known to this resource
|
157
155
|
const expandableFields = fieldNames.filter(
|
158
|
-
(fieldName) =>
|
156
|
+
(fieldName) =>
|
157
|
+
!Object.prototype.hasOwnProperty.call(localFields, fieldName),
|
159
158
|
);
|
160
159
|
|
161
160
|
const odataIdField = sqlNameToODataName(table.idField);
|
162
|
-
const webResourceHandler = getWebresourceHandler();
|
163
161
|
for (const row of rows) {
|
164
162
|
for (const fieldName of processedFields) {
|
165
163
|
row[fieldName] = fetchProcessingFields[fieldName](row[fieldName]);
|
166
|
-
if (
|
167
|
-
webResourceHandler &&
|
168
|
-
isWebResourceField(fieldName, table) &&
|
169
|
-
row[fieldName]?.href != null
|
170
|
-
) {
|
171
|
-
row[fieldName] = await webResourceHandler.onPreRespond(row[fieldName]);
|
172
|
-
}
|
173
164
|
}
|
174
165
|
if (includeMetadata) {
|
175
166
|
row.__metadata = {
|
@@ -52,7 +52,7 @@ import {
|
|
52
52
|
} from './uri-parser';
|
53
53
|
import memoizeWeak = require('memoizee/weak');
|
54
54
|
|
55
|
-
//
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
56
56
|
const userModel: string = require('./user.sbvr');
|
57
57
|
|
58
58
|
const DEFAULT_ACTOR_BIND = '@__ACTOR_ID';
|
@@ -87,7 +87,7 @@ interface NestedCheckOr<T> {
|
|
87
87
|
interface NestedCheckAnd<T> {
|
88
88
|
and: NestedCheckArray<T>;
|
89
89
|
}
|
90
|
-
|
90
|
+
type NestedCheckArray<T> = Array<NestedCheck<T>>;
|
91
91
|
type NestedCheck<T> =
|
92
92
|
| NestedCheckOr<T>
|
93
93
|
| NestedCheckAnd<T>
|
@@ -175,22 +175,26 @@ const isAnd = <T>(x: any): x is NestedCheckAnd<T> =>
|
|
175
175
|
typeof x === 'object' && 'and' in x;
|
176
176
|
const isOr = <T>(x: any): x is NestedCheckOr<T> =>
|
177
177
|
typeof x === 'object' && 'or' in x;
|
178
|
-
export function nestedCheck<I extends
|
179
|
-
check:
|
178
|
+
export function nestedCheck<I extends string, O>(
|
179
|
+
check: I,
|
180
180
|
stringCallback: (s: string) => O,
|
181
181
|
): O;
|
182
|
-
export function nestedCheck<I extends
|
183
|
-
check:
|
182
|
+
export function nestedCheck<I extends boolean, O>(
|
183
|
+
check: I,
|
184
184
|
stringCallback: (s: string) => O,
|
185
185
|
): boolean;
|
186
|
-
export function nestedCheck<I extends
|
186
|
+
export function nestedCheck<I extends NonNullable<unknown>, O>(
|
187
187
|
check: NestedCheck<I>,
|
188
188
|
stringCallback: (s: string) => O,
|
189
189
|
): Exclude<I, string> | O | MappedNestedCheck<typeof check, I, O>;
|
190
|
-
export function nestedCheck<I extends
|
191
|
-
check: NestedCheck<I
|
190
|
+
export function nestedCheck<I extends object, O>(
|
191
|
+
check: NestedCheck<I> | string | boolean,
|
192
192
|
stringCallback: (s: string) => O,
|
193
|
-
):
|
193
|
+
):
|
194
|
+
| boolean
|
195
|
+
| Exclude<I, string>
|
196
|
+
| O
|
197
|
+
| MappedNestedCheck<Exclude<typeof check, string | boolean>, I, O> {
|
194
198
|
if (typeof check === 'string') {
|
195
199
|
return stringCallback(check);
|
196
200
|
}
|
@@ -228,10 +232,11 @@ export function nestedCheck<I extends {}, O>(
|
|
228
232
|
}
|
229
233
|
const checkType = checkTypes[0];
|
230
234
|
switch (checkType.toUpperCase()) {
|
231
|
-
case 'AND':
|
235
|
+
case 'AND': {
|
232
236
|
const and = (check as NestedCheckAnd<I>)[checkType as 'and'];
|
233
237
|
return nestedCheck(and, stringCallback);
|
234
|
-
|
238
|
+
}
|
239
|
+
case 'OR': {
|
235
240
|
const or = (check as NestedCheckOr<I>)[checkType as 'or'];
|
236
241
|
let results: any[] = [];
|
237
242
|
for (const subcheck of or) {
|
@@ -255,6 +260,7 @@ export function nestedCheck<I extends {}, O>(
|
|
255
260
|
};
|
256
261
|
}
|
257
262
|
return false;
|
263
|
+
}
|
258
264
|
default:
|
259
265
|
throw new Error('Cannot parse required checking logic: ' + checkType);
|
260
266
|
}
|
@@ -425,7 +431,7 @@ const convertToLambda = (filter: AnyObject, identifier: string) => {
|
|
425
431
|
}
|
426
432
|
}
|
427
433
|
|
428
|
-
if (
|
434
|
+
if (Object.prototype.hasOwnProperty.call(object, 'name')) {
|
429
435
|
object.property = { ...object };
|
430
436
|
object.name = identifier;
|
431
437
|
delete object.lambda;
|
@@ -721,7 +727,7 @@ const deepFreezeExceptDefinition = (obj: AnyObject) => {
|
|
721
727
|
// We skip the definition because we know it's a property we've defined that will throw an error in some cases
|
722
728
|
if (
|
723
729
|
prop !== 'definition' &&
|
724
|
-
|
730
|
+
Object.prototype.hasOwnProperty.call(obj, prop) &&
|
725
731
|
obj[prop] !== null &&
|
726
732
|
!['object', 'function'].includes(typeof obj[prop])
|
727
733
|
) {
|
@@ -3,7 +3,9 @@ import type * as Db from '../database-layer/db';
|
|
3
3
|
import type { Model } from '../config-loader/config-loader';
|
4
4
|
import type { AnyObject, RequiredField } from './common-types';
|
5
5
|
|
6
|
+
// Augment the Express typings
|
6
7
|
declare global {
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
7
9
|
namespace Express {
|
8
10
|
export interface Request {
|
9
11
|
tx?: Db.Tx;
|
@@ -38,7 +40,7 @@ import * as asyncMigrator from '../migrator/async';
|
|
38
40
|
import * as syncMigrator from '../migrator/sync';
|
39
41
|
import { generateODataMetadata } from '../odata-metadata/odata-metadata-generator';
|
40
42
|
|
41
|
-
//
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
42
44
|
const devModel = require('./dev.sbvr');
|
43
45
|
import * as permissions from './permissions';
|
44
46
|
import {
|
@@ -249,13 +251,14 @@ const prettifyConstraintError = (
|
|
249
251
|
err.message,
|
250
252
|
);
|
251
253
|
break;
|
252
|
-
case 'postgres':
|
254
|
+
case 'postgres': {
|
253
255
|
const resourceName = resolveSynonym(request);
|
254
256
|
const abstractSqlModel = getFinalAbstractSqlModel(request);
|
255
257
|
matches = new RegExp(
|
256
258
|
'"' + abstractSqlModel.tables[resourceName].name + '_(.*?)_key"',
|
257
259
|
).exec(err.message);
|
258
260
|
break;
|
261
|
+
}
|
259
262
|
}
|
260
263
|
// We know it's the right error type, so if matches exists just throw a generic error message, since we have failed to get the info for a more specific one.
|
261
264
|
if (matches == null) {
|
@@ -282,7 +285,7 @@ const prettifyConstraintError = (
|
|
282
285
|
err.message,
|
283
286
|
);
|
284
287
|
break;
|
285
|
-
case 'postgres':
|
288
|
+
case 'postgres': {
|
286
289
|
const resourceName = resolveSynonym(request);
|
287
290
|
const abstractSqlModel = getFinalAbstractSqlModel(request);
|
288
291
|
const tableName = abstractSqlModel.tables[resourceName].name;
|
@@ -301,6 +304,7 @@ const prettifyConstraintError = (
|
|
301
304
|
).exec(err.message);
|
302
305
|
}
|
303
306
|
break;
|
307
|
+
}
|
304
308
|
}
|
305
309
|
// We know it's the right error type, so if no matches exists just throw a generic error message,
|
306
310
|
// since we have failed to get the info for a more specific one.
|
@@ -983,7 +987,7 @@ export class PinejsClient extends PinejsClientCore<PinejsClient> {
|
|
983
987
|
req?: permissions.PermissionReq;
|
984
988
|
custom?: AnyObject;
|
985
989
|
}) {
|
986
|
-
return (await runURI(method, url, body, tx, req, custom)) as
|
990
|
+
return (await runURI(method, url, body, tx, req, custom)) as object;
|
987
991
|
}
|
988
992
|
}
|
989
993
|
|
@@ -416,7 +416,7 @@ export const translateUri = <
|
|
416
416
|
request = { ...request };
|
417
417
|
request.values = new Proxy(request.values, {
|
418
418
|
set: (obj: ODataRequest['values'], prop: string, value) => {
|
419
|
-
if (!
|
419
|
+
if (!Object.prototype.hasOwnProperty.call(obj, prop)) {
|
420
420
|
sbvrUtils.api[request.vocabulary].logger.warn(
|
421
421
|
`Assigning a new request.values property '${prop}' however it will be ignored`,
|
422
422
|
);
|