@happyvertical/smrt-types 0.30.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.
- package/AGENTS.md +18 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/README.md +61 -0
- package/dist/index.d.ts +927 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @happyvertical/smrt-types
|
|
2
|
+
|
|
3
|
+
Shared TypeScript type definitions. Prevents circular dependencies between packages.
|
|
4
|
+
|
|
5
|
+
## Exports
|
|
6
|
+
|
|
7
|
+
| File | Types |
|
|
8
|
+
|------|-------|
|
|
9
|
+
| `signals.ts` | `Signal`, `SignalType`, `SignalAdapter` — universal signaling system |
|
|
10
|
+
| `module.ts` | `SmrtModuleMeta`, `ModuleUISlot`, `ModuleComponentType` — module registration and UI slots |
|
|
11
|
+
| `user.ts` | `UserStatus`, `TenantStatus`, `MembershipStatus`, `SessionStatus`, `OverrideEffect` — status enums |
|
|
12
|
+
| `identity.ts` | `User`, `Tenant`, `Role`, `Membership`, `SmrtEntityFields` — cross-package identity data contracts (runtime classes live in smrt-users, which `implements` these) |
|
|
13
|
+
|
|
14
|
+
## Rules
|
|
15
|
+
|
|
16
|
+
- **Zero runtime code**: only type definitions and enums
|
|
17
|
+
- **Always `import type`**: use `import type { Signal }` to avoid runtime imports (except enums which have runtime values)
|
|
18
|
+
- **Add shared types here**: if two+ packages need the same type, put it here instead of in `smrt-core`
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright <2025> <Happy Vertical Corporation>
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @happyvertical/smrt-types
|
|
2
|
+
|
|
3
|
+
Shared TypeScript type definitions for the SMRT framework. Prevents circular dependencies by centralizing types that multiple packages need.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @happyvertical/smrt-types
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// Import types (use `import type` for type-only imports)
|
|
15
|
+
import type { Signal, SignalType, SignalAdapter } from '@happyvertical/smrt-types';
|
|
16
|
+
import type { SmrtModuleMeta, ModuleUISlot } from '@happyvertical/smrt-types';
|
|
17
|
+
|
|
18
|
+
// Enums have runtime values — use regular import
|
|
19
|
+
import { UserStatus, TenantStatus, MembershipStatus } from '@happyvertical/smrt-types';
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Exports
|
|
23
|
+
|
|
24
|
+
### Signal System (types)
|
|
25
|
+
|
|
26
|
+
| Export | Description |
|
|
27
|
+
|--------|------------|
|
|
28
|
+
| `Signal` | Signal payload with lifecycle info (id, className, method, duration, etc.) |
|
|
29
|
+
| `SignalType` | Signal lifecycle stage: `'start'` \| `'step'` \| `'end'` \| `'error'` |
|
|
30
|
+
| `SignalAdapter` | Interface for signal processors (logging, metrics, pub/sub) |
|
|
31
|
+
|
|
32
|
+
### Module UI (types)
|
|
33
|
+
|
|
34
|
+
| Export | Description |
|
|
35
|
+
|--------|------------|
|
|
36
|
+
| `SmrtModuleMeta` | Module metadata (name, version, description) |
|
|
37
|
+
| `ModuleUISlot` | UI slot definition for module admin panels |
|
|
38
|
+
| `ModuleComponentType` | Component type classification |
|
|
39
|
+
| `ModuleUIBaseProps` | Base props interface for module UI components |
|
|
40
|
+
| `ModuleUIRegistryInterface` | Registry interface for module UI registration |
|
|
41
|
+
|
|
42
|
+
### User/Tenant Status (enums — runtime values)
|
|
43
|
+
|
|
44
|
+
| Export | Description |
|
|
45
|
+
|--------|------------|
|
|
46
|
+
| `UserStatus` | User lifecycle status |
|
|
47
|
+
| `TenantStatus` | Tenant lifecycle status |
|
|
48
|
+
| `MembershipStatus` | Membership lifecycle status |
|
|
49
|
+
| `SessionStatus` | Session lifecycle status |
|
|
50
|
+
| `OverrideEffect` | Permission override effect |
|
|
51
|
+
| `TenantPermissionEffect` | Tenant-level permission effect |
|
|
52
|
+
|
|
53
|
+
## Rules
|
|
54
|
+
|
|
55
|
+
- **Zero runtime code** except enums (which require runtime values)
|
|
56
|
+
- **Use `import type`** for non-enum imports to avoid unnecessary runtime dependencies
|
|
57
|
+
- **Add shared types here** if two or more packages need the same type definition
|
|
58
|
+
|
|
59
|
+
## Dependencies
|
|
60
|
+
|
|
61
|
+
None. This is a leaf package with zero dependencies.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,927 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared AI usage tracking types for SMRT.
|
|
3
|
+
*
|
|
4
|
+
* These types are intentionally provider-agnostic so SMRT can normalize
|
|
5
|
+
* telemetry emitted by the underlying AI SDK into a stable internal shape.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Normalized token usage information for an AI call.
|
|
9
|
+
*/
|
|
10
|
+
export declare interface AiTokenUsage {
|
|
11
|
+
/** Number of input tokens consumed by the request */
|
|
12
|
+
promptTokens?: number;
|
|
13
|
+
/** Number of output tokens produced by the response */
|
|
14
|
+
completionTokens?: number;
|
|
15
|
+
/** Total tokens consumed across the call */
|
|
16
|
+
totalTokens?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Grouping dimensions supported by summary helpers.
|
|
21
|
+
*/
|
|
22
|
+
export declare type AiUsageGroupBy = 'provider' | 'model' | 'class' | 'tenant' | 'operation' | 'day';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Callback interface for handling normalized AI usage events.
|
|
26
|
+
*/
|
|
27
|
+
export declare interface AiUsageHandler {
|
|
28
|
+
/**
|
|
29
|
+
* Handle a normalized AI usage event.
|
|
30
|
+
*/
|
|
31
|
+
handle(event: SmrtAiUsageEvent): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Options for listing raw AI usage records from persistence.
|
|
36
|
+
*/
|
|
37
|
+
export declare interface AiUsageListOptions {
|
|
38
|
+
/** Only include records on or after this timestamp */
|
|
39
|
+
since?: Date;
|
|
40
|
+
/** Only include records before or at this timestamp */
|
|
41
|
+
until?: Date;
|
|
42
|
+
/** Filter by provider */
|
|
43
|
+
provider?: string;
|
|
44
|
+
/** Filter by model */
|
|
45
|
+
model?: string;
|
|
46
|
+
/** Filter by operation */
|
|
47
|
+
operation?: string;
|
|
48
|
+
/** Filter by SMRT class name */
|
|
49
|
+
className?: string;
|
|
50
|
+
/** Filter by tenant ID */
|
|
51
|
+
tenantId?: string | null;
|
|
52
|
+
/** Maximum number of rows to return */
|
|
53
|
+
limit?: number;
|
|
54
|
+
/** Number of rows to skip */
|
|
55
|
+
offset?: number;
|
|
56
|
+
/** Sort order */
|
|
57
|
+
orderBy?: 'timestamp DESC' | 'timestamp ASC';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* In-memory snapshot returned by the collector.
|
|
62
|
+
*/
|
|
63
|
+
export declare interface AiUsageSnapshot {
|
|
64
|
+
/** Usage aggregated by "provider:model" */
|
|
65
|
+
byModel: Record<string, AiUsageStats>;
|
|
66
|
+
/** Usage aggregated by "className:operation" */
|
|
67
|
+
byClass: Record<string, AiUsageStats>;
|
|
68
|
+
/** Total number of calls observed by the collector */
|
|
69
|
+
totalCalls: number;
|
|
70
|
+
/** Collector start time in epoch milliseconds */
|
|
71
|
+
startTime: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Aggregated statistics bucket for AI usage reporting.
|
|
76
|
+
*/
|
|
77
|
+
export declare interface AiUsageStats {
|
|
78
|
+
/** Number of calls represented in the bucket */
|
|
79
|
+
callCount: number;
|
|
80
|
+
/** Sum of prompt/input tokens */
|
|
81
|
+
promptTokens: number;
|
|
82
|
+
/** Sum of completion/output tokens */
|
|
83
|
+
completionTokens: number;
|
|
84
|
+
/** Sum of total tokens */
|
|
85
|
+
totalTokens: number;
|
|
86
|
+
/** Sum of durations in milliseconds */
|
|
87
|
+
totalDuration: number;
|
|
88
|
+
/** Sum of estimated costs in USD */
|
|
89
|
+
estimatedCost: number;
|
|
90
|
+
/** Timestamp of the most recent event in epoch milliseconds */
|
|
91
|
+
lastUsed: number;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Options for summarized AI usage queries.
|
|
96
|
+
*/
|
|
97
|
+
export declare interface AiUsageSummaryOptions extends Omit<AiUsageListOptions, 'limit' | 'offset' | 'orderBy'> {
|
|
98
|
+
/** Dimension to group summary buckets by */
|
|
99
|
+
groupBy?: AiUsageGroupBy;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Per-object configuration controlling domain-knowledge generation and exposure. */
|
|
103
|
+
export declare interface DomainKnowledgeConfig {
|
|
104
|
+
enabled?: boolean;
|
|
105
|
+
api?: {
|
|
106
|
+
/**
|
|
107
|
+
* Generate HTTP knowledge routes. Disabled by default; prefer CLI/MCP for
|
|
108
|
+
* agent workflows unless this is a guarded dev/admin endpoint.
|
|
109
|
+
*/
|
|
110
|
+
enabled?: boolean;
|
|
111
|
+
basePath?: string;
|
|
112
|
+
includeDocs?: boolean;
|
|
113
|
+
includePrompts?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Require dev mode or admin locals for HTTP knowledge access. Setting this
|
|
116
|
+
* to false makes the route public and should only be used when sanitized
|
|
117
|
+
* anonymous schema/surface metadata is acceptable.
|
|
118
|
+
*/
|
|
119
|
+
requireAdmin?: boolean;
|
|
120
|
+
};
|
|
121
|
+
includeDocs?: boolean;
|
|
122
|
+
includePrompts?: boolean;
|
|
123
|
+
tags?: string[];
|
|
124
|
+
summary?: string;
|
|
125
|
+
risks?: string[];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Result of a domain-knowledge freshness check (stale references, error/warning counts). */
|
|
129
|
+
export declare interface DomainKnowledgeFreshnessResult {
|
|
130
|
+
ok: boolean;
|
|
131
|
+
checkedAt: string;
|
|
132
|
+
artifactPath?: string;
|
|
133
|
+
issueCount: number;
|
|
134
|
+
errorCount: number;
|
|
135
|
+
warningCount: number;
|
|
136
|
+
issues: Array<{
|
|
137
|
+
severity: 'error' | 'warning';
|
|
138
|
+
code: string;
|
|
139
|
+
message: string;
|
|
140
|
+
file?: string;
|
|
141
|
+
packageName?: string;
|
|
142
|
+
}>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** The package-level domain-knowledge artifact (`smrt-knowledge.json`) — the agent/developer contract. */
|
|
146
|
+
export declare interface DomainKnowledgeManifest {
|
|
147
|
+
schemaVersion: 1;
|
|
148
|
+
generatedAt: string;
|
|
149
|
+
packageName?: string;
|
|
150
|
+
packageVersion?: string;
|
|
151
|
+
sourceManifestPath?: string;
|
|
152
|
+
agentDocPath?: string;
|
|
153
|
+
sourceHashes: Record<string, string>;
|
|
154
|
+
exports: string[];
|
|
155
|
+
dependencies: Record<string, string>;
|
|
156
|
+
smrtDependencies: string[];
|
|
157
|
+
sdkDependencies: string[];
|
|
158
|
+
tags: string[];
|
|
159
|
+
summary?: string;
|
|
160
|
+
risks: string[];
|
|
161
|
+
objects: DomainKnowledgeObject[];
|
|
162
|
+
surfaces: DomainKnowledgeSurface[];
|
|
163
|
+
prompts: Array<{
|
|
164
|
+
filePath: string;
|
|
165
|
+
key?: string;
|
|
166
|
+
}>;
|
|
167
|
+
relationshipsV2: {
|
|
168
|
+
foreignKeyFields: number;
|
|
169
|
+
crossPackageRefFields: number;
|
|
170
|
+
junctionCollections: number;
|
|
171
|
+
hierarchicalObjects: number;
|
|
172
|
+
polymorphicAssociations: number;
|
|
173
|
+
uuidColumns: number;
|
|
174
|
+
};
|
|
175
|
+
agentDoc?: string;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** One object's entry in the domain-knowledge manifest (fields, relationships, surfaces). */
|
|
179
|
+
export declare interface DomainKnowledgeObject {
|
|
180
|
+
name: string;
|
|
181
|
+
qualifiedName?: string;
|
|
182
|
+
collection: string;
|
|
183
|
+
tableName?: string;
|
|
184
|
+
packageName?: string;
|
|
185
|
+
extends?: string;
|
|
186
|
+
visibility?: string;
|
|
187
|
+
fields: Array<{
|
|
188
|
+
name: string;
|
|
189
|
+
type: string;
|
|
190
|
+
required?: boolean;
|
|
191
|
+
related?: string;
|
|
192
|
+
columnType?: string;
|
|
193
|
+
}>;
|
|
194
|
+
relationships: Array<{
|
|
195
|
+
name: string;
|
|
196
|
+
type: string;
|
|
197
|
+
required?: boolean;
|
|
198
|
+
related?: string;
|
|
199
|
+
columnType?: string;
|
|
200
|
+
}>;
|
|
201
|
+
methods: string[];
|
|
202
|
+
surfaces: DomainKnowledgeSurface[];
|
|
203
|
+
relationshipFeatures: string[];
|
|
204
|
+
tags: string[];
|
|
205
|
+
summary?: string;
|
|
206
|
+
risks: string[];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** A single generated surface (one api/cli/mcp/ai operation) exposed by an object. */
|
|
210
|
+
export declare interface DomainKnowledgeSurface {
|
|
211
|
+
kind: DomainKnowledgeSurfaceKind;
|
|
212
|
+
name: string;
|
|
213
|
+
operation: string;
|
|
214
|
+
path?: string;
|
|
215
|
+
method?: string;
|
|
216
|
+
description?: string;
|
|
217
|
+
objectName?: string;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** Kind of generated surface a knowledge entry describes (REST/CLI/MCP/AI). */
|
|
221
|
+
export declare type DomainKnowledgeSurfaceKind = 'api' | 'cli' | 'mcp' | 'ai';
|
|
222
|
+
|
|
223
|
+
/** User↔Tenant↔Role junction. Runtime class: `@happyvertical/smrt-users:Membership`. */
|
|
224
|
+
export declare interface Membership extends SmrtEntityFields {
|
|
225
|
+
userId?: string;
|
|
226
|
+
tenantId?: string;
|
|
227
|
+
roleId?: string;
|
|
228
|
+
status: MembershipStatus;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Status of a user's membership within a specific tenant.
|
|
233
|
+
*
|
|
234
|
+
* A user may hold memberships in multiple tenants simultaneously, each with an
|
|
235
|
+
* independent `MembershipStatus`.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```typescript
|
|
239
|
+
* const active = memberships.filter(m => m.status === MembershipStatus.ACTIVE);
|
|
240
|
+
* ```
|
|
241
|
+
*
|
|
242
|
+
* @see {@link UserStatus} for the global account-level status
|
|
243
|
+
* @see {@link TenantStatus} for the status of the tenant itself
|
|
244
|
+
*/
|
|
245
|
+
export declare enum MembershipStatus {
|
|
246
|
+
/** Active membership */
|
|
247
|
+
ACTIVE = "active",
|
|
248
|
+
/** Inactive membership */
|
|
249
|
+
INACTIVE = "inactive",
|
|
250
|
+
/** Pending invitation acceptance */
|
|
251
|
+
PENDING = "pending"
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Generic component type for SMRT module UI slots.
|
|
256
|
+
*
|
|
257
|
+
* Intentionally opaque — defined as a loose function signature rather than
|
|
258
|
+
* `import('svelte').ComponentType` to avoid pulling Svelte (and its DOM types)
|
|
259
|
+
* into server-side Node.js builds. The actual Svelte component constructor
|
|
260
|
+
* is assignable to this type at runtime.
|
|
261
|
+
*
|
|
262
|
+
* @typeParam Props - The props interface the component accepts; defaults to `unknown`.
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* ```typescript
|
|
266
|
+
* import InvoiceCard from './InvoiceCard.svelte';
|
|
267
|
+
* // InvoiceCard is assignable to ModuleComponentType<InvoiceCardProps>
|
|
268
|
+
* registry.register('@happyvertical/smrt-commerce', 'invoice-card', InvoiceCard);
|
|
269
|
+
* ```
|
|
270
|
+
*
|
|
271
|
+
* @see {@link ModuleUIBaseProps} for the base props all slot components receive
|
|
272
|
+
* @see {@link ModuleUIRegistryInterface} for storing and retrieving components
|
|
273
|
+
*/
|
|
274
|
+
export declare type ModuleComponentType<Props = unknown> = (...args: any[]) => any;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Base props contract for all SMRT module UI slot components.
|
|
278
|
+
*
|
|
279
|
+
* Every component registered against a `ModuleUISlot` should accept at least
|
|
280
|
+
* these props. Individual slot components may extend this interface with
|
|
281
|
+
* slot-specific required props.
|
|
282
|
+
*
|
|
283
|
+
* @typeParam TData - Shape of the primary data object(s) the component renders.
|
|
284
|
+
* @typeParam TConfig - Shape of the optional configuration/settings object.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```typescript
|
|
288
|
+
* interface InvoiceCardProps extends ModuleUIBaseProps<Invoice> {
|
|
289
|
+
* showLineItems?: boolean;
|
|
290
|
+
* }
|
|
291
|
+
* ```
|
|
292
|
+
*
|
|
293
|
+
* @see {@link ModuleComponentType} for the component type that accepts these props
|
|
294
|
+
* @see {@link ModuleUISlot} for the slot declaration that names the `propsInterface`
|
|
295
|
+
*/
|
|
296
|
+
export declare interface ModuleUIBaseProps<TData = unknown, TConfig = unknown> {
|
|
297
|
+
/** Primary data object(s) the component operates on */
|
|
298
|
+
data?: TData;
|
|
299
|
+
/** Configuration/settings */
|
|
300
|
+
config?: TConfig;
|
|
301
|
+
/** Callback for data changes */
|
|
302
|
+
onChange?: (data: TData) => void | Promise<void>;
|
|
303
|
+
/** Callback for saving */
|
|
304
|
+
onSave?: (data: TData) => Promise<void>;
|
|
305
|
+
/** Whether component is read-only */
|
|
306
|
+
readonly?: boolean;
|
|
307
|
+
/** CSS class for styling */
|
|
308
|
+
class?: string;
|
|
309
|
+
/** Loading state */
|
|
310
|
+
loading?: boolean;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Registry interface for mapping SMRT module slots to Svelte components.
|
|
315
|
+
*
|
|
316
|
+
* Implemented by `ModuleUIRegistry` in `@happyvertical/smrt-ui`. Consumers
|
|
317
|
+
* call `register()` once per slot at Svelte package initialisation time and
|
|
318
|
+
* `get()` when rendering to retrieve the correct component.
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* ```typescript
|
|
322
|
+
* // Registration (in packages/commerce/src/svelte/index.ts)
|
|
323
|
+
* ModuleUIRegistry.registerModule(COMMERCE_MODULE_META);
|
|
324
|
+
* ModuleUIRegistry.register('@happyvertical/smrt-commerce', 'invoice-card', InvoiceCard);
|
|
325
|
+
*
|
|
326
|
+
* // Retrieval (in a host Svelte app)
|
|
327
|
+
* const InvoiceCard = ModuleUIRegistry.get('@happyvertical/smrt-commerce', 'invoice-card');
|
|
328
|
+
* ```
|
|
329
|
+
*
|
|
330
|
+
* @see {@link SmrtModuleMeta} for the module metadata structure passed to `registerModule()`
|
|
331
|
+
* @see {@link ModuleUISlot} for the slot identifiers used as `slotId`
|
|
332
|
+
* @see {@link ModuleComponentType} for the component type stored in the registry
|
|
333
|
+
*/
|
|
334
|
+
export declare interface ModuleUIRegistryInterface {
|
|
335
|
+
/** Register a component for a module's slot */
|
|
336
|
+
register<TProps extends ModuleUIBaseProps>(moduleName: string, slotId: string, component: ModuleComponentType<TProps>): void;
|
|
337
|
+
/** Get a component for a module's slot */
|
|
338
|
+
get<TProps extends ModuleUIBaseProps>(moduleName: string, slotId: string): ModuleComponentType<TProps> | undefined;
|
|
339
|
+
/** Check if component is registered */
|
|
340
|
+
has(moduleName: string, slotId: string): boolean;
|
|
341
|
+
/** Get all registered slot IDs for a module */
|
|
342
|
+
getSlots(moduleName: string): string[];
|
|
343
|
+
/** Get all registered module names */
|
|
344
|
+
getModules(): string[];
|
|
345
|
+
/** Get module metadata */
|
|
346
|
+
getModuleMeta(moduleName: string): SmrtModuleMeta | undefined;
|
|
347
|
+
/** Register module metadata */
|
|
348
|
+
registerModule(meta: SmrtModuleMeta): void;
|
|
349
|
+
/** Unregister for testing */
|
|
350
|
+
unregister(moduleName: string, slotId: string): boolean;
|
|
351
|
+
/** Clear all for testing */
|
|
352
|
+
clear(): void;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Module type definitions for SMRT Framework
|
|
357
|
+
*
|
|
358
|
+
* These types allow SMRT modules to declare their capabilities,
|
|
359
|
+
* including models, collections, and optional Svelte UI components.
|
|
360
|
+
*
|
|
361
|
+
* @example Module with UI components
|
|
362
|
+
* ```typescript
|
|
363
|
+
* // In core module: packages/commerce/src/ui.ts
|
|
364
|
+
* import type { SmrtModuleMeta, ModuleUISlot } from '@happyvertical/smrt-types';
|
|
365
|
+
*
|
|
366
|
+
* export const COMMERCE_UI_SLOTS: Record<string, ModuleUISlot> = {
|
|
367
|
+
* 'invoice-card': { id: 'invoice-card', label: 'Invoice Card', category: 'display' },
|
|
368
|
+
* };
|
|
369
|
+
*
|
|
370
|
+
* export const COMMERCE_MODULE_META: SmrtModuleMeta = {
|
|
371
|
+
* name: '@happyvertical/smrt-commerce',
|
|
372
|
+
* displayName: 'Commerce',
|
|
373
|
+
* uiSlots: COMMERCE_UI_SLOTS,
|
|
374
|
+
* };
|
|
375
|
+
*
|
|
376
|
+
* // In svelte subpath: packages/commerce/src/svelte/index.ts
|
|
377
|
+
* import { ModuleUIRegistry } from '@happyvertical/smrt-ui/registry';
|
|
378
|
+
* import { COMMERCE_MODULE_META } from '../ui.js';
|
|
379
|
+
* import InvoiceCard from './components/InvoiceCard.svelte';
|
|
380
|
+
*
|
|
381
|
+
* ModuleUIRegistry.registerModule(COMMERCE_MODULE_META);
|
|
382
|
+
* ModuleUIRegistry.register('@happyvertical/smrt-commerce', 'invoice-card', InvoiceCard);
|
|
383
|
+
* ```
|
|
384
|
+
*/
|
|
385
|
+
/**
|
|
386
|
+
* UI slot definition for a SMRT module.
|
|
387
|
+
*
|
|
388
|
+
* Modules declare the slots they support in their `SmrtModuleMeta`. Svelte UI
|
|
389
|
+
* packages then implement those slots by registering components against the
|
|
390
|
+
* same `id` via `ModuleUIRegistryInterface.register()`.
|
|
391
|
+
*
|
|
392
|
+
* @example
|
|
393
|
+
* ```typescript
|
|
394
|
+
* const slot: ModuleUISlot = {
|
|
395
|
+
* id: 'invoice-card',
|
|
396
|
+
* label: 'Invoice Card',
|
|
397
|
+
* description: 'Compact card view for a single invoice',
|
|
398
|
+
* category: 'display',
|
|
399
|
+
* order: 10,
|
|
400
|
+
* };
|
|
401
|
+
* ```
|
|
402
|
+
*
|
|
403
|
+
* @see {@link SmrtModuleMeta} for how slots are declared on a module
|
|
404
|
+
* @see {@link ModuleUIRegistryInterface} for registering component implementations
|
|
405
|
+
*/
|
|
406
|
+
export declare interface ModuleUISlot {
|
|
407
|
+
/** Unique identifier (e.g., 'invoice-card', 'customer-form') */
|
|
408
|
+
id: string;
|
|
409
|
+
/** Human-readable label */
|
|
410
|
+
label: string;
|
|
411
|
+
/** Description of the component's purpose */
|
|
412
|
+
description?: string;
|
|
413
|
+
/** Icon identifier (lucide icon names) */
|
|
414
|
+
icon?: string;
|
|
415
|
+
/** Display order (lower first) */
|
|
416
|
+
order?: number;
|
|
417
|
+
/** Component category for grouping */
|
|
418
|
+
category?: 'display' | 'form' | 'admin' | 'list' | 'detail' | 'action' | 'dashboard' | 'navigation';
|
|
419
|
+
/** Required props interface name (for documentation) */
|
|
420
|
+
propsInterface?: string;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Effect applied by a user-level permission override.
|
|
425
|
+
*
|
|
426
|
+
* Overrides target a specific user + permission combination and always win
|
|
427
|
+
* over role-based grants. `DENY` overrides are checked before `GRANT` in
|
|
428
|
+
* the 4-level permission cascade.
|
|
429
|
+
*
|
|
430
|
+
* @example
|
|
431
|
+
* ```typescript
|
|
432
|
+
* await override.create({
|
|
433
|
+
* userId,
|
|
434
|
+
* permission: 'billing.view',
|
|
435
|
+
* effect: OverrideEffect.DENY,
|
|
436
|
+
* });
|
|
437
|
+
* ```
|
|
438
|
+
*
|
|
439
|
+
* @see {@link TenantPermissionEffect} for the tenant-level equivalent that supports inheritance
|
|
440
|
+
*/
|
|
441
|
+
export declare enum OverrideEffect {
|
|
442
|
+
/** Grant the permission */
|
|
443
|
+
GRANT = "grant",
|
|
444
|
+
/** Deny the permission */
|
|
445
|
+
DENY = "deny"
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/** RBAC role. Runtime class: `@happyvertical/smrt-users:Role`. */
|
|
449
|
+
export declare interface Role extends SmrtEntityFields {
|
|
450
|
+
/** `null` → system role available to every tenant. */
|
|
451
|
+
tenantId?: string | null;
|
|
452
|
+
name: string;
|
|
453
|
+
description: string;
|
|
454
|
+
isSystem: boolean;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Status of an authenticated session.
|
|
459
|
+
*
|
|
460
|
+
* Sessions transition from `ACTIVE` to either `EXPIRED` (time-based) or
|
|
461
|
+
* `REVOKED` (explicit action by the user or an administrator).
|
|
462
|
+
*
|
|
463
|
+
* @example
|
|
464
|
+
* ```typescript
|
|
465
|
+
* if (session.status !== SessionStatus.ACTIVE) {
|
|
466
|
+
* redirect(302, '/login');
|
|
467
|
+
* }
|
|
468
|
+
* ```
|
|
469
|
+
*
|
|
470
|
+
* @see {@link UserStatus} for the account-level status checked before session creation
|
|
471
|
+
*/
|
|
472
|
+
export declare enum SessionStatus {
|
|
473
|
+
/** Active session */
|
|
474
|
+
ACTIVE = "active",
|
|
475
|
+
/** Expired session (past expiresAt) */
|
|
476
|
+
EXPIRED = "expired",
|
|
477
|
+
/** Revoked by user or admin */
|
|
478
|
+
REVOKED = "revoked"
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Signal emitted during SMRT method execution.
|
|
483
|
+
*
|
|
484
|
+
* Signals provide automatic observability into method execution,
|
|
485
|
+
* enabling logging, metrics, pub/sub updates, and other integrations
|
|
486
|
+
* without requiring manual instrumentation.
|
|
487
|
+
*
|
|
488
|
+
* @example
|
|
489
|
+
* ```typescript
|
|
490
|
+
* // Logging adapter
|
|
491
|
+
* const loggingAdapter: SignalAdapter = {
|
|
492
|
+
* async handle(signal: Signal) {
|
|
493
|
+
* const label = `${signal.className}.${signal.method} [${signal.id}]`;
|
|
494
|
+
* if (signal.type === 'start') console.log(`→ ${label}`);
|
|
495
|
+
* if (signal.type === 'end') console.log(`✓ ${label} (${signal.duration}ms)`);
|
|
496
|
+
* if (signal.type === 'error') console.error(`✗ ${label}`, signal.error);
|
|
497
|
+
* },
|
|
498
|
+
* };
|
|
499
|
+
* ```
|
|
500
|
+
*
|
|
501
|
+
* @see {@link SignalType} for the lifecycle stage values
|
|
502
|
+
* @see {@link SignalAdapter} for implementing a consumer
|
|
503
|
+
*/
|
|
504
|
+
export declare interface Signal {
|
|
505
|
+
/**
|
|
506
|
+
* Unique identifier for this specific execution
|
|
507
|
+
* Generated once per method invocation
|
|
508
|
+
*/
|
|
509
|
+
id: string;
|
|
510
|
+
/**
|
|
511
|
+
* ID of the SMRT object instance
|
|
512
|
+
*/
|
|
513
|
+
objectId: string;
|
|
514
|
+
/**
|
|
515
|
+
* Name of the SMRT class
|
|
516
|
+
*/
|
|
517
|
+
className: string;
|
|
518
|
+
/**
|
|
519
|
+
* Name of the method being executed
|
|
520
|
+
*/
|
|
521
|
+
method: string;
|
|
522
|
+
/**
|
|
523
|
+
* Signal type indicating lifecycle stage:
|
|
524
|
+
* - 'start': Method execution started
|
|
525
|
+
* - 'step': Manual step within method (optional)
|
|
526
|
+
* - 'end': Method execution completed successfully
|
|
527
|
+
* - 'error': Method execution failed
|
|
528
|
+
*/
|
|
529
|
+
type: SignalType;
|
|
530
|
+
/**
|
|
531
|
+
* Optional step label for manual progress tracking
|
|
532
|
+
* Developers can emit custom steps within methods using bus.emit()
|
|
533
|
+
*/
|
|
534
|
+
step?: string;
|
|
535
|
+
/**
|
|
536
|
+
* Sanitized method arguments (sensitive data removed)
|
|
537
|
+
* Objects with @sensitive JSDoc tags are excluded
|
|
538
|
+
*/
|
|
539
|
+
args?: any[];
|
|
540
|
+
/**
|
|
541
|
+
* Method result (only present on 'end' signals)
|
|
542
|
+
*/
|
|
543
|
+
result?: any;
|
|
544
|
+
/**
|
|
545
|
+
* Error that was thrown (only present on 'error' signals)
|
|
546
|
+
*/
|
|
547
|
+
error?: Error;
|
|
548
|
+
/**
|
|
549
|
+
* Method execution duration in milliseconds
|
|
550
|
+
* Only present on 'end' and 'error' signals
|
|
551
|
+
*/
|
|
552
|
+
duration?: number;
|
|
553
|
+
/**
|
|
554
|
+
* Timestamp when signal was emitted
|
|
555
|
+
*/
|
|
556
|
+
timestamp: Date;
|
|
557
|
+
/**
|
|
558
|
+
* Optional additional context
|
|
559
|
+
* Can include tracing IDs, user context, request metadata, etc.
|
|
560
|
+
*/
|
|
561
|
+
metadata?: Record<string, any>;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Adapter interface for consuming signals from the SMRT signaling system.
|
|
566
|
+
*
|
|
567
|
+
* Adapters process signals for specific purposes:
|
|
568
|
+
* - **Logging**: write to console, file, or a logging service
|
|
569
|
+
* - **Metrics**: track execution counts, durations, and error rates
|
|
570
|
+
* - **Pub/Sub**: broadcast real-time updates to connected clients
|
|
571
|
+
* - **Tracing**: forward spans to a distributed tracing system (e.g., OpenTelemetry)
|
|
572
|
+
*
|
|
573
|
+
* Adapters are fire-and-forget — errors thrown inside `handle()` are caught
|
|
574
|
+
* by the SignalBus and do not interrupt the main execution flow.
|
|
575
|
+
*
|
|
576
|
+
* @example
|
|
577
|
+
* ```typescript
|
|
578
|
+
* class MetricsAdapter implements SignalAdapter {
|
|
579
|
+
* async handle(signal: Signal): Promise<void> {
|
|
580
|
+
* if (signal.type === 'end') {
|
|
581
|
+
* metrics.histogram('smrt.method.duration', signal.duration ?? 0, {
|
|
582
|
+
* class: signal.className,
|
|
583
|
+
* method: signal.method,
|
|
584
|
+
* });
|
|
585
|
+
* }
|
|
586
|
+
* }
|
|
587
|
+
* }
|
|
588
|
+
* ```
|
|
589
|
+
*
|
|
590
|
+
* @see {@link Signal} for the payload each adapter receives
|
|
591
|
+
* @see {@link SignalType} for the lifecycle stages
|
|
592
|
+
*/
|
|
593
|
+
export declare interface SignalAdapter {
|
|
594
|
+
/**
|
|
595
|
+
* Handle a signal event
|
|
596
|
+
*
|
|
597
|
+
* @param signal - The signal to process
|
|
598
|
+
* @returns Promise that resolves when signal is handled
|
|
599
|
+
*
|
|
600
|
+
* @remarks
|
|
601
|
+
* This method should not throw - errors are caught by the SignalBus.
|
|
602
|
+
* Implementations should handle their own error logging/recovery.
|
|
603
|
+
*/
|
|
604
|
+
handle(signal: Signal): Promise<void>;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Universal Signaling System Types
|
|
609
|
+
*
|
|
610
|
+
* This module defines the core types for the SMRT signaling system,
|
|
611
|
+
* which provides automatic method tracking and event distribution
|
|
612
|
+
* for logging, metrics, pub/sub, and other observability needs.
|
|
613
|
+
*/
|
|
614
|
+
/**
|
|
615
|
+
* Lifecycle stage of a signal emitted during SMRT method execution.
|
|
616
|
+
*
|
|
617
|
+
* - `'start'` — emitted when a tracked method begins executing
|
|
618
|
+
* - `'step'` — emitted manually within a method for progress tracking
|
|
619
|
+
* - `'end'` — emitted when a method completes successfully
|
|
620
|
+
* - `'error'` — emitted when a method throws an unhandled exception
|
|
621
|
+
*
|
|
622
|
+
* @example
|
|
623
|
+
* ```typescript
|
|
624
|
+
* adapter.handle = async (signal: Signal) => {
|
|
625
|
+
* if (signal.type === 'error') {
|
|
626
|
+
* logger.error(`${signal.className}.${signal.method} failed`, signal.error);
|
|
627
|
+
* }
|
|
628
|
+
* };
|
|
629
|
+
* ```
|
|
630
|
+
*
|
|
631
|
+
* @see {@link Signal} for the full signal payload shape
|
|
632
|
+
* @see {@link SignalAdapter} for consuming signals
|
|
633
|
+
*/
|
|
634
|
+
export declare type SignalType = 'start' | 'step' | 'end' | 'error';
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Stable usage event shape emitted inside SMRT after every AI call.
|
|
638
|
+
*/
|
|
639
|
+
export declare interface SmrtAiUsageEvent {
|
|
640
|
+
/** AI provider identifier (e.g. "openai", "anthropic") */
|
|
641
|
+
provider: string;
|
|
642
|
+
/** Model identifier used for the call */
|
|
643
|
+
model: string;
|
|
644
|
+
/** High-level operation name (e.g. "chat", "embed", "stream") */
|
|
645
|
+
operation: string;
|
|
646
|
+
/** Token usage reported by the provider, when available */
|
|
647
|
+
usage?: AiTokenUsage;
|
|
648
|
+
/** Wall-clock duration in milliseconds */
|
|
649
|
+
duration: number;
|
|
650
|
+
/** Event timestamp */
|
|
651
|
+
timestamp: Date;
|
|
652
|
+
/** Optional provider- or application-specific tags */
|
|
653
|
+
tags?: Record<string, string>;
|
|
654
|
+
/** SMRT class responsible for the call */
|
|
655
|
+
className?: string;
|
|
656
|
+
/** Tenant identifier when available */
|
|
657
|
+
tenantId?: string | null;
|
|
658
|
+
/** Best-effort estimated cost in USD */
|
|
659
|
+
estimatedCost?: number;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Persisted AI usage record returned from query helpers.
|
|
664
|
+
*/
|
|
665
|
+
export declare interface SmrtAiUsageRecord extends SmrtAiUsageEvent {
|
|
666
|
+
/** Persistent record identifier */
|
|
667
|
+
id: string;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Fields every persisted SMRT entity exposes — a subset of `SmrtObject`'s public
|
|
672
|
+
* surface. `id`/`slug` are `null`/`undefined` before the first persist, matching
|
|
673
|
+
* the base getters.
|
|
674
|
+
*/
|
|
675
|
+
export declare interface SmrtEntityFields {
|
|
676
|
+
/** UUID, assigned on first persist. */
|
|
677
|
+
id: string | null | undefined;
|
|
678
|
+
/** URL-safe slug, when the model maintains one. */
|
|
679
|
+
slug: string | null | undefined;
|
|
680
|
+
/** Creation timestamp; `null`/`undefined` before first persist. */
|
|
681
|
+
created_at: Date | null | undefined;
|
|
682
|
+
/** Last-update timestamp; `null`/`undefined` before first persist. */
|
|
683
|
+
updated_at: Date | null | undefined;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Metadata declaration for a SMRT module.
|
|
688
|
+
*
|
|
689
|
+
* Each module exports a `SmrtModuleMeta` constant describing its package
|
|
690
|
+
* identity, the UI slots it declares, and the model/collection classes it
|
|
691
|
+
* provides. The UI registry uses this to resolve component lookups at runtime.
|
|
692
|
+
*
|
|
693
|
+
* @example
|
|
694
|
+
* ```typescript
|
|
695
|
+
* export const COMMERCE_MODULE_META: SmrtModuleMeta = {
|
|
696
|
+
* name: '@happyvertical/smrt-commerce',
|
|
697
|
+
* displayName: 'Commerce',
|
|
698
|
+
* description: 'Invoicing, contracts, and fulfillment',
|
|
699
|
+
* models: ['Customer', 'Invoice', 'Contract'],
|
|
700
|
+
* uiSlots: {
|
|
701
|
+
* 'invoice-card': { id: 'invoice-card', label: 'Invoice Card', category: 'display' },
|
|
702
|
+
* },
|
|
703
|
+
* };
|
|
704
|
+
* ```
|
|
705
|
+
*
|
|
706
|
+
* @see {@link ModuleUISlot} for the shape of each declared slot
|
|
707
|
+
* @see {@link ModuleUIRegistryInterface} for registering and retrieving module components
|
|
708
|
+
*/
|
|
709
|
+
export declare interface SmrtModuleMeta {
|
|
710
|
+
/** Package name (e.g., '@happyvertical/smrt-commerce') */
|
|
711
|
+
name: string;
|
|
712
|
+
/** Human-readable display name */
|
|
713
|
+
displayName: string;
|
|
714
|
+
/** Module description */
|
|
715
|
+
description?: string;
|
|
716
|
+
/** Module version */
|
|
717
|
+
version?: string;
|
|
718
|
+
/** UI slots this module declares */
|
|
719
|
+
uiSlots?: Record<string, ModuleUISlot>;
|
|
720
|
+
/** Model classes this module provides */
|
|
721
|
+
models?: string[];
|
|
722
|
+
/** Collection classes this module provides */
|
|
723
|
+
collections?: string[];
|
|
724
|
+
/** Peer dependencies for UI (e.g., ['@happyvertical/smrt-profiles']) */
|
|
725
|
+
uiDependencies?: string[];
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* Package-owned route definition.
|
|
730
|
+
*
|
|
731
|
+
* @typeParam TData - Data shape the route component expects.
|
|
732
|
+
* @typeParam TLoadInput - Input accepted by the optional `load` helper.
|
|
733
|
+
* @typeParam TProps - Component props shape. Defaults to `{ data?: TData }`.
|
|
734
|
+
*/
|
|
735
|
+
export declare interface SmrtRouteDefinition<TData = unknown, TLoadInput = unknown, TProps = {
|
|
736
|
+
data?: TData;
|
|
737
|
+
}> {
|
|
738
|
+
/** Stable route identifier, namespaced by package. */
|
|
739
|
+
id: string;
|
|
740
|
+
/** Human-readable page title. */
|
|
741
|
+
title: string;
|
|
742
|
+
/** Optional description for docs and tooling. */
|
|
743
|
+
description?: string;
|
|
744
|
+
/** Canonical path the package recommends by default. */
|
|
745
|
+
defaultPath: string;
|
|
746
|
+
/** Page component exported by the package. */
|
|
747
|
+
component: ModuleComponentType<TProps>;
|
|
748
|
+
/** Optional reusable load helper for app-owned route files. */
|
|
749
|
+
load?: (input: TLoadInput) => Promise<TData> | TData;
|
|
750
|
+
/** Which SvelteKit route file the `load` helper belongs in. */
|
|
751
|
+
loadKind?: SmrtRouteLoadKind;
|
|
752
|
+
/** Optional navigation metadata. */
|
|
753
|
+
nav?: SmrtRouteNavigationMeta;
|
|
754
|
+
/** Optional tags for docs, hosts, or filtering. */
|
|
755
|
+
tags?: string[];
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Route load function category.
|
|
760
|
+
*
|
|
761
|
+
* `page` maps naturally to SvelteKit's `+page.ts`, while `page-server` maps to
|
|
762
|
+
* `+page.server.ts`.
|
|
763
|
+
*/
|
|
764
|
+
export declare type SmrtRouteLoadKind = 'page' | 'page-server';
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Package-owned route module.
|
|
768
|
+
*
|
|
769
|
+
* Consumers import one of these from `@happyvertical/smrt-<pkg>/routes`, then
|
|
770
|
+
* mount the exported components and loaders inside their own app route tree.
|
|
771
|
+
*
|
|
772
|
+
*/
|
|
773
|
+
export declare interface SmrtRouteModule {
|
|
774
|
+
/** Package name, usually `@happyvertical/smrt-<pkg>`. */
|
|
775
|
+
packageName: string;
|
|
776
|
+
/** Human-readable module name. */
|
|
777
|
+
displayName: string;
|
|
778
|
+
/** Optional module description. */
|
|
779
|
+
description?: string;
|
|
780
|
+
/** Route definitions keyed by package-local name. */
|
|
781
|
+
routes: Record<string, SmrtRouteDefinition<any, any, any>>;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Resolved navigation entry for a mounted route.
|
|
786
|
+
*/
|
|
787
|
+
export declare interface SmrtRouteNavigationItem {
|
|
788
|
+
/** Stable route identifier. */
|
|
789
|
+
routeId: string;
|
|
790
|
+
/** Link href as mounted by the consuming app. */
|
|
791
|
+
href: string;
|
|
792
|
+
/** Label shown in the app navigation. */
|
|
793
|
+
label: string;
|
|
794
|
+
/** Optional description for menu UI. */
|
|
795
|
+
description?: string;
|
|
796
|
+
/** Optional icon identifier. */
|
|
797
|
+
icon?: string;
|
|
798
|
+
/** Display order (lower first). */
|
|
799
|
+
order?: number;
|
|
800
|
+
/** Optional grouping key for larger menus. */
|
|
801
|
+
group?: string;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Navigation metadata for a package route.
|
|
806
|
+
*/
|
|
807
|
+
export declare interface SmrtRouteNavigationMeta {
|
|
808
|
+
/** Label shown in app navigation. */
|
|
809
|
+
label: string;
|
|
810
|
+
/** Optional route description for menus or docs. */
|
|
811
|
+
description?: string;
|
|
812
|
+
/** Optional icon identifier. */
|
|
813
|
+
icon?: string;
|
|
814
|
+
/** Display order (lower first). */
|
|
815
|
+
order?: number;
|
|
816
|
+
/** Optional grouping key for larger menus. */
|
|
817
|
+
group?: string;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/** Hierarchical tenant. Runtime class: `@happyvertical/smrt-users:Tenant`. */
|
|
821
|
+
export declare interface Tenant extends SmrtEntityFields {
|
|
822
|
+
name: string;
|
|
823
|
+
status: TenantStatus;
|
|
824
|
+
description: string;
|
|
825
|
+
parentTenantId?: string | null;
|
|
826
|
+
hierarchyLevel: number;
|
|
827
|
+
hierarchyPath: string;
|
|
828
|
+
cascadePermissions: boolean;
|
|
829
|
+
inheritPermissions: boolean;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* Effect of a tenant-level permission setting in a hierarchical tenant tree.
|
|
834
|
+
*
|
|
835
|
+
* Unlike `OverrideEffect`, tenant-level effects support `INHERIT` — the default
|
|
836
|
+
* behaviour where a child tenant walks up to its parent to resolve the permission.
|
|
837
|
+
* `DENY` blocks inheritance, preventing child tenants from acquiring the permission
|
|
838
|
+
* even if a grandparent grants it.
|
|
839
|
+
*
|
|
840
|
+
* @example
|
|
841
|
+
* ```typescript
|
|
842
|
+
* // Sub-tenant explicitly blocks billing access regardless of parent settings
|
|
843
|
+
* await tenantPermission.create({
|
|
844
|
+
* tenantId: subTenantId,
|
|
845
|
+
* permission: 'billing.manage',
|
|
846
|
+
* effect: TenantPermissionEffect.DENY,
|
|
847
|
+
* });
|
|
848
|
+
* ```
|
|
849
|
+
*
|
|
850
|
+
* @see {@link OverrideEffect} for user-level overrides (no inheritance step)
|
|
851
|
+
* @see {@link TenantStatus} for the tenant lifecycle status
|
|
852
|
+
*/
|
|
853
|
+
export declare enum TenantPermissionEffect {
|
|
854
|
+
/** Inherit from parent tenant (default behavior) */
|
|
855
|
+
INHERIT = "inherit",
|
|
856
|
+
/** Explicitly grant at this tenant level */
|
|
857
|
+
GRANT = "grant",
|
|
858
|
+
/** Explicitly deny at this tenant level (blocks inheritance) */
|
|
859
|
+
DENY = "deny"
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Lifecycle status of a tenant (organization) within the platform.
|
|
864
|
+
*
|
|
865
|
+
* @example
|
|
866
|
+
* ```typescript
|
|
867
|
+
* if (tenant.status === TenantStatus.ARCHIVED) {
|
|
868
|
+
* return; // skip soft-deleted tenants
|
|
869
|
+
* }
|
|
870
|
+
* ```
|
|
871
|
+
*
|
|
872
|
+
* @see {@link MembershipStatus} for a user's membership status within a tenant
|
|
873
|
+
* @see {@link TenantPermissionEffect} for permission inheritance across tenant hierarchies
|
|
874
|
+
*/
|
|
875
|
+
export declare enum TenantStatus {
|
|
876
|
+
/** Active tenant */
|
|
877
|
+
ACTIVE = "active",
|
|
878
|
+
/** Inactive tenant */
|
|
879
|
+
INACTIVE = "inactive",
|
|
880
|
+
/** Suspended tenant */
|
|
881
|
+
SUSPENDED = "suspended",
|
|
882
|
+
/** Archived tenant (soft-deleted) */
|
|
883
|
+
ARCHIVED = "archived"
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
/** Auth identity record. Runtime class: `@happyvertical/smrt-users:User`. */
|
|
887
|
+
export declare interface User extends SmrtEntityFields {
|
|
888
|
+
/** Plain-string reference to the owning `Profile` (not a DB foreign key). */
|
|
889
|
+
profileId: string;
|
|
890
|
+
/** Lower-cased email; globally unique. */
|
|
891
|
+
email: string;
|
|
892
|
+
status: UserStatus;
|
|
893
|
+
lastLoginAt: Date | null;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* User-related type definitions
|
|
898
|
+
*
|
|
899
|
+
* These enums and types are exported from smrt-types to allow
|
|
900
|
+
* browser-safe packages (like smrt-svelte) to import them without
|
|
901
|
+
* pulling in server-side dependencies from smrt-users.
|
|
902
|
+
*/
|
|
903
|
+
/**
|
|
904
|
+
* Lifecycle status of a user account.
|
|
905
|
+
*
|
|
906
|
+
* @example
|
|
907
|
+
* ```typescript
|
|
908
|
+
* if (user.status === UserStatus.SUSPENDED) {
|
|
909
|
+
* throw new ForbiddenError('Account is suspended');
|
|
910
|
+
* }
|
|
911
|
+
* ```
|
|
912
|
+
*
|
|
913
|
+
* @see {@link MembershipStatus} for a user's status within a specific tenant
|
|
914
|
+
* @see {@link SessionStatus} for the status of an active session
|
|
915
|
+
*/
|
|
916
|
+
export declare enum UserStatus {
|
|
917
|
+
/** Active user account */
|
|
918
|
+
ACTIVE = "active",
|
|
919
|
+
/** Inactive user account */
|
|
920
|
+
INACTIVE = "inactive",
|
|
921
|
+
/** Suspended user account */
|
|
922
|
+
SUSPENDED = "suspended",
|
|
923
|
+
/** Pending email verification */
|
|
924
|
+
PENDING = "pending"
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
export { }
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
var UserStatus = /* @__PURE__ */ ((UserStatus2) => {
|
|
2
|
+
UserStatus2["ACTIVE"] = "active";
|
|
3
|
+
UserStatus2["INACTIVE"] = "inactive";
|
|
4
|
+
UserStatus2["SUSPENDED"] = "suspended";
|
|
5
|
+
UserStatus2["PENDING"] = "pending";
|
|
6
|
+
return UserStatus2;
|
|
7
|
+
})(UserStatus || {});
|
|
8
|
+
var TenantStatus = /* @__PURE__ */ ((TenantStatus2) => {
|
|
9
|
+
TenantStatus2["ACTIVE"] = "active";
|
|
10
|
+
TenantStatus2["INACTIVE"] = "inactive";
|
|
11
|
+
TenantStatus2["SUSPENDED"] = "suspended";
|
|
12
|
+
TenantStatus2["ARCHIVED"] = "archived";
|
|
13
|
+
return TenantStatus2;
|
|
14
|
+
})(TenantStatus || {});
|
|
15
|
+
var MembershipStatus = /* @__PURE__ */ ((MembershipStatus2) => {
|
|
16
|
+
MembershipStatus2["ACTIVE"] = "active";
|
|
17
|
+
MembershipStatus2["INACTIVE"] = "inactive";
|
|
18
|
+
MembershipStatus2["PENDING"] = "pending";
|
|
19
|
+
return MembershipStatus2;
|
|
20
|
+
})(MembershipStatus || {});
|
|
21
|
+
var SessionStatus = /* @__PURE__ */ ((SessionStatus2) => {
|
|
22
|
+
SessionStatus2["ACTIVE"] = "active";
|
|
23
|
+
SessionStatus2["EXPIRED"] = "expired";
|
|
24
|
+
SessionStatus2["REVOKED"] = "revoked";
|
|
25
|
+
return SessionStatus2;
|
|
26
|
+
})(SessionStatus || {});
|
|
27
|
+
var OverrideEffect = /* @__PURE__ */ ((OverrideEffect2) => {
|
|
28
|
+
OverrideEffect2["GRANT"] = "grant";
|
|
29
|
+
OverrideEffect2["DENY"] = "deny";
|
|
30
|
+
return OverrideEffect2;
|
|
31
|
+
})(OverrideEffect || {});
|
|
32
|
+
var TenantPermissionEffect = /* @__PURE__ */ ((TenantPermissionEffect2) => {
|
|
33
|
+
TenantPermissionEffect2["INHERIT"] = "inherit";
|
|
34
|
+
TenantPermissionEffect2["GRANT"] = "grant";
|
|
35
|
+
TenantPermissionEffect2["DENY"] = "deny";
|
|
36
|
+
return TenantPermissionEffect2;
|
|
37
|
+
})(TenantPermissionEffect || {});
|
|
38
|
+
export {
|
|
39
|
+
MembershipStatus,
|
|
40
|
+
OverrideEffect,
|
|
41
|
+
SessionStatus,
|
|
42
|
+
TenantPermissionEffect,
|
|
43
|
+
TenantStatus,
|
|
44
|
+
UserStatus
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/user.ts"],"sourcesContent":["/**\n * User-related type definitions\n *\n * These enums and types are exported from smrt-types to allow\n * browser-safe packages (like smrt-svelte) to import them without\n * pulling in server-side dependencies from smrt-users.\n */\n\n// ============= User Status =============\n\n/**\n * Lifecycle status of a user account.\n *\n * @example\n * ```typescript\n * if (user.status === UserStatus.SUSPENDED) {\n * throw new ForbiddenError('Account is suspended');\n * }\n * ```\n *\n * @see {@link MembershipStatus} for a user's status within a specific tenant\n * @see {@link SessionStatus} for the status of an active session\n */\nexport enum UserStatus {\n /** Active user account */\n ACTIVE = 'active',\n /** Inactive user account */\n INACTIVE = 'inactive',\n /** Suspended user account */\n SUSPENDED = 'suspended',\n /** Pending email verification */\n PENDING = 'pending',\n}\n\n// ============= Tenant Status =============\n\n/**\n * Lifecycle status of a tenant (organization) within the platform.\n *\n * @example\n * ```typescript\n * if (tenant.status === TenantStatus.ARCHIVED) {\n * return; // skip soft-deleted tenants\n * }\n * ```\n *\n * @see {@link MembershipStatus} for a user's membership status within a tenant\n * @see {@link TenantPermissionEffect} for permission inheritance across tenant hierarchies\n */\nexport enum TenantStatus {\n /** Active tenant */\n ACTIVE = 'active',\n /** Inactive tenant */\n INACTIVE = 'inactive',\n /** Suspended tenant */\n SUSPENDED = 'suspended',\n /** Archived tenant (soft-deleted) */\n ARCHIVED = 'archived',\n}\n\n// ============= Membership Status =============\n\n/**\n * Status of a user's membership within a specific tenant.\n *\n * A user may hold memberships in multiple tenants simultaneously, each with an\n * independent `MembershipStatus`.\n *\n * @example\n * ```typescript\n * const active = memberships.filter(m => m.status === MembershipStatus.ACTIVE);\n * ```\n *\n * @see {@link UserStatus} for the global account-level status\n * @see {@link TenantStatus} for the status of the tenant itself\n */\nexport enum MembershipStatus {\n /** Active membership */\n ACTIVE = 'active',\n /** Inactive membership */\n INACTIVE = 'inactive',\n /** Pending invitation acceptance */\n PENDING = 'pending',\n}\n\n// ============= Session Status =============\n\n/**\n * Status of an authenticated session.\n *\n * Sessions transition from `ACTIVE` to either `EXPIRED` (time-based) or\n * `REVOKED` (explicit action by the user or an administrator).\n *\n * @example\n * ```typescript\n * if (session.status !== SessionStatus.ACTIVE) {\n * redirect(302, '/login');\n * }\n * ```\n *\n * @see {@link UserStatus} for the account-level status checked before session creation\n */\nexport enum SessionStatus {\n /** Active session */\n ACTIVE = 'active',\n /** Expired session (past expiresAt) */\n EXPIRED = 'expired',\n /** Revoked by user or admin */\n REVOKED = 'revoked',\n}\n\n// ============= Permission Override =============\n\n/**\n * Effect applied by a user-level permission override.\n *\n * Overrides target a specific user + permission combination and always win\n * over role-based grants. `DENY` overrides are checked before `GRANT` in\n * the 4-level permission cascade.\n *\n * @example\n * ```typescript\n * await override.create({\n * userId,\n * permission: 'billing.view',\n * effect: OverrideEffect.DENY,\n * });\n * ```\n *\n * @see {@link TenantPermissionEffect} for the tenant-level equivalent that supports inheritance\n */\nexport enum OverrideEffect {\n /** Grant the permission */\n GRANT = 'grant',\n /** Deny the permission */\n DENY = 'deny',\n}\n\n// ============= Tenant Permission Override =============\n\n/**\n * Effect of a tenant-level permission setting in a hierarchical tenant tree.\n *\n * Unlike `OverrideEffect`, tenant-level effects support `INHERIT` — the default\n * behaviour where a child tenant walks up to its parent to resolve the permission.\n * `DENY` blocks inheritance, preventing child tenants from acquiring the permission\n * even if a grandparent grants it.\n *\n * @example\n * ```typescript\n * // Sub-tenant explicitly blocks billing access regardless of parent settings\n * await tenantPermission.create({\n * tenantId: subTenantId,\n * permission: 'billing.manage',\n * effect: TenantPermissionEffect.DENY,\n * });\n * ```\n *\n * @see {@link OverrideEffect} for user-level overrides (no inheritance step)\n * @see {@link TenantStatus} for the tenant lifecycle status\n */\nexport enum TenantPermissionEffect {\n /** Inherit from parent tenant (default behavior) */\n INHERIT = 'inherit',\n /** Explicitly grant at this tenant level */\n GRANT = 'grant',\n /** Explicitly deny at this tenant level (blocks inheritance) */\n DENY = 'deny',\n}\n"],"names":["UserStatus","TenantStatus","MembershipStatus","SessionStatus","OverrideEffect","TenantPermissionEffect"],"mappings":"AAuBO,IAAK,+BAAAA,gBAAL;AAELA,cAAA,QAAA,IAAS;AAETA,cAAA,UAAA,IAAW;AAEXA,cAAA,WAAA,IAAY;AAEZA,cAAA,SAAA,IAAU;AARA,SAAAA;AAAA,GAAA,cAAA,CAAA,CAAA;AA0BL,IAAK,iCAAAC,kBAAL;AAELA,gBAAA,QAAA,IAAS;AAETA,gBAAA,UAAA,IAAW;AAEXA,gBAAA,WAAA,IAAY;AAEZA,gBAAA,UAAA,IAAW;AARD,SAAAA;AAAA,GAAA,gBAAA,CAAA,CAAA;AA2BL,IAAK,qCAAAC,sBAAL;AAELA,oBAAA,QAAA,IAAS;AAETA,oBAAA,UAAA,IAAW;AAEXA,oBAAA,SAAA,IAAU;AANA,SAAAA;AAAA,GAAA,oBAAA,CAAA,CAAA;AA0BL,IAAK,kCAAAC,mBAAL;AAELA,iBAAA,QAAA,IAAS;AAETA,iBAAA,SAAA,IAAU;AAEVA,iBAAA,SAAA,IAAU;AANA,SAAAA;AAAA,GAAA,iBAAA,CAAA,CAAA;AA6BL,IAAK,mCAAAC,oBAAL;AAELA,kBAAA,OAAA,IAAQ;AAERA,kBAAA,MAAA,IAAO;AAJG,SAAAA;AAAA,GAAA,kBAAA,CAAA,CAAA;AA8BL,IAAK,2CAAAC,4BAAL;AAELA,0BAAA,SAAA,IAAU;AAEVA,0BAAA,OAAA,IAAQ;AAERA,0BAAA,MAAA,IAAO;AANG,SAAAA;AAAA,GAAA,0BAAA,CAAA,CAAA;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@happyvertical/smrt-types",
|
|
3
|
+
"version": "0.30.0",
|
|
4
|
+
"description": "Shared type definitions for the HAVE SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/node": "25.0.9",
|
|
16
|
+
"typescript": "^5.9.3",
|
|
17
|
+
"vite": "7.3.1",
|
|
18
|
+
"vitest": "^4.0.17"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"CLAUDE.md",
|
|
23
|
+
"AGENTS.md"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"registry": "https://registry.npmjs.org",
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"author": "HappyVertical",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/happyvertical/smrt.git",
|
|
33
|
+
"directory": "packages/types"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"test:watch": "vitest",
|
|
38
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
39
|
+
"build": "vite build",
|
|
40
|
+
"build:watch": "vite build --watch",
|
|
41
|
+
"docs": "typedoc --plugin typedoc-plugin-markdown --out docs --entryPoints ./src/index.ts --tsconfig ./tsconfig.json --excludePrivate --excludeInternal --hideGenerator --fileExtension .md --readme none --categorizeByGroup false --includeVersion false --hidePageHeader --hidePageTitle false --outputFileStrategy modules",
|
|
42
|
+
"docs:watch": "typedoc --plugin typedoc-plugin-markdown --out docs --entryPoints ./src/index.ts --tsconfig ./tsconfig.json --excludePrivate --excludeInternal --hideGenerator --fileExtension .md --readme none --categorizeByGroup false --includeVersion false --hidePageHeader --hidePageTitle false --outputFileStrategy modules --watch",
|
|
43
|
+
"clean": "rm -rf dist docs",
|
|
44
|
+
"dev": "npm run build:watch & npm run test:watch"
|
|
45
|
+
}
|
|
46
|
+
}
|