@90soft/parse-server-kit 2.6.0 → 2.8.0

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 (56) hide show
  1. package/README.md +613 -424
  2. package/dist/database/schema.d.ts +14 -0
  3. package/dist/database/schema.d.ts.map +1 -1
  4. package/dist/database/schema.js +2 -1
  5. package/dist/database/schema.js.map +1 -1
  6. package/dist/database/versionRegistry.d.ts +35 -0
  7. package/dist/database/versionRegistry.d.ts.map +1 -0
  8. package/dist/database/versionRegistry.js +153 -0
  9. package/dist/database/versionRegistry.js.map +1 -0
  10. package/dist/database/versionedMongoAdapter.d.ts +51 -0
  11. package/dist/database/versionedMongoAdapter.d.ts.map +1 -0
  12. package/dist/database/versionedMongoAdapter.js +131 -0
  13. package/dist/database/versionedMongoAdapter.js.map +1 -0
  14. package/dist/decorators/cloudRegistry.d.ts.map +1 -1
  15. package/dist/decorators/cloudRegistry.js +5 -0
  16. package/dist/decorators/cloudRegistry.js.map +1 -1
  17. package/dist/decorators/triggerDecorator.d.ts +8 -0
  18. package/dist/decorators/triggerDecorator.d.ts.map +1 -1
  19. package/dist/decorators/triggerDecorator.js +10 -1
  20. package/dist/decorators/triggerDecorator.js.map +1 -1
  21. package/dist/decorators/triggerRegistry.d.ts.map +1 -1
  22. package/dist/decorators/triggerRegistry.js +52 -8
  23. package/dist/decorators/triggerRegistry.js.map +1 -1
  24. package/dist/decorators/types/triggerTypes.d.ts +1 -1
  25. package/dist/decorators/types/triggerTypes.d.ts.map +1 -1
  26. package/dist/index.d.ts +7 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +27 -2
  29. package/dist/index.js.map +1 -1
  30. package/dist/middleware/middleware.d.ts.map +1 -1
  31. package/dist/middleware/middleware.js +34 -1
  32. package/dist/middleware/middleware.js.map +1 -1
  33. package/dist/middleware/rateLimit.d.ts.map +1 -1
  34. package/dist/middleware/rateLimit.js +7 -1
  35. package/dist/middleware/rateLimit.js.map +1 -1
  36. package/dist/swagger/index.d.ts +5 -1
  37. package/dist/swagger/index.d.ts.map +1 -1
  38. package/dist/swagger/index.js +32 -8
  39. package/dist/swagger/index.js.map +1 -1
  40. package/dist/transactions/ambientSession.d.ts +39 -0
  41. package/dist/transactions/ambientSession.d.ts.map +1 -0
  42. package/dist/transactions/ambientSession.js +88 -0
  43. package/dist/transactions/ambientSession.js.map +1 -0
  44. package/dist/transactions/context.d.ts +86 -0
  45. package/dist/transactions/context.d.ts.map +1 -0
  46. package/dist/transactions/context.js +124 -0
  47. package/dist/transactions/context.js.map +1 -0
  48. package/dist/utils/dynamicImport.d.ts +22 -1
  49. package/dist/utils/dynamicImport.d.ts.map +1 -1
  50. package/dist/utils/dynamicImport.js +13 -4
  51. package/dist/utils/dynamicImport.js.map +1 -1
  52. package/dist/utils/helper.d.ts +10 -1
  53. package/dist/utils/helper.d.ts.map +1 -1
  54. package/dist/utils/helper.js +10 -1
  55. package/dist/utils/helper.js.map +1 -1
  56. package/package.json +75 -54
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Transactions that follow the call, not the request.
3
+ *
4
+ * Parse Server has a transaction of its own, but it keeps the open session in a
5
+ * single field on the shared `DatabaseController`, and every write in the
6
+ * process passes that field to the adapter. One cloud function's transaction
7
+ * therefore swallows every *unrelated* request running at the same moment, and
8
+ * two of them collide outright.
9
+ *
10
+ * This one lives in an `AsyncLocalStorage` instead. The store follows the chain
11
+ * of awaits belonging to one call and nothing else, so two callers each get
12
+ * their own session and neither can see the other's. The database adapter reads
13
+ * it at the moment it talks to the driver — see `ambientSession.ts` — which is
14
+ * why a save inside the body joins without being told to.
15
+ *
16
+ * **This needs Parse Server's `directAccess`.** With it, a `save()` in cloud
17
+ * code is handled in the same async context; without it the SDK sends itself an
18
+ * HTTP request, which arrives in a fresh context with an empty store and writes
19
+ * outside the transaction. `directAccess` defaults to true and the config pins
20
+ * it, because that failure has no symptom.
21
+ *
22
+ * And it needs MongoDB to be a replica set. A standalone has no transactions
23
+ * and refuses to open one.
24
+ */
25
+ /**
26
+ * One code for every "somebody else got there first".
27
+ *
28
+ * A lost optimistic lock and a transaction that lost its race are the same
29
+ * event to whoever is looking at the screen, so they read the same. Parse has
30
+ * no code of its own for a write conflict and every code it does have means
31
+ * something else.
32
+ */
33
+ type ParseErrorCode = ConstructorParameters<typeof Parse.Error>[0];
34
+ export declare const CONFLICT: ParseErrorCode;
35
+ export declare const CONFLICT_MESSAGE = "Somebody else changed this while you were working on it. Open it again and redo your change.";
36
+ /**
37
+ * The four things this needs of a storage adapter.
38
+ *
39
+ * Deliberately structural and deliberately ignorant: the session is `unknown`
40
+ * because what a transaction *is* belongs to the adapter, and nothing here
41
+ * should be able to reach into one.
42
+ */
43
+ export interface TransactionalAdapter {
44
+ connect(): Promise<unknown>;
45
+ createTransactionalSession(): Promise<unknown>;
46
+ commitTransactionalSession(session: unknown): Promise<unknown>;
47
+ abortTransactionalSession(session: unknown): Promise<unknown>;
48
+ }
49
+ /** Told once, when the adapter is built. */
50
+ export declare function useTransactionAdapter(value: TransactionalAdapter): void;
51
+ /** The session this call is running under, if it is running under one. */
52
+ export declare function currentSession(): unknown;
53
+ export declare function inTransaction(): boolean;
54
+ /**
55
+ * Run this, and either everything it wrote lands or none of it does.
56
+ *
57
+ * **Nested calls join.** A body already running inside a transaction simply
58
+ * runs — MongoDB has no nested transactions, and the useful meaning of an inner
59
+ * one is "take part in the outer". Committing is therefore the outermost
60
+ * caller's job alone.
61
+ *
62
+ * A body may be **re-run** if the transaction lost a race with another one, so
63
+ * it must be safe to repeat. Ours are: each reads the state it acts on at the
64
+ * start, and anything it wrote on the failed attempt was rolled back with it.
65
+ */
66
+ export declare function withTransaction<T>(body: () => Promise<T>): Promise<T>;
67
+ /**
68
+ * Everything this cloud function writes lands together, or none of it does.
69
+ *
70
+ * **Order matters.** `@CloudFunction` reads the method off the descriptor when
71
+ * it is applied, and decorators apply bottom-up — so this must sit *below* it,
72
+ * or the registry keeps the unwrapped method and the transaction silently never
73
+ * opens:
74
+ *
75
+ * ```ts
76
+ * @CloudFunction({...}) // sees the wrapped method
77
+ * @Transactional() // wraps it
78
+ * async submitJob(req) {}
79
+ * ```
80
+ *
81
+ * `withTransaction` is exported beside this for anything that is not a cloud
82
+ * function, or for wrapping part of one by hand.
83
+ */
84
+ export declare function Transactional(): (_target: object, _propertyKey: string | symbol, descriptor: PropertyDescriptor) => PropertyDescriptor;
85
+ export {};
86
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/transactions/context.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;;;GAOG;AACH,KAAK,cAAc,GAAG,qBAAqB,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAEnE,eAAO,MAAM,QAAQ,EAAW,cAAc,CAAC;AAE/C,eAAO,MAAM,gBAAgB,iGACmE,CAAC;AASjG;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,0BAA0B,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/D;AAKD,4CAA4C;AAC5C,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAEvE;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAmCD;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAkC3E;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,KAEzB,SAAS,MAAM,EACf,cAAc,MAAM,GAAG,MAAM,EAC7B,YAAY,kBAAkB,KAC7B,kBAAkB,CAWtB"}
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CONFLICT_MESSAGE = exports.CONFLICT = void 0;
4
+ exports.useTransactionAdapter = useTransactionAdapter;
5
+ exports.currentSession = currentSession;
6
+ exports.inTransaction = inTransaction;
7
+ exports.withTransaction = withTransaction;
8
+ exports.Transactional = Transactional;
9
+ const node_async_hooks_1 = require("node:async_hooks");
10
+ exports.CONFLICT = 5001;
11
+ exports.CONFLICT_MESSAGE = 'Somebody else changed this while you were working on it. Open it again and redo your change.';
12
+ const storage = new node_async_hooks_1.AsyncLocalStorage();
13
+ let adapter = null;
14
+ let warnedWithoutAdapter = false;
15
+ /** Told once, when the adapter is built. */
16
+ function useTransactionAdapter(value) {
17
+ adapter = value;
18
+ }
19
+ /** The session this call is running under, if it is running under one. */
20
+ function currentSession() {
21
+ return storage.getStore()?.session;
22
+ }
23
+ function inTransaction() {
24
+ return storage.getStore() !== undefined;
25
+ }
26
+ /**
27
+ * A write that lost a race with another transaction and may simply be retried.
28
+ *
29
+ * MongoDB labels these itself, and a write inside a transaction reports code
30
+ * 251. Neither survives the trip up, though: the Mongo adapter classifies the
31
+ * error first and rethrows it as a bare `INTERNAL_SERVER_ERROR` with the message
32
+ * `Database error`, dropping the label and the code.
33
+ *
34
+ * So that message is the third thing checked. It reads like a guess and is not:
35
+ * Parse Server produces that exact string in exactly one place, and only for an
36
+ * error its own `isTransientError` has already classified — which is the same
37
+ * question being asked here.
38
+ */
39
+ const PARSE_TRANSIENT_MESSAGE = 'Database error';
40
+ function isTransient(error) {
41
+ const failure = error;
42
+ if (failure?.hasErrorLabel?.('TransientTransactionError') === true)
43
+ return true;
44
+ if (failure?.code === 251)
45
+ return true;
46
+ return (failure?.code === Parse.Error.INTERNAL_SERVER_ERROR &&
47
+ failure?.message === PARSE_TRANSIENT_MESSAGE);
48
+ }
49
+ /** How many times a body may be re-run after losing a race. */
50
+ const MAX_ATTEMPTS = 3;
51
+ /**
52
+ * Run this, and either everything it wrote lands or none of it does.
53
+ *
54
+ * **Nested calls join.** A body already running inside a transaction simply
55
+ * runs — MongoDB has no nested transactions, and the useful meaning of an inner
56
+ * one is "take part in the outer". Committing is therefore the outermost
57
+ * caller's job alone.
58
+ *
59
+ * A body may be **re-run** if the transaction lost a race with another one, so
60
+ * it must be safe to repeat. Ours are: each reads the state it acts on at the
61
+ * start, and anything it wrote on the failed attempt was rolled back with it.
62
+ */
63
+ async function withTransaction(body) {
64
+ // Already inside one — take part in it rather than opening a second.
65
+ if (inTransaction())
66
+ return body();
67
+ if (!adapter) {
68
+ if (!warnedWithoutAdapter) {
69
+ warnedWithoutAdapter = true;
70
+ console.warn('[Transactions] No storage adapter registered — running without one. ' +
71
+ 'Writes will not be rolled back together.');
72
+ }
73
+ return body();
74
+ }
75
+ // `createTransactionalSession` reaches straight for the driver's client, so
76
+ // the very first transaction of the process has to wait for the connection.
77
+ await adapter.connect();
78
+ for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt += 1) {
79
+ const session = await adapter.createTransactionalSession();
80
+ try {
81
+ const result = await storage.run({ session }, body);
82
+ await adapter.commitTransactionalSession(session);
83
+ return result;
84
+ }
85
+ catch (error) {
86
+ await adapter.abortTransactionalSession(session).catch(() => undefined);
87
+ if (!isTransient(error))
88
+ throw error;
89
+ }
90
+ }
91
+ // Out of attempts, still losing. The caller is not interested in which lock
92
+ // it was — only that somebody else is working on the same thing.
93
+ throw new Parse.Error(exports.CONFLICT, exports.CONFLICT_MESSAGE);
94
+ }
95
+ /**
96
+ * Everything this cloud function writes lands together, or none of it does.
97
+ *
98
+ * **Order matters.** `@CloudFunction` reads the method off the descriptor when
99
+ * it is applied, and decorators apply bottom-up — so this must sit *below* it,
100
+ * or the registry keeps the unwrapped method and the transaction silently never
101
+ * opens:
102
+ *
103
+ * ```ts
104
+ * @CloudFunction({...}) // sees the wrapped method
105
+ * @Transactional() // wraps it
106
+ * async submitJob(req) {}
107
+ * ```
108
+ *
109
+ * `withTransaction` is exported beside this for anything that is not a cloud
110
+ * function, or for wrapping part of one by hand.
111
+ */
112
+ function Transactional() {
113
+ return (_target, _propertyKey, descriptor) => {
114
+ const body = descriptor.value;
115
+ if (typeof body !== 'function') {
116
+ throw new Error('@Transactional can only be applied to methods.');
117
+ }
118
+ descriptor.value = function (...args) {
119
+ return withTransaction(() => body.apply(this, args));
120
+ };
121
+ return descriptor;
122
+ };
123
+ }
124
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/transactions/context.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,23 @@
1
- export declare const importFiles: (directoryPath: string) => void;
1
+ export interface ImportFilesOptions {
2
+ /**
3
+ * Which file extensions to load. Defaults to `['.js']` — the compiled output
4
+ * a production server runs.
5
+ *
6
+ * Pass `['.js', '.ts']` when running straight from source under ts-node or
7
+ * tsx. Without it nothing is imported at all: no models register, no cloud
8
+ * functions exist, and the server starts perfectly happily with an empty
9
+ * schema. It is not the kind of failure you want to debug from the symptoms.
10
+ *
11
+ * Point this at a source directory only. A directory holding *both* compiled
12
+ * and source copies would register every class twice.
13
+ */
14
+ extensions?: string[];
15
+ /** Log each file as it is imported. Defaults to true, as it always has. */
16
+ verbose?: boolean;
17
+ }
18
+ /**
19
+ * Recursively import every matching file in a directory, for the side effect of
20
+ * running its decorators.
21
+ */
22
+ export declare const importFiles: (directoryPath: string, options?: ImportFilesOptions) => void;
2
23
  //# sourceMappingURL=dynamicImport.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamicImport.d.ts","sourceRoot":"","sources":["../../src/utils/dynamicImport.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,WAAW,GAAI,eAAe,MAAM,SAWhD,CAAC"}
1
+ {"version":3,"file":"dynamicImport.d.ts","sourceRoot":"","sources":["../../src/utils/dynamicImport.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,GACtB,eAAe,MAAM,EACrB,UAAS,kBAAuB,SAkBjC,CAAC"}
@@ -4,15 +4,24 @@ exports.importFiles = void 0;
4
4
  const fs_1 = require("fs");
5
5
  const path_1 = require("path");
6
6
  const isDirectory = (path) => (0, fs_1.statSync)(path).isDirectory();
7
- const importFiles = (directoryPath) => {
7
+ /**
8
+ * Recursively import every matching file in a directory, for the side effect of
9
+ * running its decorators.
10
+ */
11
+ const importFiles = (directoryPath, options = {}) => {
12
+ const { extensions = ['.js'], verbose = true } = options;
13
+ // `.d.ts` is a declaration, never a module to execute — importing one under
14
+ // ts-node is at best a no-op and at worst a crash.
15
+ const wanted = new Set(extensions.map(e => (e.startsWith('.') ? e : `.${e}`)));
8
16
  const files = (0, fs_1.readdirSync)(directoryPath);
9
17
  files.forEach(file => {
10
18
  const filePath = (0, path_1.join)(directoryPath, file);
11
19
  if (isDirectory(filePath)) {
12
- (0, exports.importFiles)(filePath);
20
+ (0, exports.importFiles)(filePath, options);
13
21
  }
14
- else if ((0, path_1.extname)(filePath) === '.js') {
15
- console.log(filePath);
22
+ else if (wanted.has((0, path_1.extname)(filePath)) && !file.endsWith('.d.ts')) {
23
+ if (verbose)
24
+ console.log(filePath);
16
25
  require(filePath);
17
26
  }
18
27
  });
@@ -1 +1 @@
1
- {"version":3,"file":"dynamicImport.js","sourceRoot":"","sources":["../../src/utils/dynamicImport.ts"],"names":[],"mappings":";;;AAAA,2BAAyC;AACzC,+BAAmC;AAEnC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAA,aAAQ,EAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAE5D,MAAM,WAAW,GAAG,CAAC,aAAqB,EAAE,EAAE;IACnD,MAAM,KAAK,GAAG,IAAA,gBAAW,EAAC,aAAa,CAAC,CAAC;IACzC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACnB,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,IAAA,mBAAW,EAAC,QAAQ,CAAC,CAAC;QACxB,CAAC;aAAM,IAAI,IAAA,cAAO,EAAC,QAAQ,CAAC,KAAK,KAAK,EAAE,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACtB,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAXW,QAAA,WAAW,eAWtB"}
1
+ {"version":3,"file":"dynamicImport.js","sourceRoot":"","sources":["../../src/utils/dynamicImport.ts"],"names":[],"mappings":";;;AAAA,2BAAyC;AACzC,+BAAmC;AAEnC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAA,aAAQ,EAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAoBnE;;;GAGG;AACI,MAAM,WAAW,GAAG,CACzB,aAAqB,EACrB,UAA8B,EAAE,EAChC,EAAE;IACF,MAAM,EAAC,UAAU,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,EAAC,GAAG,OAAO,CAAC;IAEvD,4EAA4E;IAC5E,mDAAmD;IACnD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAE/E,MAAM,KAAK,GAAG,IAAA,gBAAW,EAAC,aAAa,CAAC,CAAC;IACzC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACnB,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,IAAA,mBAAW,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjC,CAAC;aAAM,IAAI,MAAM,CAAC,GAAG,CAAC,IAAA,cAAO,EAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACpE,IAAI,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACnC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AApBW,QAAA,WAAW,eAoBtB"}
@@ -9,7 +9,16 @@ export declare function catchError<T>(promise: Promise<T>): Promise<[undefined,
9
9
  */
10
10
  export declare function getUserRoles(user: Parse.User): Promise<string[]>;
11
11
  /**
12
- * Get role names for multiple users (batch — avoids N+1)
12
+ * Get role names for multiple users.
13
+ *
14
+ * Costs one query per *role*, not one per user — which is the half that
15
+ * matters, since the role list is a fixed property of the deployment (and
16
+ * capped at 100 here) while the user list is whatever the caller passed. A page
17
+ * of 500 users costs the same as a page of 5.
18
+ *
19
+ * It is not a single query: Parse relations cannot be filtered across roles in
20
+ * one go. If the role count ever grows past a few dozen, this is the place to
21
+ * look.
13
22
  */
14
23
  export declare function getUsersRoles(users: Parse.User[]): Promise<Map<string, string[]>>;
15
24
  //# sourceMappingURL=helper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../src/utils/helper.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,SAAO,UAMlD;AAED,wBAAgB,sBAAsB,CACpC,MAAM,SAAI,EACV,cAAc,UAAO,EACrB,cAAc,UAAO,UAiBtB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,UAInD;AAED,wBAAgB,oBAAoB,CAAC,MAAM,SAAI,GAAG,MAAM,CAOvD;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,oBAE/B;AAED,wBAAsB,UAAU,CAAC,CAAC,EAChC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAClB,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAQnC;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAKtE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAmBvF"}
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../src/utils/helper.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,SAAO,UAMlD;AAED,wBAAgB,sBAAsB,CACpC,MAAM,SAAI,EACV,cAAc,UAAO,EACrB,cAAc,UAAO,UAiBtB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,UAInD;AAED,wBAAgB,oBAAoB,CAAC,MAAM,SAAI,GAAG,MAAM,CAOvD;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,oBAE/B;AAED,wBAAsB,UAAU,CAAC,CAAC,EAChC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAClB,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAQnC;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAKtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAmBvF"}
@@ -67,7 +67,16 @@ async function getUserRoles(user) {
67
67
  return roles.map(r => r.get('name'));
68
68
  }
69
69
  /**
70
- * Get role names for multiple users (batch — avoids N+1)
70
+ * Get role names for multiple users.
71
+ *
72
+ * Costs one query per *role*, not one per user — which is the half that
73
+ * matters, since the role list is a fixed property of the deployment (and
74
+ * capped at 100 here) while the user list is whatever the caller passed. A page
75
+ * of 500 users costs the same as a page of 5.
76
+ *
77
+ * It is not a single query: Parse relations cannot be filtered across roles in
78
+ * one go. If the role count ever grows past a few dozen, this is the place to
79
+ * look.
71
80
  */
72
81
  async function getUsersRoles(users) {
73
82
  if (users.length === 0)
@@ -1 +1 @@
1
- {"version":3,"file":"helper.js","sourceRoot":"","sources":["../../src/utils/helper.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"helper.js","sourceRoot":"","sources":["../../src/utils/helper.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,54 +1,75 @@
1
- {
2
- "name": "@90soft/parse-server-kit",
3
- "version": "2.6.0",
4
- "description": "Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "files": [
8
- "dist"
9
- ],
10
- "scripts": {
11
- "build": "tsc",
12
- "prepublishOnly": "npm run build"
13
- },
14
- "keywords": [
15
- "parse-server",
16
- "decorators",
17
- "typescript",
18
- "backend",
19
- "cloud-functions",
20
- "mongodb",
21
- "acl",
22
- "swagger",
23
- "cron"
24
- ],
25
- "author": "90Soft",
26
- "license": "MIT",
27
- "repository": {
28
- "type": "git",
29
- "url": "https://git.90-soft.com/90_soft/parse-server-kit.git"
30
- },
31
- "peerDependencies": {
32
- "parse": ">=5.0.0",
33
- "reflect-metadata": ">=0.1.13",
34
- "express": ">=4.0.0"
35
- },
36
- "peerDependenciesMeta": {
37
- "node-cron": {
38
- "optional": true
39
- },
40
- "swagger-ui-express": {
41
- "optional": true
42
- }
43
- },
44
- "devDependencies": {
45
- "typescript": "^5.5.0",
46
- "@types/node": "^20.0.0",
47
- "@types/express": "^5.0.0",
48
- "parse": "^5.3.0",
49
- "reflect-metadata": "^0.2.2",
50
- "express": "^5.0.0",
51
- "swagger-ui-express": "^5.0.1",
52
- "node-cron": "^4.0.0"
53
- }
54
- }
1
+ {
2
+ "name": "@90soft/parse-server-kit",
3
+ "version": "2.8.0",
4
+ "description": "Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "test": "jest",
13
+ "test:integration": "NODE_OPTIONS=--experimental-vm-modules jest --config jest.integration.config.js",
14
+ "test:all": "npm test && npm run test:integration",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "keywords": [
18
+ "parse-server",
19
+ "decorators",
20
+ "typescript",
21
+ "backend",
22
+ "cloud-functions",
23
+ "mongodb",
24
+ "acl",
25
+ "swagger",
26
+ "cron"
27
+ ],
28
+ "author": "90Soft",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://git.90-soft.com/90_soft/parse-server-kit.git"
33
+ },
34
+ "engines": {
35
+ "node": ">=18.0.0"
36
+ },
37
+ "peerDependencies": {
38
+ "@types/parse": ">=3.0.0",
39
+ "express": ">=4.0.0",
40
+ "node-cron": ">=3.0.0",
41
+ "parse": ">=5.0.0",
42
+ "parse-server": ">=8.3.0",
43
+ "reflect-metadata": ">=0.1.13",
44
+ "swagger-ui-express": ">=4.0.0"
45
+ },
46
+ "peerDependenciesMeta": {
47
+ "@types/parse": {
48
+ "optional": true
49
+ },
50
+ "node-cron": {
51
+ "optional": true
52
+ },
53
+ "swagger-ui-express": {
54
+ "optional": true
55
+ },
56
+ "parse-server": {
57
+ "optional": true
58
+ }
59
+ },
60
+ "devDependencies": {
61
+ "@types/express": "^5.0.0",
62
+ "@types/jest": "^29.5.0",
63
+ "@types/node": "^20.0.0",
64
+ "express": "^5.0.0",
65
+ "jest": "^29.7.0",
66
+ "mongodb-memory-server": "^11.2.0",
67
+ "node-cron": "^4.0.0",
68
+ "parse": "^5.3.0",
69
+ "parse-server": "^9.10.0",
70
+ "reflect-metadata": "^0.2.2",
71
+ "swagger-ui-express": "^5.0.1",
72
+ "ts-jest": "^29.2.0",
73
+ "typescript": "^5.5.0"
74
+ }
75
+ }