@revealui/core 0.5.2 → 0.5.4
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/README.md +14 -0
- package/dist/cache/query-cache.d.ts.map +1 -1
- package/dist/cache/query-cache.js +12 -2
- package/dist/client/admin/layout.js +1 -1
- package/dist/collections/operations/sqlAdapter.d.ts.map +1 -1
- package/dist/collections/operations/sqlAdapter.js +37 -5
- package/dist/features.d.ts +5 -9
- package/dist/features.d.ts.map +1 -1
- package/dist/features.js +1 -3
- package/dist/globals/GlobalOperations.d.ts.map +1 -1
- package/dist/globals/GlobalOperations.js +11 -7
- package/dist/license.d.ts +1 -7
- package/dist/license.d.ts.map +1 -1
- package/dist/license.js +0 -11
- package/dist/observability/health-check.d.ts.map +1 -1
- package/dist/observability/health-check.js +7 -1
- package/dist/queries/queryBuilder.d.ts.map +1 -1
- package/dist/queries/queryBuilder.js +17 -4
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -145,6 +145,20 @@ pnpm test
|
|
|
145
145
|
pnpm dev
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
+
## When to Use This
|
|
149
|
+
|
|
150
|
+
- You're building a content-driven app and need collections, admin UI, and CRUD out of the box
|
|
151
|
+
- You need RBAC/ABAC access control, GDPR compliance, or feature gating by license tier
|
|
152
|
+
- You want a rich text editor (Lexical) integrated with your CMS
|
|
153
|
+
- **Not** for standalone UI components — use `@revealui/presentation`
|
|
154
|
+
- **Not** for raw database queries — use `@revealui/db` directly
|
|
155
|
+
|
|
156
|
+
## JOSHUA Alignment
|
|
157
|
+
|
|
158
|
+
- **Sovereign**: Self-hosted CMS engine — no SaaS dependency for content management, auth, or storage
|
|
159
|
+
- **Unified**: One `buildConfig()` call wires collections, globals, plugins, security, and feature gates into a single configuration
|
|
160
|
+
- **Adaptive**: Plugin system and tier-based feature gating let the platform evolve without breaking existing deployments
|
|
161
|
+
|
|
148
162
|
## Related
|
|
149
163
|
|
|
150
164
|
- [Contracts Package](../contracts/README.md) — Zod schemas and TypeScript types
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-cache.d.ts","sourceRoot":"","sources":["../../src/cache/query-cache.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,UAAU,YAAY;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"query-cache.d.ts","sourceRoot":"","sources":["../../src/cache/query-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -50,8 +50,18 @@ class QueryCache {
|
|
|
50
50
|
return deleted;
|
|
51
51
|
}
|
|
52
52
|
keys(pattern) {
|
|
53
|
-
const
|
|
54
|
-
|
|
53
|
+
const startsWild = pattern.startsWith('*');
|
|
54
|
+
const endsWild = pattern.endsWith('*');
|
|
55
|
+
const core = pattern.slice(startsWild ? 1 : 0, endsWild ? -1 : undefined);
|
|
56
|
+
return Array.from(this.cache.keys()).filter((key) => {
|
|
57
|
+
if (startsWild && endsWild)
|
|
58
|
+
return key.includes(core);
|
|
59
|
+
if (startsWild)
|
|
60
|
+
return key.endsWith(core);
|
|
61
|
+
if (endsWild)
|
|
62
|
+
return key.startsWith(core);
|
|
63
|
+
return key === core;
|
|
64
|
+
});
|
|
55
65
|
}
|
|
56
66
|
clear() {
|
|
57
67
|
this.cache.clear();
|
|
@@ -3,5 +3,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import Head from 'next/head';
|
|
4
4
|
import { ServerFunctionProvider } from './context/ServerFunctionContext.js';
|
|
5
5
|
export function RootLayout({ children, serverFunction }) {
|
|
6
|
-
return (_jsxs("html", { lang: "en", children: [_jsxs(Head, { children: [_jsx("meta", { charSet: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "RevealUI Admin" })] }), _jsx("body", { className: "antialiased", children: _jsx(ServerFunctionProvider, { serverFunction: serverFunction, children: _jsx("
|
|
6
|
+
return (_jsxs("html", { lang: "en", children: [_jsxs(Head, { children: [_jsx("meta", { charSet: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "RevealUI Admin" })] }), _jsx("body", { className: "antialiased", children: _jsx(ServerFunctionProvider, { serverFunction: serverFunction, children: _jsx("main", { id: "revealui-admin", className: "min-h-screen", children: children }) }) })] }));
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlAdapter.d.ts","sourceRoot":"","sources":["../../../src/collections/operations/sqlAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CACvE,CAAC;
|
|
1
|
+
{"version":3,"file":"sqlAdapter.d.ts","sourceRoot":"","sources":["../../../src/collections/operations/sqlAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CACvE,CAAC;AA6BF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAM/C;AAkBD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAMvD;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAIpF;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,MAAM,CAER;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAKjF;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAI1E;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAKrF"}
|
|
@@ -9,21 +9,53 @@
|
|
|
9
9
|
* redesign the collection storage layer toward typed tables instead.
|
|
10
10
|
*/
|
|
11
11
|
/** Only lowercase alphanumeric, hyphens, and underscores (1-63 chars, PostgreSQL identifier limit). */
|
|
12
|
-
|
|
12
|
+
function isValidSlug(s) {
|
|
13
|
+
if (s.length < 1 || s.length > 63)
|
|
14
|
+
return false;
|
|
15
|
+
// First char must be lowercase letter
|
|
16
|
+
const first = s.charCodeAt(0);
|
|
17
|
+
if (first < 97 || first > 122)
|
|
18
|
+
return false;
|
|
19
|
+
for (let i = 1; i < s.length; i++) {
|
|
20
|
+
const c = s.charCodeAt(i);
|
|
21
|
+
const isLower = c >= 97 && c <= 122;
|
|
22
|
+
const isDigit = c >= 48 && c <= 57;
|
|
23
|
+
// underscore = 95, hyphen = 45
|
|
24
|
+
if (!(isLower || isDigit || c === 95 || c === 45))
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
13
29
|
export function validateSlug(slug) {
|
|
14
|
-
if (!
|
|
30
|
+
if (!isValidSlug(slug)) {
|
|
15
31
|
throw new Error(`Invalid collection slug: "${slug}". Slugs must start with a lowercase letter and contain only lowercase alphanumeric characters, hyphens, and underscores (max 63 chars).`);
|
|
16
32
|
}
|
|
17
33
|
}
|
|
18
34
|
/** Only lowercase alphanumeric and underscores (PostgreSQL column name safe). */
|
|
19
|
-
|
|
35
|
+
function isValidColumnName(s) {
|
|
36
|
+
if (s.length < 1 || s.length > 63)
|
|
37
|
+
return false;
|
|
38
|
+
// First char must be lowercase letter or underscore
|
|
39
|
+
const first = s.charCodeAt(0);
|
|
40
|
+
const firstIsLower = first >= 97 && first <= 122;
|
|
41
|
+
if (!(firstIsLower || first === 95))
|
|
42
|
+
return false;
|
|
43
|
+
for (let i = 1; i < s.length; i++) {
|
|
44
|
+
const c = s.charCodeAt(i);
|
|
45
|
+
const isLower = c >= 97 && c <= 122;
|
|
46
|
+
const isDigit = c >= 48 && c <= 57;
|
|
47
|
+
if (!(isLower || isDigit || c === 95))
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
20
52
|
export function validateColumnName(column) {
|
|
21
|
-
if (!
|
|
53
|
+
if (!isValidColumnName(column)) {
|
|
22
54
|
throw new Error(`Invalid column name: "${column}". Column names must start with a lowercase letter or underscore and contain only lowercase alphanumeric characters and underscores.`);
|
|
23
55
|
}
|
|
24
56
|
}
|
|
25
57
|
export function escapeIdentifier(identifier) {
|
|
26
|
-
return identifier.
|
|
58
|
+
return identifier.split('"').join('""');
|
|
27
59
|
}
|
|
28
60
|
export function collectionTable(configSlug) {
|
|
29
61
|
validateSlug(configSlug);
|
package/dist/features.d.ts
CHANGED
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
import { type LicenseTier } from './license.js';
|
|
12
12
|
/** All gated features in RevealUI */
|
|
13
13
|
export interface FeatureFlags {
|
|
14
|
-
/** Local AI inference via BitNet — available at all tiers (no API key needed) */
|
|
14
|
+
/** Local AI inference via Inference Snaps or BitNet — available at all tiers (no API key needed) */
|
|
15
15
|
aiLocal: boolean;
|
|
16
|
-
/**
|
|
16
|
+
/** AI agent system — local + cloud via RevealUI harness (Pro+) */
|
|
17
17
|
ai: boolean;
|
|
18
18
|
/** AI memory system — working + episodic + vector (Max: basic, Enterprise: full) */
|
|
19
19
|
aiMemory: boolean;
|
|
@@ -27,14 +27,10 @@ export interface FeatureFlags {
|
|
|
27
27
|
whiteLabel: boolean;
|
|
28
28
|
/** SSO/SAML authentication (planned — not yet implemented) */
|
|
29
29
|
sso: boolean;
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
/** Multi-provider AI (Max+: 2 providers, Enterprise: all providers) */
|
|
33
|
-
aiMultiProvider: boolean;
|
|
30
|
+
/** Open-model inference configuration — snaps, BitNet, harness (Max+) */
|
|
31
|
+
aiInference: boolean;
|
|
34
32
|
/** Audit logging and compliance trail */
|
|
35
33
|
auditLog: boolean;
|
|
36
|
-
/** AI sampling for free users — limited cloud tasks via platform key */
|
|
37
|
-
aiSampling: boolean;
|
|
38
34
|
/** Full real-time sync with conflict resolution */
|
|
39
35
|
advancedSync: boolean;
|
|
40
36
|
/** Monitoring dashboard */
|
|
@@ -43,7 +39,7 @@ export interface FeatureFlags {
|
|
|
43
39
|
customDomain: boolean;
|
|
44
40
|
/** Analytics and conversion tracking */
|
|
45
41
|
analytics: boolean;
|
|
46
|
-
/** RevVault desktop app — Tauri
|
|
42
|
+
/** RevVault desktop app — Tauri native AI experience for encrypted secret management (Pro+) */
|
|
47
43
|
vaultDesktop: boolean;
|
|
48
44
|
/** RevVault rotation engine — automated credential lifecycle (Pro+) */
|
|
49
45
|
vaultRotation: boolean;
|
package/dist/features.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../src/features.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAE5D,qCAAqC;AACrC,MAAM,WAAW,YAAY;IAC3B,
|
|
1
|
+
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../src/features.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAE5D,qCAAqC;AACrC,MAAM,WAAW,YAAY;IAC3B,oGAAoG;IACpG,OAAO,EAAE,OAAO,CAAC;IACjB,kEAAkE;IAClE,EAAE,EAAE,OAAO,CAAC;IACZ,oFAAoF;IACpF,QAAQ,EAAE,OAAO,CAAC;IAClB,6BAA6B;IAC7B,GAAG,EAAE,OAAO,CAAC;IACb,yCAAyC;IACzC,QAAQ,EAAE,OAAO,CAAC;IAClB,mCAAmC;IACnC,WAAW,EAAE,OAAO,CAAC;IACrB,kEAAkE;IAClE,UAAU,EAAE,OAAO,CAAC;IACpB,8DAA8D;IAC9D,GAAG,EAAE,OAAO,CAAC;IACb,yEAAyE;IACzE,WAAW,EAAE,OAAO,CAAC;IACrB,yCAAyC;IACzC,QAAQ,EAAE,OAAO,CAAC;IAClB,mDAAmD;IACnD,YAAY,EAAE,OAAO,CAAC;IACtB,2BAA2B;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,wCAAwC;IACxC,SAAS,EAAE,OAAO,CAAC;IACnB,+FAA+F;IAC/F,YAAY,EAAE,OAAO,CAAC;IACtB,uEAAuE;IACvE,aAAa,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,cAAc,EAAE,OAAO,CAAC;CACzB;AA0BD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,IAAI,YAAY,CAY1C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,YAAY,GAAG,OAAO,CAMrE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,YAAY,CAmBlE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,YAAY,GAAG,WAAW,CAExE;AAED;;GAEG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/features.js
CHANGED
|
@@ -13,7 +13,6 @@ import { isLicensed } from './license.js';
|
|
|
13
13
|
const featureTierMap = {
|
|
14
14
|
aiLocal: 'free',
|
|
15
15
|
ai: 'pro',
|
|
16
|
-
aiSampling: 'free',
|
|
17
16
|
mcp: 'pro',
|
|
18
17
|
payments: 'pro',
|
|
19
18
|
advancedSync: 'pro',
|
|
@@ -21,8 +20,7 @@ const featureTierMap = {
|
|
|
21
20
|
customDomain: 'pro',
|
|
22
21
|
analytics: 'pro',
|
|
23
22
|
aiMemory: 'max',
|
|
24
|
-
|
|
25
|
-
aiMultiProvider: 'max',
|
|
23
|
+
aiInference: 'max',
|
|
26
24
|
auditLog: 'max',
|
|
27
25
|
multiTenant: 'enterprise',
|
|
28
26
|
// NOTE: whiteLabel and sso are planned but not yet implemented.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalOperations.d.ts","sourceRoot":"","sources":["../../src/globals/GlobalOperations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GlobalOperations.d.ts","sourceRoot":"","sources":["../../src/globals/GlobalOperations.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,aAAa,EAEd,MAAM,mBAAmB,CAAC;AAG3B;;;;GAIG;AACH,qBAAa,cAAc;IACzB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,EAAE,EAAE;QACF,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;KACvE,GAAG,IAAI,CAAC;gBAGP,MAAM,EAAE,kBAAkB,EAC1B,EAAE,EAAE;QACF,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;KACvE,GAAG,IAAI;IAMJ,IAAI,CACR,OAAO,GAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,OAAO,mBAAmB,EAAE,YAAY,CAAC;QACpD,GAAG,CAAC,EAAE,aAAa,CAAC;KAChB,GACL,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAwG3B,MAAM,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC;CAqElF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { validateColumnName, validateSlug } from '../collections/operations/sqlAdapter.js';
|
|
1
|
+
import { escapeIdentifier, validateColumnName, validateSlug, } from '../collections/operations/sqlAdapter.js';
|
|
2
2
|
import { afterRead } from '../fields/hooks/afterRead/index.js';
|
|
3
3
|
import { getRelationshipFields } from '../relationships/analyzer.js';
|
|
4
4
|
import { flattenResult } from '../utils/flattenResult.js';
|
|
@@ -22,7 +22,10 @@ export class RevealUIGlobal {
|
|
|
22
22
|
}
|
|
23
23
|
if (this.db?.query) {
|
|
24
24
|
const slug = this.config.slug;
|
|
25
|
-
|
|
25
|
+
try {
|
|
26
|
+
validateSlug(slug);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
26
29
|
throw new Error(`Invalid global slug: "${slug}". Must be lowercase alphanumeric with hyphens/underscores.`);
|
|
27
30
|
}
|
|
28
31
|
const tableName = `global_${slug}`;
|
|
@@ -101,7 +104,10 @@ export class RevealUIGlobal {
|
|
|
101
104
|
const { data } = options;
|
|
102
105
|
if (this.db?.query) {
|
|
103
106
|
const slug = this.config.slug;
|
|
104
|
-
|
|
107
|
+
try {
|
|
108
|
+
validateSlug(slug);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
105
111
|
throw new Error(`Invalid global slug: "${slug}". Must be lowercase alphanumeric with hyphens/underscores.`);
|
|
106
112
|
}
|
|
107
113
|
const tableName = `global_${slug}`;
|
|
@@ -114,9 +120,7 @@ export class RevealUIGlobal {
|
|
|
114
120
|
const keys = Object.keys(data);
|
|
115
121
|
for (const key of keys)
|
|
116
122
|
validateColumnName(key);
|
|
117
|
-
const setClause = keys
|
|
118
|
-
.map((key, i) => `"${key.replace(/"/g, '""')}" = $${i + 1}`)
|
|
119
|
-
.join(', ');
|
|
123
|
+
const setClause = keys.map((key, i) => `"${escapeIdentifier(key)}" = $${i + 1}`).join(', ');
|
|
120
124
|
const values = keys.map((key) => {
|
|
121
125
|
const value = data[key];
|
|
122
126
|
// Serialize non-primitive values to JSON strings for SQLite compatibility
|
|
@@ -147,7 +151,7 @@ export class RevealUIGlobal {
|
|
|
147
151
|
}
|
|
148
152
|
return value;
|
|
149
153
|
});
|
|
150
|
-
const query = `INSERT INTO "${tableName}" (id, ${columns.map((c) => `"${c
|
|
154
|
+
const query = `INSERT INTO "${tableName}" (id, ${columns.map((c) => `"${escapeIdentifier(c)}"`).join(', ')}) VALUES ($1, ${placeholders})`;
|
|
151
155
|
await this.db.query(query, [id, ...values]);
|
|
152
156
|
}
|
|
153
157
|
const updatedDoc = await this.find();
|
package/dist/license.d.ts
CHANGED
|
@@ -11,8 +11,8 @@ export type LicenseTier = 'free' | 'pro' | 'max' | 'enterprise';
|
|
|
11
11
|
/** Decoded license payload schema */
|
|
12
12
|
declare const licensePayloadSchema: z.ZodObject<{
|
|
13
13
|
tier: z.ZodEnum<{
|
|
14
|
-
max: "max";
|
|
15
14
|
pro: "pro";
|
|
15
|
+
max: "max";
|
|
16
16
|
enterprise: "enterprise";
|
|
17
17
|
}>;
|
|
18
18
|
customerId: z.ZodString;
|
|
@@ -78,12 +78,6 @@ export declare function getMaxUsers(): number;
|
|
|
78
78
|
* Track B metering: free=1K, pro=10K, max=50K, enterprise=unlimited.
|
|
79
79
|
*/
|
|
80
80
|
export declare function getMaxAgentTasks(): number;
|
|
81
|
-
/**
|
|
82
|
-
* Returns the maximum free-tier AI sampling tasks per billing cycle.
|
|
83
|
-
* Free users get 50 cloud AI tasks/month via platform Groq key.
|
|
84
|
-
* Paid users return 0 (they use full quota via getMaxAgentTasks instead).
|
|
85
|
-
*/
|
|
86
|
-
export declare function getMaxFreemiumTasks(): number;
|
|
87
81
|
/**
|
|
88
82
|
* Generates a signed license key JWT.
|
|
89
83
|
* This is a server-only function — requires the private key.
|
package/dist/license.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,8BAA8B;AAC9B,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,YAAY,CAAC;AAEhE,qCAAqC;AACrC,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;iBAqBxB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;CACf;AASD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAElF;AAoCD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA0BhC;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,WAAW,CAAC,CAkC9D;AAaD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAG5C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,IAAI,CAGzD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,WAAW,GAAG,OAAO,CAqB7D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AAED
|
|
1
|
+
{"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,8BAA8B;AAC9B,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,YAAY,CAAC;AAEhE,qCAAqC;AACrC,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;iBAqBxB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;CACf;AASD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAElF;AAoCD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA0BhC;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,WAAW,CAAC,CAkC9D;AAaD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAG5C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,IAAI,CAGzD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,WAAW,GAAG,OAAO,CAqB7D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,KAAK,CAAC,EAC5C,UAAU,EAAE,MAAM,EAClB,gBAAgB,GAAE,MAAM,GAAG,IAAyB,EACpD,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
|
package/dist/license.js
CHANGED
|
@@ -228,17 +228,6 @@ export function getMaxAgentTasks() {
|
|
|
228
228
|
return 10_000;
|
|
229
229
|
return 1_000;
|
|
230
230
|
}
|
|
231
|
-
/**
|
|
232
|
-
* Returns the maximum free-tier AI sampling tasks per billing cycle.
|
|
233
|
-
* Free users get 50 cloud AI tasks/month via platform Groq key.
|
|
234
|
-
* Paid users return 0 (they use full quota via getMaxAgentTasks instead).
|
|
235
|
-
*/
|
|
236
|
-
export function getMaxFreemiumTasks() {
|
|
237
|
-
evictStaleCache();
|
|
238
|
-
if (cachedState.tier === 'free')
|
|
239
|
-
return 50;
|
|
240
|
-
return 0;
|
|
241
|
-
}
|
|
242
231
|
/**
|
|
243
232
|
* Generates a signed license key JWT.
|
|
244
233
|
* This is a server-only function — requires the private key.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health-check.d.ts","sourceRoot":"","sources":["../../src/observability/health-check.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,SAAS,CAAsB;IAEvC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAIlC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC;IAoD1C;;OAEG;YACW,cAAc;IAS5B;;OAEG;IACH,SAAS,IAAI,MAAM;CAGpB;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,mBAA0B,CAAC;AAEnD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"health-check.d.ts","sourceRoot":"","sources":["../../src/observability/health-check.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,SAAS,CAAsB;IAEvC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAIlC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC;IAoD1C;;OAEG;YACW,cAAc;IAS5B;;OAEG;IACH,SAAS,IAAI,MAAM;CAGpB;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,mBAA0B,CAAC;AAEnD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,CAmCnF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,gBAAgB,GAAE,MAAW,GAAG,WAAW,CAwClF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,gBAAgB,GAAE,MAAW,GAAG,WAAW,CA4ChF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,GAAE,MAAY,GAAG,WAAW,CAuC3F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,OAAO,CAAC,iBAAiB,CAAC,EACzC,QAAQ,GAAE,OAAe,GACxB,WAAW,CAMb;AAED;;GAEG;AACH,wBAAgB,oBAAoB,UACjB,OAAO,CAAC,QAAQ,CAAC,CAanC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,UACpB,OAAO,CAAC,QAAQ,CAAC,CA2BnC;AAED;;GAEG;AACH,wBAAgB,sBAAsB,UACzB,QAAQ,CAqBpB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,UAAU,GAAE,MAAc,EAC1B,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAC9C,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAsBzB"}
|
|
@@ -115,9 +115,15 @@ export function createDatabaseHealthCheck(queryFn) {
|
|
|
115
115
|
};
|
|
116
116
|
}
|
|
117
117
|
catch (error) {
|
|
118
|
+
// Surface the root cause — Drizzle wraps Neon errors with "Failed query: ..."
|
|
119
|
+
// but the actual HTTP/connection error is in .cause
|
|
120
|
+
let message = error instanceof Error ? error.message : 'Database connection failed';
|
|
121
|
+
if (error instanceof Error && error.cause instanceof Error) {
|
|
122
|
+
message = `${message} | cause: ${error.cause.message}`;
|
|
123
|
+
}
|
|
118
124
|
return {
|
|
119
125
|
status: 'unhealthy',
|
|
120
|
-
message
|
|
126
|
+
message,
|
|
121
127
|
};
|
|
122
128
|
}
|
|
123
129
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryBuilder.d.ts","sourceRoot":"","sources":["../../src/queries/queryBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAExE;;;;;GAKG;AAEH,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"queryBuilder.d.ts","sourceRoot":"","sources":["../../src/queries/queryBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAExE;;;;;GAKG;AAEH,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,YAAY,CAAC;AAevD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,WAAW,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,SAAS,EAC3D,MAAM,EAAE,OAAO,EAAE,EACjB,OAAO,GAAE,iBAAsB,GAC9B,MAAM,CA0NR;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,EAAE,CAoEjE"}
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/** Escape SQL LIKE wildcards (%, _, \) in user input */
|
|
2
|
+
function escapeLikeWildcards(value) {
|
|
3
|
+
let result = '';
|
|
4
|
+
for (const ch of value) {
|
|
5
|
+
if (ch === '%' || ch === '_' || ch === '\\') {
|
|
6
|
+
result += `\\${ch}`;
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
result += ch;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
1
14
|
/**
|
|
2
15
|
* Builds a WHERE clause from a RevealWhere query object.
|
|
3
16
|
* Supports nested AND/OR conditions and various operators.
|
|
@@ -27,7 +40,7 @@ export function buildWhereClause(where, params, options = {}) {
|
|
|
27
40
|
if (!quoteFields)
|
|
28
41
|
return field;
|
|
29
42
|
// Escape embedded double quotes to prevent SQL injection via identifier breakout
|
|
30
|
-
const escaped = field.
|
|
43
|
+
const escaped = field.split('"').join('""');
|
|
31
44
|
return `"${escaped}"`;
|
|
32
45
|
};
|
|
33
46
|
const whereWithGroups = where;
|
|
@@ -149,7 +162,7 @@ export function buildWhereClause(where, params, options = {}) {
|
|
|
149
162
|
if ('contains' in condition && typeof condition.contains === 'string') {
|
|
150
163
|
const placeholder = getPlaceholder();
|
|
151
164
|
// Escape LIKE wildcards (% and _) in user input to prevent wildcard injection
|
|
152
|
-
const escaped = condition.contains
|
|
165
|
+
const escaped = escapeLikeWildcards(condition.contains);
|
|
153
166
|
params.push(`%${escaped}%`);
|
|
154
167
|
conditions.push(`${quotedField} LIKE ${placeholder} ESCAPE '\\'`);
|
|
155
168
|
}
|
|
@@ -168,7 +181,7 @@ export function buildWhereClause(where, params, options = {}) {
|
|
|
168
181
|
// like (escape wildcards to prevent blind LIKE probing)
|
|
169
182
|
if ('like' in condition && typeof condition.like === 'string') {
|
|
170
183
|
const placeholder = getPlaceholder();
|
|
171
|
-
const escaped = condition.like
|
|
184
|
+
const escaped = escapeLikeWildcards(condition.like);
|
|
172
185
|
params.push(escaped);
|
|
173
186
|
conditions.push(`${quotedField} LIKE ${placeholder} ESCAPE '\\'`);
|
|
174
187
|
}
|
|
@@ -219,7 +232,7 @@ export function extractWhereValues(where) {
|
|
|
219
232
|
break;
|
|
220
233
|
case 'contains':
|
|
221
234
|
if (typeof value === 'string') {
|
|
222
|
-
const escaped = value
|
|
235
|
+
const escaped = escapeLikeWildcards(value);
|
|
223
236
|
values.push(`%${escaped}%`);
|
|
224
237
|
}
|
|
225
238
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revealui/core",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
|
+
"description": "CMS engine, REST API, auth, rich text, admin UI, and plugins for RevealUI",
|
|
4
5
|
"license": "MIT",
|
|
5
6
|
"dependencies": {
|
|
6
7
|
"@electric-sql/pglite": "^0.4.2",
|
|
@@ -23,11 +24,11 @@
|
|
|
23
24
|
"pg": "^8.18.0",
|
|
24
25
|
"yjs": "^13.6.29",
|
|
25
26
|
"zod": "^4.3.6",
|
|
26
|
-
"@revealui/
|
|
27
|
-
"@revealui/
|
|
28
|
-
"@revealui/
|
|
29
|
-
"@revealui/
|
|
30
|
-
"@revealui/
|
|
27
|
+
"@revealui/cache": "0.1.2",
|
|
28
|
+
"@revealui/contracts": "1.3.5",
|
|
29
|
+
"@revealui/resilience": "0.2.2",
|
|
30
|
+
"@revealui/security": "0.2.5",
|
|
31
|
+
"@revealui/utils": "0.3.2"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@types/json-schema": "^7.0.15",
|
|
@@ -212,6 +213,10 @@
|
|
|
212
213
|
"types": "./dist/observability/logger.d.ts",
|
|
213
214
|
"import": "./dist/observability/logger.js"
|
|
214
215
|
},
|
|
216
|
+
"./observability/alerts": {
|
|
217
|
+
"types": "./dist/observability/alerts.d.ts",
|
|
218
|
+
"import": "./dist/observability/alerts.js"
|
|
219
|
+
},
|
|
215
220
|
"./utils/cache": {
|
|
216
221
|
"types": "./dist/utils/cache.d.ts",
|
|
217
222
|
"import": "./dist/utils/cache.js"
|