@90soft/parse-server-kit 2.8.2 → 2.10.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.
- package/CHANGELOG.md +99 -0
- package/CLAUDE.md +698 -674
- package/README.md +27 -0
- package/dist/config.d.ts +68 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +35 -0
- package/dist/config.js.map +1 -0
- package/dist/database/indexes.d.ts.map +1 -1
- package/dist/database/indexes.js +14 -1
- package/dist/database/indexes.js.map +1 -1
- package/dist/decorators/cloudDecorator.d.ts.map +1 -1
- package/dist/decorators/cloudDecorator.js +58 -15
- package/dist/decorators/cloudDecorator.js.map +1 -1
- package/dist/decorators/cloudRegistry.d.ts +13 -0
- package/dist/decorators/cloudRegistry.d.ts.map +1 -1
- package/dist/decorators/cloudRegistry.js +23 -1
- package/dist/decorators/cloudRegistry.js.map +1 -1
- package/dist/decorators/parseDecorators.d.ts +1 -1
- package/dist/decorators/parseDecorators.d.ts.map +1 -1
- package/dist/decorators/parseDecorators.js +131 -4
- package/dist/decorators/parseDecorators.js.map +1 -1
- package/dist/decorators/triggerDecorator.d.ts +14 -0
- package/dist/decorators/triggerDecorator.d.ts.map +1 -1
- package/dist/decorators/triggerDecorator.js +31 -2
- package/dist/decorators/triggerDecorator.js.map +1 -1
- package/dist/decorators/triggerRegistry.d.ts +8 -0
- package/dist/decorators/triggerRegistry.d.ts.map +1 -1
- package/dist/decorators/triggerRegistry.js +18 -0
- package/dist/decorators/triggerRegistry.js.map +1 -1
- package/dist/decorators/types/cloudTypes.d.ts +22 -0
- package/dist/decorators/types/cloudTypes.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware/middleware.d.ts.map +1 -1
- package/dist/middleware/middleware.js +66 -5
- package/dist/middleware/middleware.js.map +1 -1
- package/dist/models/BaseModel.d.ts.map +1 -1
- package/dist/models/BaseModel.js +5 -2
- package/dist/models/BaseModel.js.map +1 -1
- package/dist/swagger/index.d.ts.map +1 -1
- package/dist/swagger/index.js +17 -4
- package/dist/swagger/index.js.map +1 -1
- package/dist/swagger/swaggerRegistry.d.ts +11 -0
- package/dist/swagger/swaggerRegistry.d.ts.map +1 -1
- package/dist/swagger/swaggerRegistry.js +18 -1
- package/dist/swagger/swaggerRegistry.js.map +1 -1
- package/dist/utils/dynamicImport.d.ts.map +1 -1
- package/dist/utils/dynamicImport.js +33 -11
- package/dist/utils/dynamicImport.js.map +1 -1
- package/dist/utils/helper.d.ts +5 -1
- package/dist/utils/helper.d.ts.map +1 -1
- package/dist/utils/helper.js +25 -2
- package/dist/utils/helper.js.map +1 -1
- package/dist/utils/roleCache.d.ts +60 -0
- package/dist/utils/roleCache.d.ts.map +1 -0
- package/dist/utils/roleCache.js +112 -0
- package/dist/utils/roleCache.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Role membership, remembered for a while.
|
|
4
|
+
*
|
|
5
|
+
* `@CloudFunction({requireRoles})` asks the database who a user is on every
|
|
6
|
+
* single call, and so does every `getUserRoles()`. That is a full round-trip —
|
|
7
|
+
* milliseconds, not microseconds — to answer a question whose answer almost
|
|
8
|
+
* never changes.
|
|
9
|
+
*
|
|
10
|
+
* **Off by default, and deliberately so.** Caching membership means a revoked
|
|
11
|
+
* role keeps working until the entry expires. That is a security trade, and it
|
|
12
|
+
* belongs to whoever runs the deployment, not to this library. Nothing here
|
|
13
|
+
* takes effect until `configureRoleCache()` is called.
|
|
14
|
+
*
|
|
15
|
+
* When it is on, `invalidateRoles(userId)` is the tool that keeps the window
|
|
16
|
+
* from mattering: call it wherever you grant or revoke, and the TTL becomes a
|
|
17
|
+
* backstop for changes made outside your code rather than the primary control.
|
|
18
|
+
*
|
|
19
|
+
* There is no timer. Entries expire when read and the map is capped on write,
|
|
20
|
+
* so importing this module costs nothing and holds nothing open.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.configureRoleCache = configureRoleCache;
|
|
24
|
+
exports.roleCacheEnabled = roleCacheEnabled;
|
|
25
|
+
exports.invalidateRoles = invalidateRoles;
|
|
26
|
+
exports.roleCacheStats = roleCacheStats;
|
|
27
|
+
exports.readCachedRoles = readCachedRoles;
|
|
28
|
+
exports.writeCachedRoles = writeCachedRoles;
|
|
29
|
+
const DEFAULT_MAX_USERS = 10000;
|
|
30
|
+
let options = null;
|
|
31
|
+
const cache = new Map();
|
|
32
|
+
/**
|
|
33
|
+
* Turn the cache on, change its settings, or turn it off with `false`.
|
|
34
|
+
*
|
|
35
|
+
* Switching off clears whatever was held, so a deployment can disable it and be
|
|
36
|
+
* certain nothing stale survives.
|
|
37
|
+
*/
|
|
38
|
+
function configureRoleCache(config) {
|
|
39
|
+
if (config === false) {
|
|
40
|
+
options = null;
|
|
41
|
+
cache.clear();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (!Number.isFinite(config.ttlMs) || config.ttlMs <= 0) {
|
|
45
|
+
throw new Error(`configureRoleCache: ttlMs must be a positive number, got ${config.ttlMs}. ` +
|
|
46
|
+
'Pass `false` to disable the cache.');
|
|
47
|
+
}
|
|
48
|
+
options = {
|
|
49
|
+
ttlMs: config.ttlMs,
|
|
50
|
+
maxUsers: config.maxUsers ?? DEFAULT_MAX_USERS,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function roleCacheEnabled() {
|
|
54
|
+
return options !== null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Forget a user's roles, or everyone's.
|
|
58
|
+
*
|
|
59
|
+
* Call this wherever a role is granted or revoked. Safe to call when the cache
|
|
60
|
+
* is off — it simply has nothing to do.
|
|
61
|
+
*/
|
|
62
|
+
function invalidateRoles(userId) {
|
|
63
|
+
if (userId === undefined)
|
|
64
|
+
cache.clear();
|
|
65
|
+
else
|
|
66
|
+
cache.delete(userId);
|
|
67
|
+
}
|
|
68
|
+
/** For tests and for reporting. */
|
|
69
|
+
function roleCacheStats() {
|
|
70
|
+
return {
|
|
71
|
+
enabled: options !== null,
|
|
72
|
+
size: cache.size,
|
|
73
|
+
ttlMs: options?.ttlMs ?? null,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The cached roles for this user, or nothing if there is no live entry.
|
|
78
|
+
*
|
|
79
|
+
* `ttlOverrideMs` of 0 means "do not use the cache for this call" — how a
|
|
80
|
+
* single cloud function opts out of a global policy.
|
|
81
|
+
*/
|
|
82
|
+
function readCachedRoles(userId, ttlOverrideMs) {
|
|
83
|
+
if (!options || ttlOverrideMs === 0)
|
|
84
|
+
return undefined;
|
|
85
|
+
const entry = cache.get(userId);
|
|
86
|
+
if (!entry)
|
|
87
|
+
return undefined;
|
|
88
|
+
if (Date.now() >= entry.expiresAt) {
|
|
89
|
+
cache.delete(userId);
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
// A copy, not the stored array. Handing out the internal one means a caller
|
|
93
|
+
// that sorts or filters it in place silently rewrites what every later
|
|
94
|
+
// permission check for this user sees.
|
|
95
|
+
return entry.roles.slice();
|
|
96
|
+
}
|
|
97
|
+
/** Remember this user's roles. A no-op while the cache is off. */
|
|
98
|
+
function writeCachedRoles(userId, roles, ttlOverrideMs) {
|
|
99
|
+
if (!options || ttlOverrideMs === 0)
|
|
100
|
+
return;
|
|
101
|
+
// Map preserves insertion order, so the first key is the oldest write.
|
|
102
|
+
if (cache.size >= options.maxUsers && !cache.has(userId)) {
|
|
103
|
+
const oldest = cache.keys().next();
|
|
104
|
+
if (!oldest.done)
|
|
105
|
+
cache.delete(oldest.value);
|
|
106
|
+
}
|
|
107
|
+
cache.set(userId, {
|
|
108
|
+
roles,
|
|
109
|
+
expiresAt: Date.now() + (ttlOverrideMs ?? options.ttlMs),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=roleCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roleCache.js","sourceRoot":"","sources":["../../src/utils/roleCache.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;;AA4BH,gDAkBC;AAED,4CAEC;AAQD,0CAGC;AAGD,wCAMC;AAQD,0CAiBC;AAGD,4CAiBC;AAlGD,MAAM,iBAAiB,GAAG,KAAM,CAAC;AAEjC,IAAI,OAAO,GAAsC,IAAI,CAAC;AACtD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;AAE5C;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,MAAgC;IACjE,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;QACrB,OAAO,GAAG,IAAI,CAAC;QACf,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,OAAO;IACT,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,4DAA4D,MAAM,CAAC,KAAK,IAAI;YAC1E,oCAAoC,CACvC,CAAC;IACJ,CAAC;IAED,OAAO,GAAG;QACR,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,iBAAiB;KAC/C,CAAC;AACJ,CAAC;AAED,SAAgB,gBAAgB;IAC9B,OAAO,OAAO,KAAK,IAAI,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,MAAe;IAC7C,IAAI,MAAM,KAAK,SAAS;QAAE,KAAK,CAAC,KAAK,EAAE,CAAC;;QACnC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED,mCAAmC;AACnC,SAAgB,cAAc;IAC5B,OAAO;QACL,OAAO,EAAE,OAAO,KAAK,IAAI;QACzB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI;KAC9B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAC7B,MAAc,EACd,aAAsB;IAEtB,IAAI,CAAC,OAAO,IAAI,aAAa,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAEtD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAE7B,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QAClC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACrB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,4EAA4E;IAC5E,uEAAuE;IACvE,uCAAuC;IACvC,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED,kEAAkE;AAClE,SAAgB,gBAAgB,CAC9B,MAAc,EACd,KAAe,EACf,aAAsB;IAEtB,IAAI,CAAC,OAAO,IAAI,aAAa,KAAK,CAAC;QAAE,OAAO;IAE5C,uEAAuE;IACvE,IAAI,KAAK,CAAC,IAAI,IAAI,OAAO,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACzD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,IAAI;YAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE;QAChB,KAAK;QACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,KAAK,CAAC;KACzD,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@90soft/parse-server-kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.1",
|
|
4
4
|
"description": "Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
|
-
"CLAUDE.md"
|
|
9
|
+
"CLAUDE.md",
|
|
10
|
+
"CHANGELOG.md"
|
|
10
11
|
],
|
|
11
12
|
"scripts": {
|
|
12
13
|
"build": "tsc",
|