prostgles-server 4.2.642 → 4.2.643

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 (86) hide show
  1. package/debug/caught-request-fix-build.log +4 -0
  2. package/debug/caught-request-fix-test-build.log +0 -0
  3. package/debug/caught-request-subscription-failure.log +603 -0
  4. package/debug/caught-validation-build.log +4 -0
  5. package/debug/caught-validation-fix-build.log +4 -0
  6. package/debug/caught-validation-fix-test-build.log +0 -0
  7. package/debug/caught-validation-test-build.log +0 -0
  8. package/debug/client-db-tx-build.log +4 -0
  9. package/debug/client-db-tx-test-server.log +3248 -0
  10. package/debug/client-db-tx-tests-build.log +0 -0
  11. package/debug/client-handler-shape-build.log +4 -0
  12. package/debug/client-handler-shape-test-server.log +544 -0
  13. package/debug/client-handler-shape-tests-build.log +0 -0
  14. package/debug/column-definitions-test-server.log +152 -164
  15. package/debug/function-client-db-tx-build.log +4 -0
  16. package/debug/function-client-db-tx-tests-build.log +0 -0
  17. package/debug/schema-types-focused-strict-check.log +0 -0
  18. package/debug/schema-types-strict-check.log +38 -0
  19. package/debug/schema-types-tests-build.log +0 -0
  20. package/debug/security-review-baseline-tests.log +3250 -0
  21. package/debug/security-review-build.log +4 -0
  22. package/debug/security-review-checkfilter-repro.log +545 -0
  23. package/debug/security-review-clientSchemaTypes.spec.ts.backup +553 -0
  24. package/debug/security-review-repro-build.log +0 -0
  25. package/debug/security-review-repro.spec.ts +591 -0
  26. package/debug/security-review-restore-build.log +0 -0
  27. package/debug/security-review-server-tests.log +3254 -0
  28. package/debug/security-review-test-build.log +0 -0
  29. package/debug/test-check-eslint.log +6 -0
  30. package/debug/test-check-lint-baseline.json +1 -0
  31. package/debug/test-check-npm-test.log +789 -0
  32. package/debug/test-check-types.log +8 -0
  33. package/debug/test-config-npm-test.log +223 -0
  34. package/debug/test-config-strict-null-check.log +50 -0
  35. package/debug/test-config-typecheck.log +8 -0
  36. package/debug/tryRunP-test-quick.log +78 -0
  37. package/debug/tryRunP-typecheck.log +42 -0
  38. package/dist/Auth/AuthTypes.d.ts +3 -3
  39. package/dist/Auth/AuthTypes.d.ts.map +1 -1
  40. package/dist/Auth/AuthTypes.js.map +1 -1
  41. package/dist/DboBuilder/DboBuilder.d.ts.map +1 -1
  42. package/dist/DboBuilder/DboBuilder.js +4 -2
  43. package/dist/DboBuilder/DboBuilder.js.map +1 -1
  44. package/dist/DboBuilder/TableHandler/TableHandler.d.ts +1 -1
  45. package/dist/DboBuilder/dboBuilderUtils.d.ts +1 -0
  46. package/dist/DboBuilder/dboBuilderUtils.d.ts.map +1 -1
  47. package/dist/DboBuilder/dboBuilderUtils.js +2 -1
  48. package/dist/DboBuilder/dboBuilderUtils.js.map +1 -1
  49. package/dist/PublishParser/PublishParser.d.ts.map +1 -1
  50. package/dist/PublishParser/PublishParser.js +2 -1
  51. package/dist/PublishParser/PublishParser.js.map +1 -1
  52. package/dist/PublishParser/defineServerFunction.d.ts +2 -0
  53. package/dist/PublishParser/defineServerFunction.d.ts.map +1 -1
  54. package/dist/PublishParser/defineServerFunction.js.map +1 -1
  55. package/dist/PublishParser/getPublishedTableNames.d.ts.map +1 -1
  56. package/dist/PublishParser/getPublishedTableNames.js +2 -1
  57. package/dist/PublishParser/getPublishedTableNames.js.map +1 -1
  58. package/dist/PublishParser/publishTypesAndUtils.d.ts +1 -1
  59. package/dist/PublishParser/publishTypesAndUtils.d.ts.map +1 -1
  60. package/dist/StorageClient/StorageClientTypes.d.ts +5 -4
  61. package/dist/StorageClient/StorageClientTypes.d.ts.map +1 -1
  62. package/dist/WebsocketAPI/getClientHandlers.d.ts +5 -0
  63. package/dist/WebsocketAPI/getClientHandlers.d.ts.map +1 -1
  64. package/dist/WebsocketAPI/getClientHandlers.js +33 -14
  65. package/dist/WebsocketAPI/getClientHandlers.js.map +1 -1
  66. package/dist/index.d.ts +1 -0
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +3 -1
  69. package/dist/index.js.map +1 -1
  70. package/dist/runClientRequest.d.ts +2 -1
  71. package/dist/runClientRequest.d.ts.map +1 -1
  72. package/dist/runClientRequest.js +4 -2
  73. package/dist/runClientRequest.js.map +1 -1
  74. package/eslint.config.mjs +21 -1
  75. package/lib/Auth/AuthTypes.ts +3 -2
  76. package/lib/DboBuilder/DboBuilder.ts +7 -2
  77. package/lib/DboBuilder/dboBuilderUtils.ts +2 -0
  78. package/lib/PublishParser/PublishParser.ts +2 -1
  79. package/lib/PublishParser/defineServerFunction.ts +3 -5
  80. package/lib/PublishParser/getPublishedTableNames.ts +2 -1
  81. package/lib/PublishParser/publishTypesAndUtils.ts +1 -1
  82. package/lib/StorageClient/StorageClientTypes.ts +5 -4
  83. package/lib/WebsocketAPI/getClientHandlers.ts +63 -29
  84. package/lib/index.ts +3 -3
  85. package/lib/runClientRequest.ts +5 -1
  86. package/package.json +5 -3
package/eslint.config.mjs CHANGED
@@ -3,7 +3,18 @@ import tseslint from "typescript-eslint";
3
3
 
4
4
  export default tseslint.config(
5
5
  {
6
- ignores: ["node_modules", "dist", "debug", "examples", "**/*.d.ts", "tests", "docs"],
6
+ ignores: [
7
+ "**/node_modules",
8
+ "**/dist",
9
+ "**/debug",
10
+ "examples",
11
+ "**/*.d.ts",
12
+ "docs",
13
+ "tests/**/*.js",
14
+ "tests/DBGeneratedSchema.ts",
15
+ "tests/config_test",
16
+ "tests/server/DEMO_SERVER.ts",
17
+ ],
7
18
  },
8
19
  eslint.configs.recommended,
9
20
  tseslint.configs.recommendedTypeChecked,
@@ -58,4 +69,13 @@ export default tseslint.config(
58
69
  ],
59
70
  },
60
71
  },
72
+ {
73
+ files: ["tests/**/*.ts"],
74
+ languageOptions: {
75
+ parserOptions: {
76
+ projectService: false,
77
+ project: ["./tests/server/tsconfig.json", "./tests/client/tsconfig.json"],
78
+ },
79
+ },
80
+ },
61
81
  );
@@ -21,6 +21,7 @@ import type {
21
21
  FullFilter,
22
22
  IdentityProvider,
23
23
  LocalLoginMode,
24
+ MaybePromise,
24
25
  UserLike,
25
26
  } from "prostgles-types";
26
27
  import type { DBOFullyTyped } from "../DBSchemaBuilder/DBSchemaBuilder";
@@ -210,7 +211,7 @@ export type LoginWithOAuthConfig<S> = {
210
211
  req: ExpressReq;
211
212
  res: ExpressRes;
212
213
  clientInfo: LoginClientInfo;
213
- }) => Promise<
214
+ }) => MaybePromise<
214
215
  AuthResponse.OAuthRegisterSuccess | AuthResponse.OAuthRegisterFailure | AuthResponse.AuthFailure
215
216
  >;
216
217
 
@@ -225,7 +226,7 @@ export type LoginWithOAuthConfig<S> = {
225
226
  req: ExpressReq;
226
227
  res: ExpressRes;
227
228
  clientInfo: LoginClientInfo;
228
- }) => void | Promise<void>;
229
+ }) => void | MaybePromise<void>;
229
230
  };
230
231
 
231
232
  export type SessionUser<
@@ -29,6 +29,7 @@ import {
29
29
  getCanExecute,
30
30
  getConstraints,
31
31
  getSerializedClientErrorFromPGError,
32
+ TX_KEY,
32
33
  } from "./dboBuilderUtils";
33
34
  import { prepareShortestJoinPaths } from "./joins/prepareShortestJoinPaths";
34
35
  import { cacheDBTypes, runSQL } from "./runSql/runSQL";
@@ -304,10 +305,14 @@ export class DboBuilder {
304
305
  });
305
306
 
306
307
  if (this.prostgles.opts.transactions) {
307
- const txKey = "tx";
308
+ if (this.dboMap.has(TX_KEY)) {
309
+ throw new Error(
310
+ `Transaction key ${JSON.stringify(TX_KEY)} clashes with an existing table or view name`,
311
+ );
312
+ }
308
313
 
309
314
  //@ts-ignore
310
- this.dbo[txKey] = <R, TH extends DbTxTableHandlers & Pick<DBHandlerServer, "sql">>(
315
+ this.dbo[TX_KEY] = <R, TH extends DbTxTableHandlers & Pick<DBHandlerServer, "sql">>(
311
316
  cb: TxCB<Promise<R>, TH>,
312
317
  ) => this.getTX(cb);
313
318
  }
@@ -203,3 +203,5 @@ export const withUserRLS = (
203
203
  const queryId = crypto.randomUUID();
204
204
  return [QUERY_ID_PREFIX + queryId, firstQuery, query].filter(Boolean).join("\n");
205
205
  };
206
+
207
+ export const TX_KEY = "tx" as const;
@@ -129,10 +129,11 @@ export class PublishParser {
129
129
  };
130
130
  return unrestrictedCtx;
131
131
  }
132
- const { clientDb } = await publishParams.getClientDBHandlers(undefined);
132
+ const { clientDb, withClientDbTx } = await publishParams.getClientDBHandlers(undefined);
133
133
  const { clientInfo, clientReq, tables } = publishParams;
134
134
  const restrictedCtx: RestrictedFunctionContext<void, SessionUser, unknown> = {
135
135
  dbo: clientDb,
136
+ withClientDbTx,
136
137
  user,
137
138
  clientInfo,
138
139
  clientReq,
@@ -11,6 +11,7 @@ import type { SessionUser } from "../Auth/AuthTypes";
11
11
  import type { DBOFullyTyped, DBOFullyTypedClient } from "../DBSchemaBuilder/DBSchemaBuilder";
12
12
  import type { DB } from "../initProstgles";
13
13
  import type { PublishParams } from "./publishTypesAndUtils";
14
+ import type { ClientHandlers } from "../WebsocketAPI/getClientHandlers";
14
15
 
15
16
  type FunctionContextBase<S, SUser extends SessionUser, Context> = Pick<
16
17
  PublishParams<S, SUser>,
@@ -30,6 +31,7 @@ export type RestrictedFunctionContext<
30
31
  Context = undefined,
31
32
  > = FunctionContextBase<S, SUser, Context> & {
32
33
  dbo: DBOFullyTypedClient<S>;
34
+ withClientDbTx: ClientHandlers<S>["withClientDbTx"];
33
35
  };
34
36
 
35
37
  export type UnrestrictedFunctionContext<
@@ -55,11 +57,7 @@ export type ServerFunctionDefinition = {
55
57
  };
56
58
 
57
59
  declare const serverFunctionContext: unique symbol;
58
- export type ServerFunctionContextMarker<
59
- S,
60
- SUser extends SessionUser,
61
- Context = undefined,
62
- > = {
60
+ export type ServerFunctionContextMarker<S, SUser extends SessionUser, Context = undefined> = {
63
61
  [serverFunctionContext]?: [S, SUser, [Context] extends [undefined] ? never : Context];
64
62
  };
65
63
 
@@ -2,12 +2,13 @@ import { isObject } from "prostgles-types";
2
2
  import type { PublishParser } from "./PublishParser";
3
3
  import { type PublishObject } from "./PublishParser";
4
4
  import { getFileVersionTableName, isFileVersionTable } from "../StorageClient/fileVersionUtils";
5
+ import { TX_KEY } from "../DboBuilder/dboBuilderUtils";
5
6
 
6
7
  export const getPublishedTableNames = (
7
8
  publishParserInstance: PublishParser,
8
9
  publishObject: PublishObject,
9
10
  ) => {
10
- const txKey = !publishParserInstance.prostgles.opts.transactions ? "" : "tx";
11
+ const txKey = !publishParserInstance.prostgles.opts.transactions ? "" : TX_KEY;
11
12
  if (txKey && txKey in publishObject) {
12
13
  throw new Error(
13
14
  `Transactions key ${JSON.stringify(txKey)} collides with a published table name`,
@@ -127,7 +127,7 @@ export type AfterEachTsTrigger<R, DBX, Context = undefined, InputDataType = R> =
127
127
  localParams: undefined | LocalParams;
128
128
  context: Context;
129
129
  },
130
- ) => Promise<void>;
130
+ ) => MaybePromise<void>;
131
131
  };
132
132
 
133
133
  export type ValidateRowsArgsCommon<R = AnyObject, DBX = DBHandlerServer> = {
@@ -1,3 +1,4 @@
1
+ import type { MaybePromise } from "prostgles-types";
1
2
  import type * as stream from "stream";
2
3
 
3
4
  export type LocalUploadedFileDetails = {
@@ -22,9 +23,9 @@ export type UploadFileOptions = {
22
23
  onProgress?: (bytesUploaded: number) => void;
23
24
  };
24
25
  export type StorageClientBase<T> = {
25
- upload: (file: UploadFileOptions) => Promise<T>;
26
- downloadAsStream: (name: string) => Promise<stream.Readable>;
27
- delete: (fileName: string) => Promise<void>;
26
+ upload: (file: UploadFileOptions) => MaybePromise<T>;
27
+ downloadAsStream: (name: string) => MaybePromise<stream.Readable>;
28
+ delete: (fileName: string) => MaybePromise<void>;
28
29
  };
29
30
  export type LocalStorageClient = StorageClientBase<LocalUploadedFileDetails> & {
30
31
  type: "local";
@@ -32,6 +33,6 @@ export type LocalStorageClient = StorageClientBase<LocalUploadedFileDetails> & {
32
33
  };
33
34
  export type CloudStorageClient = StorageClientBase<CloudUploadedFileDetails> & {
34
35
  type: "cloud";
35
- getSignedUrlForDownload: (fileName: string, expiresInSeconds: number) => Promise<string>;
36
+ getSignedUrlForDownload: (fileName: string, expiresInSeconds: number) => MaybePromise<string>;
36
37
  };
37
38
  export type StorageClient = LocalStorageClient | CloudStorageClient;
@@ -1,4 +1,5 @@
1
1
  import {
2
+ getAllowedTableMethods,
2
3
  getKeys,
3
4
  type AnyObject,
4
5
  type ClientSchema,
@@ -8,6 +9,7 @@ import {
8
9
  } from "prostgles-types";
9
10
  import type { AuthClientRequest } from "../Auth/AuthTypes";
10
11
  import type { DBOFullyTypedClient } from "../DBSchemaBuilder/DBSchemaBuilder";
12
+ import type { DbTxTableHandlers } from "../DboBuilder/DboBuilderTypes";
11
13
  import type { Prostgles } from "../Prostgles";
12
14
  import type { ServerFunctionDefinition } from "../PublishParser/defineServerFunction";
13
15
  import type { PermissionScope } from "../PublishParser/publishTypesAndUtils";
@@ -17,6 +19,11 @@ import { getClientSchema } from "./getClientSchema";
17
19
  export type ClientHandlers<S = void> = {
18
20
  clientSql: SQLHandler;
19
21
  clientDb: DBOFullyTypedClient<S>;
22
+ /**
23
+ * Runs permission-checked table operations in a transaction. Requires transactions: true.
24
+ * Caught table request errors also roll back the transaction.
25
+ */
26
+ withClientDbTx: <R>(callback: (clientDb: DBOFullyTypedClient<S>) => R | Promise<R>) => Promise<R>;
20
27
  clientMethods: Record<string, ServerFunctionDefinition>;
21
28
  clientSchema: ClientSchema;
22
29
  };
@@ -27,47 +34,74 @@ export const getClientHandlers = async <S = void>(
27
34
  ): Promise<ClientHandlers<S>> => {
28
35
  prostgles.checkNotDestroyed();
29
36
  const clientSchema =
30
- clientReq.socket?.prostgles?.get(prostgles.appId) ??
37
+ (scope ? undefined : clientReq.socket?.prostgles?.get(prostgles.appId)) ??
31
38
  (await getClientSchema.bind(prostgles)(clientReq, scope));
39
+
32
40
  const sqlHandler: SQLHandler | undefined = ((
33
41
  query: string,
34
42
  params?: unknown,
35
43
  options?: SQLOptions,
36
44
  ) => runClientSqlRequest.bind(prostgles)({ query, params, options }, clientReq)) as SQLHandler;
37
- const tableHandlers = Object.fromEntries(
38
- prostgles.dboBuilder.tablesOrViews!.map((table) => {
39
- const methods = [...tableMethods];
40
- const handlers = Object.fromEntries(
41
- methods.map((command) => {
42
- const method = (param1: unknown, param2: unknown, param3: unknown) =>
43
- runClientRequest.bind(prostgles)(
44
- { command, tableName: table.name, param1, param2, param3 },
45
- clientReq,
46
- scope,
47
- );
48
- return [command, method];
49
- }),
50
- );
51
- return [table.name, handlers];
52
- }),
53
- );
54
45
 
55
- const txNotAllowed: {} = {
56
- tx: () => {
57
- throw new Error("Transactions are not allowed in client handlers");
58
- },
59
- };
46
+ const getTableHandlers = (
47
+ transactionHandlers?: DbTxTableHandlers,
48
+ onRequestError?: (error: unknown) => void,
49
+ ) =>
50
+ Object.fromEntries(
51
+ clientSchema.tableSchema.map((table) => {
52
+ const allowedMethods = getAllowedTableMethods(table);
53
+ const methods = tableMethods.filter((command) => allowedMethods.includes(command));
54
+ const handlers = Object.fromEntries(
55
+ methods.map((command) => {
56
+ const method = (param1: unknown, param2: unknown, param3: unknown) =>
57
+ runClientRequest
58
+ .bind(prostgles)(
59
+ { command, tableName: table.name, param1, param2, param3 },
60
+ clientReq,
61
+ scope,
62
+ transactionHandlers,
63
+ )
64
+ .catch((error: unknown) => {
65
+ onRequestError?.(error);
66
+ throw error;
67
+ });
68
+ return [command, method];
69
+ }),
70
+ );
71
+ return [table.name, handlers];
72
+ }),
73
+ );
74
+
60
75
  const clientSql = ((query: string, params?: AnyObject, options?: SQLOptions) => {
61
76
  if (scope && !scope.allowSql) {
62
- throw new Error("SQL is dissallowed by PermissionScope");
77
+ throw new Error("SQL is disallowed by PermissionScope");
63
78
  }
64
79
 
65
80
  return sqlHandler(query, params, options);
66
81
  }) as SQLHandler;
67
- const clientDb = {
68
- ...tableHandlers,
69
- ...txNotAllowed,
70
- } as DBOFullyTypedClient<S>;
82
+
83
+ const clientDb = getTableHandlers() as unknown as DBOFullyTypedClient<S>;
84
+
85
+ const withClientDbTx: ClientHandlers<S>["withClientDbTx"] = async (callback) => {
86
+ prostgles.checkNotDestroyed();
87
+ if (!prostgles.opts.transactions) {
88
+ throw new Error("Transactions are not enabled");
89
+ }
90
+ return prostgles.dboBuilder.getTX(async (transactionHandlers) => {
91
+ /**
92
+ * runClientRequest throws authorization errors.
93
+ * Prevent cached authorization errors from committing the transaction.
94
+ */
95
+ let failure: { error: unknown } | undefined;
96
+ const result = await callback({
97
+ ...getTableHandlers(transactionHandlers, (error) => {
98
+ failure ??= { error };
99
+ }),
100
+ } as unknown as DBOFullyTypedClient<S>);
101
+ if (failure) throw failure.error;
102
+ return result;
103
+ });
104
+ };
71
105
 
72
106
  const clientMethods: Record<string, ServerFunctionDefinition> = Object.fromEntries(
73
107
  clientSchema.methods.map(({ name, input, description, output }) => {
@@ -81,7 +115,7 @@ export const getClientHandlers = async <S = void>(
81
115
  }),
82
116
  );
83
117
 
84
- return { clientDb, clientSql, clientMethods, clientSchema };
118
+ return { clientDb, clientSql, clientMethods, clientSchema, withClientDbTx };
85
119
  };
86
120
 
87
121
  const tableMethods = getKeys({
package/lib/index.ts CHANGED
@@ -3,6 +3,7 @@ import type { SessionUser } from "./Auth/AuthTypes";
3
3
  import type { InitResult, OnReadyCallbackBasic } from "./initProstgles";
4
4
  import { Prostgles } from "./Prostgles";
5
5
  import type { ProstglesInitOptions } from "./ProstglesTypes";
6
+ export { DB_GENERATED_NAMES } from "./DBSchemaBuilder/constants";
6
7
 
7
8
  function prostgles<
8
9
  S = void,
@@ -22,9 +23,8 @@ export const createProstgles = <
22
23
  SUser extends SessionUser = SessionUser,
23
24
  ClientSchema = S,
24
25
  >() => {
25
- return <Context = undefined>(
26
- params: ProstglesInitOptions<S, SUser, Context>,
27
- ) => prostgles<S, SUser, Context, ClientSchema>(params);
26
+ return <Context = undefined>(params: ProstglesInitOptions<S, SUser, Context>) =>
27
+ prostgles<S, SUser, Context, ClientSchema>(params);
28
28
  };
29
29
  export * from "./PublishParser/defineServerFunction";
30
30
  export * from "./Auth/AuthTypes";
@@ -9,6 +9,7 @@ import {
9
9
  import type { AuthClientRequest } from "./Auth/AuthTypes";
10
10
  import { getSessionUser } from "./Auth/utils/getSessionUser";
11
11
  import type { LocalParams } from "./DboBuilder/DboBuilder";
12
+ import type { DbTxTableHandlers } from "./DboBuilder/DboBuilderTypes";
12
13
  import type { TableHandler as TableHandlerServer } from "./DboBuilder/TableHandler/TableHandler";
13
14
  import { canRunSQL } from "./DboBuilder/runSql/runSQL";
14
15
  import type { Prostgles } from "./Prostgles";
@@ -64,6 +65,7 @@ export const runClientRequest = async function (
64
65
  nonValidatedArgs: Args,
65
66
  clientReq: AuthClientRequest,
66
67
  scope: PermissionScope | undefined,
68
+ transactionHandlers?: DbTxTableHandlers,
67
69
  ) {
68
70
  this.checkNotDestroyed();
69
71
  /* Channel name will only include client-sent params so we ignore table_rules enforced params */
@@ -102,7 +104,9 @@ export const runClientRequest = async function (
102
104
  );
103
105
  }
104
106
 
105
- const tableHandler = this.dboBuilder.dboMap.get(tableName);
107
+ const tableHandler = transactionHandlers ?
108
+ (Object.hasOwn(transactionHandlers, tableName) ? transactionHandlers[tableName] : undefined)
109
+ : this.dboBuilder.dboMap.get(tableName);
106
110
  if (!tableHandler) {
107
111
  throw `tableName ${tableName} is invalid or not allowed`;
108
112
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "4.2.642",
3
+ "version": "4.2.643",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,8 +11,10 @@
11
11
  "prepare": "npm run build",
12
12
  "start": "tsc --watch",
13
13
  "build": "tsc",
14
- "lint": "eslint . --ext .ts --quiet --fix",
15
- "test:lib": "rm -rf ./node_modules/* && rm -rf ./dist/* && npm i && npm run lint && tsc && node --trace-uncaught --test dist/**/*.spec.js",
14
+ "typecheck": "tsc --noEmit && npm run typecheck:tests",
15
+ "typecheck:tests": "tsc --noEmit -p tests/server && tsc --noEmit -p tests/client",
16
+ "lint": "eslint . --ext .ts --quiet",
17
+ "test:lib": "rm -rf ./node_modules/* && rm -rf ./dist/* && npm i && npm run lint -- --ignore-pattern tests && tsc && node --trace-uncaught --test dist/**/*.spec.js",
16
18
  "test-only": "cd tests/ && ./test.sh",
17
19
  "test-quick": "cd tests/ && ./test.sh -quick",
18
20
  "test": "npm run test:lib && npm run test-only",