@balena/pinejs 17.3.4-build-update-deps-04a59f892aeac34c8e1c44e9e9425e4294c65d92-1 → 17.3.4-build-rollback-sbvr-types-911495b41b7b0bd32273478fe33230fc5e20d014-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.pinejs-cache.json +1 -1
  2. package/.versionbot/CHANGELOG.yml +5 -489
  3. package/CHANGELOG.md +1 -205
  4. package/out/bin/utils.js.map +1 -1
  5. package/out/database-layer/db.js +4 -8
  6. package/out/database-layer/db.js.map +1 -1
  7. package/out/express-emulator/express.js +5 -2
  8. package/out/express-emulator/express.js.map +1 -1
  9. package/out/passport-pinejs/mount-login-router.js +3 -1
  10. package/out/passport-pinejs/mount-login-router.js.map +1 -1
  11. package/out/passport-pinejs/passport-pinejs.js +8 -11
  12. package/out/passport-pinejs/passport-pinejs.js.map +1 -1
  13. package/out/pinejs-session-store/pinejs-session-store.js.map +1 -1
  14. package/out/sbvr-api/abstract-sql.js.map +1 -1
  15. package/out/sbvr-api/hooks.js +1 -3
  16. package/out/sbvr-api/hooks.js.map +1 -1
  17. package/out/sbvr-api/permissions.js +1 -3
  18. package/out/sbvr-api/permissions.js.map +1 -1
  19. package/out/sbvr-api/sbvr-utils.js +2 -4
  20. package/out/sbvr-api/sbvr-utils.js.map +1 -1
  21. package/out/sbvr-api/translations.js +1 -1
  22. package/out/sbvr-api/translations.js.map +1 -1
  23. package/out/sbvr-api/uri-parser.js +2 -2
  24. package/out/sbvr-api/uri-parser.js.map +1 -1
  25. package/out/webresource-handler/index.js +1 -2
  26. package/out/webresource-handler/index.js.map +1 -1
  27. package/package.json +20 -20
  28. package/src/bin/utils.ts +1 -1
  29. package/src/database-layer/db.ts +9 -13
  30. package/src/express-emulator/express.js +5 -2
  31. package/src/passport-pinejs/mount-login-router.ts +5 -1
  32. package/src/passport-pinejs/passport-pinejs.ts +2 -4
  33. package/src/pinejs-session-store/pinejs-session-store.ts +1 -1
  34. package/src/sbvr-api/abstract-sql.ts +1 -1
  35. package/src/sbvr-api/hooks.ts +3 -5
  36. package/src/sbvr-api/permissions.ts +10 -5
  37. package/src/sbvr-api/sbvr-utils.ts +6 -8
  38. package/src/sbvr-api/translations.ts +1 -1
  39. package/src/sbvr-api/uri-parser.ts +2 -2
  40. package/src/webresource-handler/index.ts +1 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@balena/pinejs",
3
- "version": "17.3.4-build-update-deps-04a59f892aeac34c8e1c44e9e9425e4294c65d92-1",
3
+ "version": "17.3.4-build-rollback-sbvr-types-911495b41b7b0bd32273478fe33230fc5e20d014-1",
4
4
  "main": "out/server-glue/module",
5
5
  "type": "commonjs",
6
6
  "repository": "git@github.com:balena-io/pinejs.git",
@@ -23,30 +23,30 @@
23
23
  "test:compose": "trap 'docker compose -f docker-compose.npm-test.yml down ; echo Stopped ; exit 0' INT; docker compose -f docker-compose.npm-test.yml up -d && sleep 2 && DATABASE_URL=postgres://docker:docker@localhost:5431/postgres PINEJS_WEBRESOURCE_MAXFILESIZE=1000000000 S3_ENDPOINT=http://localhost:43680 S3_ACCESS_KEY=USERNAME S3_SECRET_KEY=PASSWORD S3_STORAGE_ADAPTER_BUCKET=balena-pine-web-resources S3_REGION=us-east-1 npm run mocha",
24
24
  "test:generated-types": "npm run generate-types && git diff --exit-code ./src/sbvr-api/user.ts ./src/migrator/migrations.ts ./src/sbvr-api/dev.ts",
25
25
  "mocha": "TS_NODE_FILES=true mocha",
26
- "lint-fix": "balena-lint -t tsconfig.dev.json -e js -e ts --fix src test build typings Gruntfile.ts",
26
+ "prettify": "balena-lint -t tsconfig.dev.json -e js -e ts --fix src test build typings Gruntfile.ts",
27
27
  "generate-types": "node ./bin/sbvr-compiler.js generate-types ./src/sbvr-api/user.sbvr ./src/sbvr-api/user.ts && node ./bin/sbvr-compiler.js generate-types ./src/migrator/migrations.sbvr ./src/migrator/migrations.ts && node ./bin/sbvr-compiler.js generate-types ./src/sbvr-api/dev.sbvr ./src/sbvr-api/dev.ts && balena-lint -t tsconfig.dev.json --fix ./src/sbvr-api/user.ts ./src/migrator/migrations.ts ./src/sbvr-api/dev.ts"
28
28
  },
29
29
  "dependencies": {
30
30
  "@balena/abstract-sql-compiler": "^9.2.0",
31
- "@balena/abstract-sql-to-typescript": "^3.3.1",
31
+ "@balena/abstract-sql-to-typescript": "^3.2.1",
32
32
  "@balena/env-parsing": "^1.1.12",
33
33
  "@balena/lf-to-abstract-sql": "^5.0.2",
34
34
  "@balena/odata-parser": "^3.0.8",
35
35
  "@balena/odata-to-abstract-sql": "^6.2.7",
36
- "@balena/sbvr-parser": "^1.4.5",
37
- "@balena/sbvr-types": "^8.0.0",
36
+ "@balena/sbvr-parser": "^1.4.4",
37
+ "@balena/sbvr-types": "^7.1.3",
38
38
  "@types/body-parser": "^1.19.5",
39
39
  "@types/compression": "^1.7.5",
40
40
  "@types/cookie-parser": "^1.4.7",
41
41
  "@types/deep-freeze": "^0.1.5",
42
42
  "@types/express": "^4.17.21",
43
43
  "@types/express-session": "^1.18.0",
44
- "@types/lodash": "^4.17.7",
44
+ "@types/lodash": "^4.17.5",
45
45
  "@types/memoizee": "^0.4.11",
46
46
  "@types/method-override": "^0.0.35",
47
47
  "@types/multer": "^1.4.11",
48
48
  "@types/mysql": "^2.15.26",
49
- "@types/node": "^20.14.11",
49
+ "@types/node": "^20.14.5",
50
50
  "@types/passport": "^1.0.16",
51
51
  "@types/passport-local": "^1.0.38",
52
52
  "@types/passport-strategy": "^0.2.38",
@@ -60,18 +60,18 @@
60
60
  "express-session": "^1.18.0",
61
61
  "lodash": "^4.17.21",
62
62
  "memoizee": "^0.4.17",
63
- "pinejs-client-core": "^6.15.10",
63
+ "pinejs-client-core": "^6.15.1",
64
64
  "randomstring": "^1.3.0",
65
65
  "typed-error": "^3.2.2"
66
66
  },
67
67
  "devDependencies": {
68
- "@balena/lint": "^8.2.7",
68
+ "@balena/lint": "^8.0.2",
69
69
  "@faker-js/faker": "^8.4.1",
70
70
  "@types/busboy": "^1.5.4",
71
71
  "@types/chai": "^4.3.16",
72
72
  "@types/chai-as-promised": "^7.1.8",
73
73
  "@types/grunt": "^0.4.31",
74
- "@types/mocha": "^10.0.7",
74
+ "@types/mocha": "^10.0.6",
75
75
  "@types/on-finished": "^2.3.4",
76
76
  "@types/request": "^2.48.12",
77
77
  "@types/supertest": "^6.0.2",
@@ -81,7 +81,7 @@
81
81
  "chai": "^4.4.1",
82
82
  "grunt": "^1.6.1",
83
83
  "grunt-check-dependencies": "^1.0.0",
84
- "grunt-cli": "^1.5.0",
84
+ "grunt-cli": "^1.4.3",
85
85
  "grunt-contrib-clean": "^2.0.1",
86
86
  "grunt-contrib-concat": "^2.1.0",
87
87
  "grunt-contrib-copy": "^1.0.0",
@@ -90,12 +90,12 @@
90
90
  "grunt-text-replace": "^0.4.0",
91
91
  "grunt-ts": "^6.0.0-beta.22",
92
92
  "grunt-webpack": "^6.0.0",
93
- "husky": "^9.1.1",
93
+ "husky": "^9.0.11",
94
94
  "lint-staged": "^15.2.7",
95
95
  "load-grunt-tasks": "^5.1.0",
96
- "mocha": "^10.7.0",
96
+ "mocha": "^10.4.0",
97
97
  "on-finished": "^2.4.1",
98
- "pinejs-client-supertest": "^2.1.1",
98
+ "pinejs-client-supertest": "^2.0.4",
99
99
  "raw-loader": "^4.0.2",
100
100
  "request": "^2.88.2",
101
101
  "require-npm4-to-publish": "^1.0.0",
@@ -103,14 +103,14 @@
103
103
  "terser-webpack-plugin": "^5.3.10",
104
104
  "ts-loader": "^9.5.1",
105
105
  "ts-node": "^10.9.2",
106
- "typescript": "^5.5.3",
107
- "webpack": "^5.93.0",
106
+ "typescript": "^5.5.2",
107
+ "webpack": "^5.92.0",
108
108
  "webpack-dev-server": "^4.15.2"
109
109
  },
110
110
  "optionalDependencies": {
111
- "@aws-sdk/client-s3": "^3.614.0",
112
- "@aws-sdk/lib-storage": "^3.616.0",
113
- "@aws-sdk/s3-request-presigner": "^3.616.0",
111
+ "@aws-sdk/client-s3": "^3.598.0",
112
+ "@aws-sdk/lib-storage": "^3.598.0",
113
+ "@aws-sdk/s3-request-presigner": "^3.598.0",
114
114
  "bcrypt": "^5.1.1",
115
115
  "body-parser": "^1.20.2",
116
116
  "compression": "^1.7.4",
@@ -146,6 +146,6 @@
146
146
  "recursive": true
147
147
  },
148
148
  "versionist": {
149
- "publishedAt": "2024-07-30T11:31:08.392Z"
149
+ "publishedAt": "2024-07-30T11:55:20.555Z"
150
150
  }
151
151
  }
package/src/bin/utils.ts CHANGED
@@ -92,7 +92,7 @@ export const getAbstractSqlModelFromFile = (
92
92
  }
93
93
  const configModel = getConfigModel(fileContents, modelName);
94
94
  if ('abstractSql' in configModel && configModel.abstractSql != null) {
95
- return configModel.abstractSql;
95
+ return configModel.abstractSql as AbstractSqlModel;
96
96
  } else if ('modelText' in configModel && configModel.modelText != null) {
97
97
  seModel = configModel.modelText;
98
98
  } else if ('modelFile' in configModel && configModel.modelFile != null) {
@@ -423,7 +423,7 @@ export abstract class Tx {
423
423
  /* eslint-disable @typescript-eslint/no-unused-vars */
424
424
  _namespaceKey: string,
425
425
  _key: number,
426
- _blocking = true,
426
+ _blocking: boolean = true,
427
427
  /* eslint-enable @typescript-eslint/no-unused-vars */
428
428
  ): Promise<boolean> {
429
429
  throw new Error(
@@ -663,7 +663,7 @@ if (maybePg != null) {
663
663
  public override async getTxLevelLock(
664
664
  namespaceKey: string,
665
665
  key: number,
666
- blocking = true,
666
+ blocking: boolean = true,
667
667
  ) {
668
668
  validateTransactionLockParameter(key, 'key');
669
669
  const namespaceId = transactionLockNamespaceMap[namespaceKey];
@@ -693,7 +693,7 @@ if (maybePg != null) {
693
693
  }
694
694
  }
695
695
 
696
- public async tableList(extraWhereClause = '') {
696
+ public async tableList(extraWhereClause: string = '') {
697
697
  if (extraWhereClause !== '') {
698
698
  extraWhereClause = 'WHERE ' + extraWhereClause;
699
699
  }
@@ -811,7 +811,7 @@ if (maybeMysql != null) {
811
811
  await promise;
812
812
  }
813
813
 
814
- public async tableList(extraWhereClause = '') {
814
+ public async tableList(extraWhereClause: string = '') {
815
815
  if (extraWhereClause !== '') {
816
816
  extraWhereClause = ' WHERE ' + extraWhereClause;
817
817
  }
@@ -834,18 +834,14 @@ if (maybeMysql != null) {
834
834
  executeSql: atomicExecuteSql,
835
835
  transaction: createTransaction(async (stackTraceErr, timeoutMS) => {
836
836
  const client = await getConnectionAsync();
837
- const close = () => {
838
- client.release();
839
- };
837
+ const close = () => client.release();
840
838
  const tx = new MySqlTx(client, close, false, stackTraceErr, timeoutMS);
841
839
  void tx.executeSql('START TRANSACTION;');
842
840
  return tx;
843
841
  }),
844
842
  readTransaction: createTransaction(async (stackTraceErr, timeoutMS) => {
845
843
  const client = await getConnectionAsync();
846
- const close = () => {
847
- client.release();
848
- };
844
+ const close = () => client.release();
849
845
  const tx = new MySqlTx(client, close, false, stackTraceErr, timeoutMS);
850
846
  void tx.executeSql('START TRANSACTION READ ONLY;');
851
847
  return tx.asReadOnly();
@@ -930,14 +926,14 @@ if (typeof window !== 'undefined' && window.openDatabase != null) {
930
926
  }
931
927
 
932
928
  protected async _rollback(): Promise<void> {
933
- await this.tx.rollback();
929
+ return await this.tx.rollback();
934
930
  }
935
931
 
936
932
  protected async _commit() {
937
933
  this.tx.commit();
938
934
  }
939
935
 
940
- public async tableList(extraWhereClause = '') {
936
+ public async tableList(extraWhereClause: string = '') {
941
937
  if (extraWhereClause !== '') {
942
938
  extraWhereClause = ' AND ' + extraWhereClause;
943
939
  }
@@ -991,7 +987,7 @@ if (typeof window !== 'undefined' && window.openDatabase != null) {
991
987
  }
992
988
 
993
989
  public async rollback(): Promise<void> {
994
- await new Promise<void>((resolve) => {
990
+ return await new Promise((resolve) => {
995
991
  const successCallback: SQLStatementCallback = () => {
996
992
  resolve();
997
993
  throw new Error('Rollback');
@@ -80,7 +80,7 @@ const app = (function () {
80
80
  },
81
81
  };
82
82
  console.log(method, uri, body);
83
- if (uri.endsWith('/')) {
83
+ if (uri.slice(-1) === '/') {
84
84
  uri = uri.slice(0, uri.length - 1);
85
85
  }
86
86
  uri = uri.toLowerCase();
@@ -142,7 +142,10 @@ const app = (function () {
142
142
  const checkMethodHandlers = () => {
143
143
  i++;
144
144
  if (i < methodHandlers.length) {
145
- if (uri.startsWith(methodHandlers[i].match)) {
145
+ if (
146
+ uri.slice(0, methodHandlers[i].match.length) ===
147
+ methodHandlers[i].match
148
+ ) {
146
149
  j = -1;
147
150
  // Reset params that may have been added on previous routes that failed in middleware
148
151
  req.params = {};
@@ -12,7 +12,11 @@ export const mountLoginRouter = async (
12
12
  configLoader.loadConfig(PinejsSessionStore.config),
13
13
  ]);
14
14
 
15
- if (typeof process === 'undefined' || !process?.env.DISABLE_DEFAULT_AUTH) {
15
+ if (
16
+ typeof process === 'undefined' ||
17
+ process == null ||
18
+ !process.env.DISABLE_DEFAULT_AUTH
19
+ ) {
16
20
  expressApp.post(
17
21
  '/login',
18
22
  passportPinejs.login((err, user, req, res) => {
@@ -68,8 +68,7 @@ const setup: ConfigLoader.SetupFunction = (app: Express.Application) => {
68
68
  logout = (req, _res, next) => {
69
69
  req.logout((error) => {
70
70
  if (error) {
71
- next(error);
72
- return;
71
+ return next(error);
73
72
  }
74
73
  next();
75
74
  });
@@ -84,7 +83,7 @@ const setup: ConfigLoader.SetupFunction = (app: Express.Application) => {
84
83
  next();
85
84
  });
86
85
 
87
- login = (fn) => (req, res, next) => {
86
+ login = (fn) => (req, res, next) =>
88
87
  checkPassword(req.body.username, req.body.password, (err, user) => {
89
88
  if (user) {
90
89
  loggedIn = true;
@@ -92,7 +91,6 @@ const setup: ConfigLoader.SetupFunction = (app: Express.Application) => {
92
91
  }
93
92
  fn(err, user, req, res, next);
94
93
  });
95
- };
96
94
 
97
95
  logout = (req, _res, next) => {
98
96
  delete req.user;
@@ -153,7 +153,7 @@ export class PinejsSessionStore extends Store {
153
153
  },
154
154
  },
155
155
  },
156
- }),
156
+ }) as Promise<number>,
157
157
  );
158
158
  }) as Store['length'];
159
159
 
@@ -77,7 +77,7 @@ export const getAndCheckBindValues = async (
77
77
  const sqlModelTables = sbvrUtils.getAbstractSqlModel(request).tables;
78
78
  return await Promise.all(
79
79
  bindings.map(async (binding) => {
80
- let fieldName = '';
80
+ let fieldName: string = '';
81
81
  let field: { dataType: string };
82
82
  let value: any;
83
83
  if (binding[0] === 'Bind') {
@@ -101,7 +101,7 @@ class Hook<T extends HookFn> {
101
101
 
102
102
  class SideEffectHook<T extends HookFn> extends Hook<T> {
103
103
  private rollbackFns: RollbackAction[] = [];
104
- private rolledBack = false;
104
+ private rolledBack: boolean = false;
105
105
 
106
106
  public registerRollback(fn: RollbackAction): void {
107
107
  if (this.rolledBack) {
@@ -243,9 +243,7 @@ export const getHooks = (
243
243
  ),
244
244
  );
245
245
  };
246
- getHooks.clear = () => {
247
- getMethodHooks.clear();
248
- };
246
+ getHooks.clear = () => getMethodHooks.clear();
249
247
 
250
248
  interface VocabHooks {
251
249
  [resourceName: string]: HookBlueprints;
@@ -341,7 +339,7 @@ export const addHook = <Vocab extends string>(
341
339
  const hook = hooks[hookType];
342
340
  resourceHooks[hookType] ??= [];
343
341
  if (hook != null) {
344
- resourceHooks[hookType].push(hook);
342
+ resourceHooks[hookType]!.push(hook);
345
343
  }
346
344
  }
347
345
 
@@ -334,7 +334,12 @@ const getPermissionsLookup = env.createCache(
334
334
  permissionsLookup[target] = true;
335
335
  } else if (permissionsLookup[target] !== true) {
336
336
  permissionsLookup[target] ??= [];
337
- permissionsLookup[target].push(condition);
337
+ (
338
+ permissionsLookup[target] as Exclude<
339
+ PermissionLookup[typeof target],
340
+ true
341
+ >
342
+ ).push(condition);
338
343
  }
339
344
  }
340
345
  // Ensure there are no duplicate conditions as applying both would be wasteful
@@ -941,7 +946,7 @@ const rewriteRelationships = (
941
946
  );
942
947
 
943
948
  const newRelationships = _.cloneDeep(relationships);
944
- _.forOwn(newRelationships, (value, name) => {
949
+ _.forOwn(newRelationships, (value, name) =>
945
950
  rewriteRelationship(
946
951
  value,
947
952
  name,
@@ -949,8 +954,8 @@ const rewriteRelationships = (
949
954
  permissionsLookup,
950
955
  vocabulary,
951
956
  odata2AbstractSQL,
952
- );
953
- });
957
+ ),
958
+ );
954
959
 
955
960
  return newRelationships;
956
961
  };
@@ -1635,7 +1640,7 @@ const getReqPermissions = async (
1635
1640
  if (req.user?.permissions != null) {
1636
1641
  addActorPermissions(req.user.actor, req.user.permissions);
1637
1642
  } else if (req.apiKey?.permissions != null) {
1638
- addActorPermissions(req.apiKey.actor, req.apiKey.permissions);
1643
+ addActorPermissions(req.apiKey.actor!, req.apiKey.permissions);
1639
1644
  }
1640
1645
 
1641
1646
  return getPermissionsLookup(actorPermissions, guestPermissions);
@@ -209,7 +209,7 @@ const memoizedResolveNavigationResource = memoizeWeak(
209
209
  const mapping = _.get(
210
210
  abstractSqlModel.relationships[resolvedResourceName],
211
211
  navigation,
212
- );
212
+ ) as undefined | AbstractSQLCompiler.RelationshipMapping;
213
213
  if (mapping == null) {
214
214
  throw new Error(
215
215
  `Cannot navigate from '${resourceName}' to '${navigationName}'`,
@@ -701,7 +701,7 @@ export const executeModels = async (
701
701
  compiledModels.map(async (model: CompiledModel) => {
702
702
  const updateModel = async (modelType: keyof CompiledModel) => {
703
703
  if (model[modelType] == null) {
704
- await api.dev.delete({
704
+ return await api.dev.delete({
705
705
  resource: 'model',
706
706
  passthrough: {
707
707
  tx,
@@ -714,7 +714,6 @@ export const executeModels = async (
714
714
  },
715
715
  },
716
716
  });
717
- return;
718
717
  }
719
718
  const result = await api.dev.get({
720
719
  resource: 'model',
@@ -1055,7 +1054,7 @@ export class PinejsClient<
1055
1054
  url: NonNullable<Params<T>['url']>;
1056
1055
  } & Params<T>,
1057
1056
  ): Promise<AnyObject>;
1058
- public post(params: Params): Promise<AnyObject> {
1057
+ public post(params: Params<AnyResource>): Promise<AnyObject> {
1059
1058
  return super.post(params as Parameters<PinejsClient['post']>[0]);
1060
1059
  }
1061
1060
  }
@@ -1459,8 +1458,7 @@ export const getApiRoot = (req: Express.Request): string | undefined => {
1459
1458
  export const handleODataRequest: Express.Handler = async (req, res, next) => {
1460
1459
  const apiRoot = getApiRoot(req);
1461
1460
  if (apiRoot == null || models[apiRoot] == null) {
1462
- next('route');
1463
- return;
1461
+ return next('route');
1464
1462
  }
1465
1463
 
1466
1464
  try {
@@ -1523,7 +1521,7 @@ export const handleHttpErrors = (
1523
1521
  return false;
1524
1522
  };
1525
1523
  const handleResponse = (res: Express.Response, response: Response): void => {
1526
- const { body, headers, statusCode } = response;
1524
+ const { body, headers, statusCode } = response as Response;
1527
1525
  res.set(headers);
1528
1526
  res.status(statusCode);
1529
1527
  if (!body) {
@@ -1753,7 +1751,7 @@ const runQuery = async (
1753
1751
  tx: Db.Tx,
1754
1752
  request: uriParser.ODataRequest,
1755
1753
  queryIndex?: number,
1756
- addReturning = false,
1754
+ addReturning: boolean = false,
1757
1755
  ): Promise<Db.Result> => {
1758
1756
  const { vocabulary } = request;
1759
1757
  let { sqlQuery } = request;
@@ -208,7 +208,7 @@ export const translateAbstractSqlModel = (
208
208
  const { $toResource, ...definition } = translationDefinition;
209
209
  const hasToResource = typeof $toResource === 'string';
210
210
  if (hasToResource) {
211
- resourceRenames[key] = $toResource;
211
+ resourceRenames[key] = `${$toResource}`;
212
212
  }
213
213
  const toResource = hasToResource ? $toResource : `${key}$${toVersion}`;
214
214
  // TODO: Should this use the toAbstractSqlModel?
@@ -282,7 +282,7 @@ export function parseOData(
282
282
  // We sort the CS set once, we must assure that requests which reference
283
283
  // other requests in the changeset are placed last. Once they are sorted
284
284
  // Map will guarantee retrival of results in insertion order
285
- const sortedCS = _.sortBy(b.changeSet, (el) => !el.url.startsWith('/'));
285
+ const sortedCS = _.sortBy(b.changeSet, (el) => el.url[0] !== '/');
286
286
  const csReferences = new Map<
287
287
  ParsedODataRequest['id'],
288
288
  ParsedODataRequest
@@ -338,7 +338,7 @@ const parseODataChangeset = (
338
338
  let apiRoot: string;
339
339
  let url;
340
340
 
341
- if (b.url.startsWith('/')) {
341
+ if (b.url[0] === '/') {
342
342
  ({ url, apiRoot } = splitApiRoot(b.url));
343
343
  odata = memoizedParseOdata(url);
344
344
  defer = false;
@@ -116,8 +116,7 @@ export const getUploaderMiddlware = (
116
116
  ): Express.RequestHandler => {
117
117
  return (req, res, next) => {
118
118
  if (!req.is('multipart')) {
119
- next();
120
- return;
119
+ return next();
121
120
  }
122
121
  const uploadedFilePaths: string[] = [];
123
122
  const completeUploads: Array<Promise<void>> = [];