@happyvertical/smrt-features 0.51.19 → 0.51.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/AGENTS.md +17 -0
  2. package/README.md +152 -0
  3. package/dist/__smrt-register__.d.ts +2 -0
  4. package/dist/__smrt-register__.d.ts.map +1 -0
  5. package/dist/feature-definition.d.ts +18 -0
  6. package/dist/feature-definition.d.ts.map +1 -0
  7. package/dist/feature-definitions.d.ts +13 -0
  8. package/dist/feature-definitions.d.ts.map +1 -0
  9. package/dist/feature-override-service.d.ts +41 -0
  10. package/dist/feature-override-service.d.ts.map +1 -0
  11. package/dist/feature-override.d.ts +13 -0
  12. package/dist/feature-override.d.ts.map +1 -0
  13. package/dist/feature-overrides.d.ts +16 -0
  14. package/dist/feature-overrides.d.ts.map +1 -0
  15. package/dist/feature-resolver.d.ts +18 -0
  16. package/dist/feature-resolver.d.ts.map +1 -0
  17. package/dist/feature-settings.d.ts +209 -0
  18. package/dist/feature-settings.d.ts.map +1 -0
  19. package/dist/feature-sync.d.ts +17 -0
  20. package/dist/feature-sync.d.ts.map +1 -0
  21. package/dist/index.d.ts +11 -263
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +155 -2
  24. package/dist/index.js.map +1 -1
  25. package/dist/manifest.json +1 -1
  26. package/dist/smrt-knowledge.json +14 -6
  27. package/dist/svelte/components/FeatureSettingsPanel.svelte +338 -0
  28. package/dist/svelte/components/FeatureSettingsPanel.svelte.d.ts +52 -0
  29. package/dist/svelte/components/FeatureSettingsPanel.svelte.d.ts.map +1 -0
  30. package/dist/svelte/index.d.ts +17 -0
  31. package/dist/svelte/index.d.ts.map +1 -0
  32. package/dist/svelte/index.js +14 -0
  33. package/dist/svelte/types.d.ts +76 -0
  34. package/dist/svelte/types.d.ts.map +1 -0
  35. package/dist/svelte/types.js +37 -0
  36. package/dist/types.d.ts +107 -131
  37. package/dist/types.d.ts.map +1 -0
  38. package/dist/utils.d.ts +28 -0
  39. package/dist/utils.d.ts.map +1 -0
  40. package/package.json +26 -7
package/dist/index.d.ts CHANGED
@@ -1,263 +1,11 @@
1
- import { SmartObjectManifest } from '@happyvertical/smrt-core/manifest';
2
- import { SmrtClassOptions } from '@happyvertical/smrt-core';
3
- import { SmrtCollection } from '@happyvertical/smrt-core';
4
- import { SmrtObject } from '@happyvertical/smrt-core';
5
-
6
- export declare function createFeatureKey(qualifiedClassName: string, localId: string): string;
7
-
8
- export declare class FeatureDefinition extends SmrtObject {
9
- featureKey: string;
10
- packageName: string;
11
- qualifiedClassName: string;
12
- className: string;
13
- localId: string;
14
- defaultEnabled: boolean;
15
- label: string;
16
- description: string;
17
- metadata: string;
18
- visibility: string;
19
- constructor(options?: FeatureDefinitionOptions);
20
- getMetadata(): FeatureMetadata;
21
- setMetadata(metadata: FeatureMetadata | null): void;
22
- }
23
-
24
- export declare class FeatureDefinitionCollection extends SmrtCollection<FeatureDefinition> {
25
- static readonly _itemClass: typeof FeatureDefinition;
26
- findByFeatureKey(featureKey: string): Promise<FeatureDefinition | null>;
27
- findByPackageName(packageName: string): Promise<FeatureDefinition[]>;
28
- upsertDefinition(seed: FeatureDefinitionSeed): Promise<{
29
- definition: FeatureDefinition;
30
- status: 'created' | 'updated' | 'unchanged';
31
- }>;
32
- }
33
-
34
- export declare interface FeatureDefinitionOptions {
35
- id?: string;
36
- featureKey?: string;
37
- packageName?: string;
38
- qualifiedClassName?: string;
39
- className?: string;
40
- localId?: string;
41
- defaultEnabled?: boolean;
42
- label?: string;
43
- description?: string;
44
- metadata?: FeatureMetadata | string | null;
45
- visibility?: string;
46
- createdAt?: Date;
47
- updatedAt?: Date;
48
- }
49
-
50
- export declare interface FeatureDefinitionSeed {
51
- featureKey: string;
52
- packageName: string;
53
- qualifiedClassName: string;
54
- className: string;
55
- localId: string;
56
- defaultEnabled: boolean;
57
- label?: string;
58
- description?: string;
59
- metadata?: FeatureMetadata;
60
- visibility?: string;
61
- }
62
-
63
- export declare interface FeatureMetadata {
64
- [key: string]: unknown;
65
- }
66
-
67
- export declare class FeatureOverride extends SmrtObject {
68
- featureKey: string;
69
- scopeType: FeatureScopeType;
70
- scopeId: string;
71
- effect: FeatureOverrideEffect;
72
- constructor(options?: FeatureOverrideOptions);
73
- isInherit(): boolean;
74
- isEnabled(): boolean;
75
- isDisabled(): boolean;
76
- }
77
-
78
- /** Thrown when the authorizer does not return `true`. Nothing is written. */
79
- export declare class FeatureOverrideAuthorizationError extends Error {
80
- readonly request: FeatureOverrideWriteRequest;
81
- readonly status = 403;
82
- constructor(request: FeatureOverrideWriteRequest);
83
- }
84
-
85
- /**
86
- * The host's explicit authorization decision for one override write. Return
87
- * `true` only when the current caller may write that exact scope; anything
88
- * else denies.
89
- */
90
- export declare type FeatureOverrideAuthorizer = (request: FeatureOverrideWriteRequest) => boolean | Promise<boolean>;
91
-
92
- export declare class FeatureOverrideCollection extends SmrtCollection<FeatureOverride> {
93
- static readonly _itemClass: typeof FeatureOverride;
94
- findByFeatureKey(featureKey: string): Promise<FeatureOverride[]>;
95
- findByFeatureAndScope(featureKey: string, scopeType: FeatureScopeType, scopeId: string): Promise<FeatureOverride | null>;
96
- getGlobalOverride(featureKey: string): Promise<FeatureOverride | null>;
97
- getTenantOverride(featureKey: string, tenantId: string): Promise<FeatureOverride | null>;
98
- getOverrideMap(featureKey: string, scopeType: FeatureScopeType, scopeIds: string[]): Promise<Map<string, FeatureOverride>>;
99
- setOverride(featureKey: string, scopeType: FeatureScopeType, scopeId: string, effect: FeatureOverrideEffect): Promise<FeatureOverride>;
100
- setGlobalOverride(featureKey: string, effect: FeatureOverrideEffect): Promise<FeatureOverride>;
101
- setTenantOverride(featureKey: string, tenantId: string, effect: FeatureOverrideEffect): Promise<FeatureOverride>;
102
- removeOverride(featureKey: string, scopeType: FeatureScopeType, scopeId: string): Promise<boolean>;
103
- }
104
-
105
- export declare enum FeatureOverrideEffect {
106
- INHERIT = "inherit",
107
- ENABLE = "enable",
108
- DISABLE = "disable"
109
- }
110
-
111
- export declare interface FeatureOverrideOptions {
112
- id?: string;
113
- featureKey?: string;
114
- scopeType?: FeatureScopeType;
115
- scopeId?: string;
116
- effect?: FeatureOverrideEffect;
117
- createdAt?: Date;
118
- updatedAt?: Date;
119
- }
120
-
121
- /**
122
- * Authorized write path for feature overrides (#3013). Override rows are
123
- * authorization state for every scope and `FeatureOverride` is not
124
- * tenant-scoped, so generated surfaces are closed. Hosts that let callers
125
- * change flags construct this service with an authorizer bound to the
126
- * current caller and write through it; every write asks the authorizer
127
- * first and fails closed.
128
- */
129
- export declare class FeatureOverrideService {
130
- private readonly overrides;
131
- private readonly authorize;
132
- constructor(overrides: FeatureOverrideCollection, authorize: FeatureOverrideAuthorizer);
133
- setOverride(featureKey: string, scopeType: FeatureScopeType, scopeId: string, effect: FeatureOverrideEffect): Promise<FeatureOverride>;
134
- removeOverride(featureKey: string, scopeType: FeatureScopeType, scopeId: string): Promise<boolean>;
135
- private require;
136
- }
137
-
138
- /** One override write the host must authorize before it runs (#3013). */
139
- export declare interface FeatureOverrideWriteRequest {
140
- operation: 'set' | 'remove';
141
- featureKey: string;
142
- scopeType: FeatureScopeType;
143
- scopeId: string;
144
- /** Present for `set`. */
145
- effect?: FeatureOverrideEffect;
146
- }
147
-
148
- export declare interface FeatureResolutionContext {
149
- tenantId?: string;
150
- }
151
-
152
- export declare class FeatureResolver {
153
- private readonly options;
154
- private readonly resolverOptions;
155
- private featureDefinitions;
156
- private featureOverrides;
157
- private initializationPromise;
158
- private tenantHierarchyPromise;
159
- constructor(options?: SmrtClassOptions, resolverOptions?: FeatureResolverOptions);
160
- isEnabled(featureKey: string, context?: FeatureResolutionContext): Promise<boolean>;
161
- isEnabledFor(classOrInstance: object | FeatureTargetConstructor, localId: string, context?: FeatureResolutionContext): Promise<boolean>;
162
- private ensureInitialized;
163
- private resolveBaseState;
164
- private applyOverride;
165
- private getTenantHierarchy;
166
- }
167
-
168
- export declare interface FeatureResolverOptions {
169
- tenantHierarchyLoader?: FeatureTenantHierarchyLoader;
170
- }
171
-
172
- export declare type FeatureScopeType = 'global' | 'tenant';
173
-
174
- export declare interface FeatureSyncResult {
175
- total: number;
176
- created: number;
177
- updated: number;
178
- unchanged: number;
179
- deleted: number;
180
- featureKeys: string[];
181
- }
182
-
183
- export declare class FeatureSyncService {
184
- private readonly options;
185
- private featureDefinitions;
186
- private initializationPromise;
187
- constructor(options?: SmrtClassOptions);
188
- syncDefinitions(options?: SyncDefinitionsOptions): Promise<FeatureSyncResult>;
189
- syncManifest(manifest: SmartObjectManifest, options?: SyncManifestOptions): Promise<FeatureSyncResult>;
190
- private ensureInitialized;
191
- private collectDefinitionsFromRegistrations;
192
- private collectTouchedPackagesFromRegistrations;
193
- private collectRegistrations;
194
- private applyDefinitions;
195
- }
196
-
197
- /**
198
- * Constructor type for any `@smrt()`-decorated class that may declare feature
199
- * toggles. Feature targets always extend `SmrtObject`, so this mirrors
200
- * `@happyvertical/smrt-core`'s internal (non-exported) `SmrtObjectConstructor`
201
- * and remains assignable to it for `ObjectRegistry.getClassByConstructor`.
202
- */
203
- declare type FeatureTargetConstructor = new (...args: unknown[]) => SmrtObject;
204
-
205
- export declare type FeatureTenantHierarchyLoader = (options: SmrtClassOptions) => Promise<FeatureTenantHierarchyProvider | null>;
206
-
207
- export declare interface FeatureTenantHierarchyProvider {
208
- getChain(tenantId: string): Promise<FeatureTenantNode[]>;
209
- }
210
-
211
- export declare interface FeatureTenantNode {
212
- id: string;
213
- inheritPermissions: boolean;
214
- cascadePermissions: boolean;
215
- }
216
-
217
- export declare interface FeatureUsersModule {
218
- TenantCollection: {
219
- create(options: SmrtClassOptions): Promise<{
220
- get(criteria: {
221
- id: string;
222
- }): Promise<FeatureUsersTenantRecord | null>;
223
- getAncestorsFromRoot(tenantId: string): Promise<FeatureUsersTenantRecord[]>;
224
- }>;
225
- };
226
- }
227
-
228
- /**
229
- * Minimal structural shape of a tenant record returned by
230
- * `@happyvertical/smrt-users`. Only the permission-cascade fields consumed by
231
- * feature resolution are modeled; everything else is left unconstrained.
232
- */
233
- declare interface FeatureUsersTenantRecord {
234
- id: string;
235
- inheritPermissions?: boolean;
236
- cascadePermissions?: boolean;
237
- }
238
-
239
- export declare function findFeatureDefaultInRegistry(featureKey: string): boolean | undefined;
240
-
241
- export declare const GLOBAL_FEATURE_SCOPE_ID = "*";
242
-
243
- export declare function parseFeatureKey(featureKey: string): {
244
- qualifiedClassName: string;
245
- localId: string;
246
- };
247
-
248
- export declare function resolveFeatureKeyForTarget(classOrInstance: object | FeatureTargetConstructor, localId: string): {
249
- featureKey: string;
250
- defaultEnabled: boolean;
251
- };
252
-
253
- export declare interface SyncDefinitionsOptions {
254
- classNames?: string[];
255
- constructors?: FeatureTargetConstructor[];
256
- pruneStale?: boolean;
257
- }
258
-
259
- export declare interface SyncManifestOptions {
260
- pruneStale?: boolean;
261
- }
262
-
263
- export { }
1
+ export { FeatureDefinition } from './feature-definition.js';
2
+ export { FeatureDefinitionCollection } from './feature-definitions.js';
3
+ export { FeatureOverride } from './feature-override.js';
4
+ export { FeatureOverrideAuthorizationError, type FeatureOverrideAuthorizer, FeatureOverrideService, type FeatureOverrideWriteRequest, } from './feature-override-service.js';
5
+ export { FeatureOverrideCollection } from './feature-overrides.js';
6
+ export { FeatureResolver } from './feature-resolver.js';
7
+ export { type FeatureSettingsRow, FeatureSettingsService, type FeatureSettingsServiceOptions, featureOverrideEffectFromValue, InvalidFeatureScopeError, type ListFeatureSettingsOptions, type SetFeatureOverrideRequest, UnknownFeatureKeyError, } from './feature-settings.js';
8
+ export { FeatureSyncService } from './feature-sync.js';
9
+ export { type FeatureDefinitionOptions, type FeatureDefinitionSeed, type FeatureMetadata, FeatureOverrideEffect, type FeatureOverrideOptions, type FeatureResolutionContext, type FeatureResolverOptions, type FeatureScopeType, type FeatureSyncResult, type FeatureTenantHierarchyLoader, type FeatureTenantHierarchyProvider, type FeatureTenantNode, type FeatureUsersModule, GLOBAL_FEATURE_SCOPE_ID, type SyncDefinitionsOptions, type SyncManifestOptions, } from './types.js';
10
+ export { createFeatureKey, findFeatureDefaultInRegistry, parseFeatureKey, resolveFeatureKeyForTarget, } from './utils.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,wBAAwB,CAAC;AAEhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,iCAAiC,EACjC,KAAK,yBAAyB,EAC9B,sBAAsB,EACtB,KAAK,2BAA2B,GACjC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,KAAK,kBAAkB,EACvB,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,8BAA8B,EAC9B,wBAAwB,EACxB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,4BAA4B,EACjC,KAAK,8BAA8B,EACnC,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,uBAAuB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,gBAAgB,EAChB,4BAA4B,EAC5B,eAAe,EACf,0BAA0B,GAC3B,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { FeatureOverrideEffect, GLOBAL_FEATURE_SCOPE_ID } from "./types.js";
2
2
  import { ObjectRegistry, SmrtCollection, SmrtObject, createQualifiedName, isQualifiedName, parseQualifiedName, smrt } from "@happyvertical/smrt-core";
3
3
  import { importWorkspaceModule } from "@happyvertical/smrt-core/utils/import-workspace-module";
4
4
  //#region src/__smrt-register__.ts
5
- ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-features\",\"packageVersion\":\"0.51.19\",\"objects\":{\"@happyvertical/smrt-features:FeatureDefinition\":{\"name\":\"featuredefinition\",\"className\":\"FeatureDefinition\",\"qualifiedName\":\"@happyvertical/smrt-features:FeatureDefinition\",\"collection\":\"featuredefinitions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/features/src/feature-definition.ts\",\"packageName\":\"@happyvertical/smrt-features\",\"fields\":{\"featureKey\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"packageName\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"qualifiedClassName\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"className\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"localId\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"defaultEnabled\":{\"type\":\"boolean\",\"required\":false,\"default\":false},\"label\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"metadata\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"visibility\":{\"type\":\"text\",\"required\":false,\"default\":\"public\"}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"FeatureMetadata\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"FeatureMetadata | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"FeatureMetadata\"},{\"type\":\"null\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_feature_definitions\",\"api\":false,\"cli\":false,\"mcp\":false,\"conflictColumns\":[\"feature_key\"]},\"extends\":\"SmrtObject\",\"exportName\":\"FeatureDefinition\",\"collectionExportName\":\"FeatureDefinitionCollection\",\"schema\":{\"tableName\":\"_smrt_feature_definitions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_feature_definitions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"feature_key\\\" TEXT DEFAULT '',\\n \\\"package_name\\\" TEXT DEFAULT '',\\n \\\"qualified_class_name\\\" TEXT DEFAULT '',\\n \\\"class_name\\\" TEXT DEFAULT '',\\n \\\"local_id\\\" TEXT DEFAULT '',\\n \\\"default_enabled\\\" BOOLEAN DEFAULT FALSE,\\n \\\"label\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"metadata\\\" TEXT DEFAULT '',\\n \\\"visibility\\\" TEXT DEFAULT 'public'\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"feature_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"package_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"qualified_class_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"class_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"local_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"default_enabled\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false},\"label\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"visibility\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"public\"}},\"indexes\":[{\"name\":\"_smrt_feature_definitions_feature_key_idx\",\"columns\":[\"feature_key\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"_smrt_feature_definitions_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"_smrt_feature_definitions_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"8813204c\"},\"importPath\":\"@happyvertical/smrt-features\"},\"@happyvertical/smrt-features:FeatureDefinitionCollection\":{\"name\":\"featuredefinitioncollection\",\"className\":\"FeatureDefinitionCollection\",\"qualifiedName\":\"@happyvertical/smrt-features:FeatureDefinitionCollection\",\"collection\":\"featuredefinitions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/features/src/feature-definitions.ts\",\"packageName\":\"@happyvertical/smrt-features\",\"fields\":{},\"methods\":{\"findByFeatureKey\":{\"name\":\"findByFeatureKey\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureDefinition | null>\",\"isStatic\":false,\"isPublic\":true},\"findByPackageName\":{\"name\":\"findByPackageName\",\"async\":true,\"parameters\":[{\"name\":\"packageName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureDefinition[]>\",\"isStatic\":false,\"isPublic\":true},\"upsertDefinition\":{\"name\":\"upsertDefinition\",\"async\":true,\"parameters\":[{\"name\":\"seed\",\"type\":\"FeatureDefinitionSeed\",\"optional\":false}],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_feature_definitions\",\"api\":false,\"mcp\":false,\"cli\":false},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"FeatureDefinition\",\"exportName\":\"FeatureDefinitionCollection\",\"collectionExportName\":\"FeatureDefinitionCollectionCollection\",\"schema\":{\"tableName\":\"_smrt_feature_definitions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_feature_definitions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"feature_key\\\" TEXT DEFAULT '',\\n \\\"package_name\\\" TEXT DEFAULT '',\\n \\\"qualified_class_name\\\" TEXT DEFAULT '',\\n \\\"class_name\\\" TEXT DEFAULT '',\\n \\\"local_id\\\" TEXT DEFAULT '',\\n \\\"default_enabled\\\" BOOLEAN DEFAULT FALSE,\\n \\\"label\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"metadata\\\" TEXT DEFAULT '',\\n \\\"visibility\\\" TEXT DEFAULT 'public'\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"feature_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"package_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"qualified_class_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"class_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"local_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"default_enabled\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false},\"label\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"visibility\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"public\"}},\"indexes\":[{\"name\":\"_smrt_feature_definitions_feature_key_idx\",\"columns\":[\"feature_key\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"_smrt_feature_definitions_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"_smrt_feature_definitions_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"8813204c\"},\"importPath\":\"@happyvertical/smrt-features\"},\"@happyvertical/smrt-features:FeatureOverride\":{\"name\":\"featureoverride\",\"className\":\"FeatureOverride\",\"qualifiedName\":\"@happyvertical/smrt-features:FeatureOverride\",\"collection\":\"featureoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/features/src/feature-override.ts\",\"packageName\":\"@happyvertical/smrt-features\",\"fields\":{\"featureKey\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"scopeType\":{\"type\":\"text\",\"required\":false,\"default\":\"global\"},\"scopeId\":{\"type\":\"text\",\"required\":false},\"effect\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"isInherit\":{\"name\":\"isInherit\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isEnabled\":{\"name\":\"isEnabled\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isDisabled\":{\"name\":\"isDisabled\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_feature_overrides\",\"api\":false,\"cli\":false,\"mcp\":false,\"conflictColumns\":[\"feature_key\",\"scope_type\",\"scope_id\"]},\"extends\":\"SmrtObject\",\"exportName\":\"FeatureOverride\",\"collectionExportName\":\"FeatureOverrideCollection\",\"schema\":{\"tableName\":\"_smrt_feature_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_feature_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"feature_key\\\" TEXT DEFAULT '',\\n \\\"scope_type\\\" TEXT DEFAULT 'global',\\n \\\"scope_id\\\" TEXT,\\n \\\"effect\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"feature_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"scope_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"global\"},\"scope_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"effect\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"_smrt_feature_overrides_feature_key_scope_type_idx\",\"columns\":[\"feature_key\",\"scope_type\",\"scope_id\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"_smrt_feature_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"_smrt_feature_overrides_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"d61cf901\"},\"importPath\":\"@happyvertical/smrt-features\"},\"@happyvertical/smrt-features:FeatureOverrideCollection\":{\"name\":\"featureoverridecollection\",\"className\":\"FeatureOverrideCollection\",\"qualifiedName\":\"@happyvertical/smrt-features:FeatureOverrideCollection\",\"collection\":\"featureoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/features/src/feature-overrides.ts\",\"packageName\":\"@happyvertical/smrt-features\",\"fields\":{},\"methods\":{\"findByFeatureKey\":{\"name\":\"findByFeatureKey\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride[]>\",\"isStatic\":false,\"isPublic\":true},\"findByFeatureAndScope\":{\"name\":\"findByFeatureAndScope\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"FeatureScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"getGlobalOverride\":{\"name\":\"getGlobalOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"getTenantOverride\":{\"name\":\"getTenantOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"getOverrideMap\":{\"name\":\"getOverrideMap\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"FeatureScopeType\",\"optional\":false},{\"name\":\"scopeIds\",\"type\":\"string[]\",\"optional\":false}],\"returnType\":\"Promise<Map<string, FeatureOverride>>\",\"isStatic\":false,\"isPublic\":true},\"setOverride\":{\"name\":\"setOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"FeatureScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false},{\"name\":\"effect\",\"type\":\"FeatureOverrideEffect\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride>\",\"isStatic\":false,\"isPublic\":true},\"setGlobalOverride\":{\"name\":\"setGlobalOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"effect\",\"type\":\"FeatureOverrideEffect\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride>\",\"isStatic\":false,\"isPublic\":true},\"setTenantOverride\":{\"name\":\"setTenantOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"effect\",\"type\":\"FeatureOverrideEffect\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride>\",\"isStatic\":false,\"isPublic\":true},\"removeOverride\":{\"name\":\"removeOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"FeatureScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_feature_overrides\",\"api\":false,\"mcp\":false,\"cli\":false},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"FeatureOverride\",\"exportName\":\"FeatureOverrideCollection\",\"collectionExportName\":\"FeatureOverrideCollectionCollection\",\"schema\":{\"tableName\":\"_smrt_feature_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_feature_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"feature_key\\\" TEXT DEFAULT '',\\n \\\"scope_type\\\" TEXT DEFAULT 'global',\\n \\\"scope_id\\\" TEXT,\\n \\\"effect\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"feature_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"scope_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"global\"},\"scope_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"effect\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"_smrt_feature_overrides_feature_key_scope_type_idx\",\"columns\":[\"feature_key\",\"scope_type\",\"scope_id\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"_smrt_feature_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"_smrt_feature_overrides_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"d61cf901\"},\"importPath\":\"@happyvertical/smrt-features\"}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-core\",\"@happyvertical/smrt-users\"]}"));
5
+ ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-features\",\"packageVersion\":\"0.51.20\",\"objects\":{\"@happyvertical/smrt-features:FeatureDefinition\":{\"name\":\"featuredefinition\",\"className\":\"FeatureDefinition\",\"qualifiedName\":\"@happyvertical/smrt-features:FeatureDefinition\",\"collection\":\"featuredefinitions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/features/src/feature-definition.ts\",\"packageName\":\"@happyvertical/smrt-features\",\"fields\":{\"featureKey\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"packageName\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"qualifiedClassName\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"className\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"localId\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"defaultEnabled\":{\"type\":\"boolean\",\"required\":false,\"default\":false},\"label\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"metadata\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"visibility\":{\"type\":\"text\",\"required\":false,\"default\":\"public\"}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"FeatureMetadata\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"FeatureMetadata | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"FeatureMetadata\"},{\"type\":\"null\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_feature_definitions\",\"api\":false,\"cli\":false,\"mcp\":false,\"conflictColumns\":[\"feature_key\"]},\"extends\":\"SmrtObject\",\"exportName\":\"FeatureDefinition\",\"collectionExportName\":\"FeatureDefinitionCollection\",\"schema\":{\"tableName\":\"_smrt_feature_definitions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_feature_definitions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"feature_key\\\" TEXT DEFAULT '',\\n \\\"package_name\\\" TEXT DEFAULT '',\\n \\\"qualified_class_name\\\" TEXT DEFAULT '',\\n \\\"class_name\\\" TEXT DEFAULT '',\\n \\\"local_id\\\" TEXT DEFAULT '',\\n \\\"default_enabled\\\" BOOLEAN DEFAULT FALSE,\\n \\\"label\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"metadata\\\" TEXT DEFAULT '',\\n \\\"visibility\\\" TEXT DEFAULT 'public'\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"feature_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"package_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"qualified_class_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"class_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"local_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"default_enabled\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false},\"label\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"visibility\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"public\"}},\"indexes\":[{\"name\":\"_smrt_feature_definitions_feature_key_idx\",\"columns\":[\"feature_key\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"_smrt_feature_definitions_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"_smrt_feature_definitions_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"8813204c\"},\"importPath\":\"@happyvertical/smrt-features\"},\"@happyvertical/smrt-features:FeatureDefinitionCollection\":{\"name\":\"featuredefinitioncollection\",\"className\":\"FeatureDefinitionCollection\",\"qualifiedName\":\"@happyvertical/smrt-features:FeatureDefinitionCollection\",\"collection\":\"featuredefinitions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/features/src/feature-definitions.ts\",\"packageName\":\"@happyvertical/smrt-features\",\"fields\":{},\"methods\":{\"findByFeatureKey\":{\"name\":\"findByFeatureKey\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureDefinition | null>\",\"isStatic\":false,\"isPublic\":true},\"findByPackageName\":{\"name\":\"findByPackageName\",\"async\":true,\"parameters\":[{\"name\":\"packageName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureDefinition[]>\",\"isStatic\":false,\"isPublic\":true},\"upsertDefinition\":{\"name\":\"upsertDefinition\",\"async\":true,\"parameters\":[{\"name\":\"seed\",\"type\":\"FeatureDefinitionSeed\",\"optional\":false}],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_feature_definitions\",\"api\":false,\"mcp\":false,\"cli\":false},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"FeatureDefinition\",\"exportName\":\"FeatureDefinitionCollection\",\"collectionExportName\":\"FeatureDefinitionCollectionCollection\",\"schema\":{\"tableName\":\"_smrt_feature_definitions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_feature_definitions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"feature_key\\\" TEXT DEFAULT '',\\n \\\"package_name\\\" TEXT DEFAULT '',\\n \\\"qualified_class_name\\\" TEXT DEFAULT '',\\n \\\"class_name\\\" TEXT DEFAULT '',\\n \\\"local_id\\\" TEXT DEFAULT '',\\n \\\"default_enabled\\\" BOOLEAN DEFAULT FALSE,\\n \\\"label\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"metadata\\\" TEXT DEFAULT '',\\n \\\"visibility\\\" TEXT DEFAULT 'public'\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"feature_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"package_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"qualified_class_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"class_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"local_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"default_enabled\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false},\"label\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"visibility\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"public\"}},\"indexes\":[{\"name\":\"_smrt_feature_definitions_feature_key_idx\",\"columns\":[\"feature_key\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"_smrt_feature_definitions_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"_smrt_feature_definitions_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"8813204c\"},\"importPath\":\"@happyvertical/smrt-features\"},\"@happyvertical/smrt-features:FeatureOverride\":{\"name\":\"featureoverride\",\"className\":\"FeatureOverride\",\"qualifiedName\":\"@happyvertical/smrt-features:FeatureOverride\",\"collection\":\"featureoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/features/src/feature-override.ts\",\"packageName\":\"@happyvertical/smrt-features\",\"fields\":{\"featureKey\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"scopeType\":{\"type\":\"text\",\"required\":false,\"default\":\"global\"},\"scopeId\":{\"type\":\"text\",\"required\":false},\"effect\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"isInherit\":{\"name\":\"isInherit\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isEnabled\":{\"name\":\"isEnabled\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isDisabled\":{\"name\":\"isDisabled\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_feature_overrides\",\"api\":false,\"cli\":false,\"mcp\":false,\"conflictColumns\":[\"feature_key\",\"scope_type\",\"scope_id\"]},\"extends\":\"SmrtObject\",\"exportName\":\"FeatureOverride\",\"collectionExportName\":\"FeatureOverrideCollection\",\"schema\":{\"tableName\":\"_smrt_feature_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_feature_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"feature_key\\\" TEXT DEFAULT '',\\n \\\"scope_type\\\" TEXT DEFAULT 'global',\\n \\\"scope_id\\\" TEXT,\\n \\\"effect\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"feature_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"scope_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"global\"},\"scope_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"effect\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"_smrt_feature_overrides_feature_key_scope_type_idx\",\"columns\":[\"feature_key\",\"scope_type\",\"scope_id\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"_smrt_feature_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"_smrt_feature_overrides_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"d61cf901\"},\"importPath\":\"@happyvertical/smrt-features\"},\"@happyvertical/smrt-features:FeatureOverrideCollection\":{\"name\":\"featureoverridecollection\",\"className\":\"FeatureOverrideCollection\",\"qualifiedName\":\"@happyvertical/smrt-features:FeatureOverrideCollection\",\"collection\":\"featureoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/features/src/feature-overrides.ts\",\"packageName\":\"@happyvertical/smrt-features\",\"fields\":{},\"methods\":{\"findByFeatureKey\":{\"name\":\"findByFeatureKey\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride[]>\",\"isStatic\":false,\"isPublic\":true},\"findByFeatureAndScope\":{\"name\":\"findByFeatureAndScope\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"FeatureScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"getGlobalOverride\":{\"name\":\"getGlobalOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"getTenantOverride\":{\"name\":\"getTenantOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"getOverrideMap\":{\"name\":\"getOverrideMap\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"FeatureScopeType\",\"optional\":false},{\"name\":\"scopeIds\",\"type\":\"string[]\",\"optional\":false}],\"returnType\":\"Promise<Map<string, FeatureOverride>>\",\"isStatic\":false,\"isPublic\":true},\"setOverride\":{\"name\":\"setOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"FeatureScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false},{\"name\":\"effect\",\"type\":\"FeatureOverrideEffect\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride>\",\"isStatic\":false,\"isPublic\":true},\"setGlobalOverride\":{\"name\":\"setGlobalOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"effect\",\"type\":\"FeatureOverrideEffect\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride>\",\"isStatic\":false,\"isPublic\":true},\"setTenantOverride\":{\"name\":\"setTenantOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"effect\",\"type\":\"FeatureOverrideEffect\",\"optional\":false}],\"returnType\":\"Promise<FeatureOverride>\",\"isStatic\":false,\"isPublic\":true},\"removeOverride\":{\"name\":\"removeOverride\",\"async\":true,\"parameters\":[{\"name\":\"featureKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"FeatureScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_feature_overrides\",\"api\":false,\"mcp\":false,\"cli\":false},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"FeatureOverride\",\"exportName\":\"FeatureOverrideCollection\",\"collectionExportName\":\"FeatureOverrideCollectionCollection\",\"schema\":{\"tableName\":\"_smrt_feature_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_feature_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"feature_key\\\" TEXT DEFAULT '',\\n \\\"scope_type\\\" TEXT DEFAULT 'global',\\n \\\"scope_id\\\" TEXT,\\n \\\"effect\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"feature_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"scope_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"global\"},\"scope_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"effect\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"_smrt_feature_overrides_feature_key_scope_type_idx\",\"columns\":[\"feature_key\",\"scope_type\",\"scope_id\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"_smrt_feature_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"_smrt_feature_overrides_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"d61cf901\"},\"importPath\":\"@happyvertical/smrt-features\"}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-core\",\"@happyvertical/smrt-users\"]}"));
6
6
  //#endregion
7
7
  //#region src/utils.ts
8
8
  function createFeatureKey(qualifiedClassName, localId) {
@@ -496,6 +496,159 @@ function isMissingUsersDependency(error) {
496
496
  return text.includes("@happyvertical/smrt-users") && (text.includes("Cannot find module") || text.includes("Failed to load") || text.includes("could not find"));
497
497
  }
498
498
  //#endregion
499
+ //#region src/feature-settings.ts
500
+ var UnknownFeatureKeyError = class extends Error {
501
+ constructor(featureKey) {
502
+ super(`Unknown feature key: ${featureKey}`);
503
+ this.featureKey = featureKey;
504
+ this.name = "UnknownFeatureKeyError";
505
+ }
506
+ featureKey;
507
+ status = 400;
508
+ };
509
+ var InvalidFeatureScopeError = class extends Error {
510
+ constructor(scopeType, scopeId, reason) {
511
+ super(`Invalid feature override scope (${scopeType}): ${reason}`);
512
+ this.scopeType = scopeType;
513
+ this.scopeId = scopeId;
514
+ this.name = "InvalidFeatureScopeError";
515
+ }
516
+ scopeType;
517
+ scopeId;
518
+ status = 400;
519
+ };
520
+ var KNOWN_EFFECTS = new Set(Object.values(FeatureOverrideEffect));
521
+ function featureOverrideEffectFromValue(value) {
522
+ if (value === FeatureOverrideEffect.ENABLE) return FeatureOverrideEffect.ENABLE;
523
+ if (value === FeatureOverrideEffect.DISABLE) return FeatureOverrideEffect.DISABLE;
524
+ return FeatureOverrideEffect.INHERIT;
525
+ }
526
+ var FeatureSettingsService = class FeatureSettingsService {
527
+ constructor(definitions, overrides, resolver, authorize) {
528
+ this.definitions = definitions;
529
+ this.overrides = overrides;
530
+ this.resolver = resolver;
531
+ this.writes = new FeatureOverrideService(overrides, authorize ?? (() => false));
532
+ }
533
+ definitions;
534
+ overrides;
535
+ resolver;
536
+ writes;
537
+ /**
538
+ * Build a service over the given database options.
539
+ *
540
+ * @param options - SMRT database options, as passed to any collection.
541
+ * @param serviceOptions - Host authorizer and resolver wiring. Omit
542
+ * `authorize` for a read-only (load-function) service.
543
+ */
544
+ static async create(options = {}, serviceOptions = {}) {
545
+ const [definitions, overrides] = await Promise.all([FeatureDefinitionCollection.create(options), FeatureOverrideCollection.create(options)]);
546
+ return new FeatureSettingsService(definitions, overrides, new FeatureResolver(options, serviceOptions.resolver ?? {}), serviceOptions.authorize);
547
+ }
548
+ /**
549
+ * One {@link FeatureSettingsRow} per matching definition, ordered by owning
550
+ * package, then label, then key, so a rendered list is stable across loads.
551
+ *
552
+ * Makes no authorization decision — the caller has already decided that this
553
+ * principal may see this tenant's flags.
554
+ */
555
+ async listFeatureSettings(options = {}) {
556
+ const definitions = await this.loadDefinitions(options);
557
+ return Promise.all(definitions.map((definition) => this.toRow(definition, options.tenantId)));
558
+ }
559
+ /** The single row for one key, or `null` when no definition owns that key. */
560
+ async getFeatureSetting(featureKey, tenantId) {
561
+ const definition = await this.definitions.findByFeatureKey(featureKey);
562
+ return definition ? this.toRow(definition, tenantId) : null;
563
+ }
564
+ /**
565
+ * Apply one override change.
566
+ *
567
+ * Refuses any `featureKey` without a {@link FeatureDefinition} row and any
568
+ * scope the resolver would never read back, then delegates to
569
+ * {@link FeatureOverrideService} so the host authorizer decides whether this
570
+ * caller may write this scope. `INHERIT` removes the row.
571
+ *
572
+ * @returns the stored override, or `null` when the row was removed (or was
573
+ * already absent).
574
+ * @throws {UnknownFeatureKeyError} when the key has no definition.
575
+ * @throws {InvalidFeatureScopeError} when the scope is not one the resolver reads.
576
+ * @throws `FeatureOverrideAuthorizationError` when the authorizer declines.
577
+ */
578
+ async setFeatureOverride(request) {
579
+ const { featureKey, scopeType, scopeId, effect } = request;
580
+ if (!KNOWN_EFFECTS.has(effect)) throw new TypeError(`Unknown feature override effect: ${String(effect)}`);
581
+ assertValidFeatureScope(scopeType, scopeId);
582
+ await this.assertKnownFeatureKey(featureKey);
583
+ if (effect === FeatureOverrideEffect.INHERIT) {
584
+ await this.writes.removeOverride(featureKey, scopeType, scopeId);
585
+ return null;
586
+ }
587
+ return this.writes.setOverride(featureKey, scopeType, scopeId, effect);
588
+ }
589
+ /** {@link setFeatureOverride} for the global scope. */
590
+ async setGlobalFeatureOverride(featureKey, effect) {
591
+ return this.setFeatureOverride({
592
+ featureKey,
593
+ scopeType: "global",
594
+ scopeId: "*",
595
+ effect
596
+ });
597
+ }
598
+ /** {@link setFeatureOverride} for one tenant. */
599
+ async setTenantFeatureOverride(featureKey, tenantId, effect) {
600
+ return this.setFeatureOverride({
601
+ featureKey,
602
+ scopeType: "tenant",
603
+ scopeId: tenantId,
604
+ effect
605
+ });
606
+ }
607
+ async assertKnownFeatureKey(featureKey) {
608
+ const key = typeof featureKey === "string" ? featureKey.trim() : "";
609
+ if (!key || key !== featureKey) throw new UnknownFeatureKeyError(String(featureKey));
610
+ if (!await this.definitions.findByFeatureKey(key)) throw new UnknownFeatureKeyError(key);
611
+ }
612
+ async loadDefinitions(options) {
613
+ const definitions = options.packageName ? await this.definitions.findByPackageName(options.packageName) : await this.definitions.list({});
614
+ const allowed = options.featureKeys ? new Set(options.featureKeys) : null;
615
+ return [...allowed ? definitions.filter((definition) => allowed.has(definition.featureKey)) : definitions].sort(compareDefinitions);
616
+ }
617
+ async toRow(definition, tenantId) {
618
+ const { featureKey } = definition;
619
+ const [globalOverride, tenantOverride, effectiveEnabled] = await Promise.all([
620
+ this.overrides.getGlobalOverride(featureKey),
621
+ tenantId ? this.overrides.getTenantOverride(featureKey, tenantId) : Promise.resolve(null),
622
+ this.resolver.isEnabled(featureKey, tenantId ? { tenantId } : {})
623
+ ]);
624
+ return {
625
+ featureKey,
626
+ label: definition.label,
627
+ description: definition.description,
628
+ packageName: definition.packageName,
629
+ qualifiedClassName: definition.qualifiedClassName,
630
+ className: definition.className,
631
+ localId: definition.localId,
632
+ visibility: definition.visibility,
633
+ metadata: definition.getMetadata(),
634
+ defaultEnabled: definition.defaultEnabled,
635
+ effectiveEnabled,
636
+ globalEffect: globalOverride?.effect ?? null,
637
+ tenantEffect: tenantOverride?.effect ?? null,
638
+ inheritedEnabled: tenantId && !tenantOverride ? effectiveEnabled : null
639
+ };
640
+ }
641
+ };
642
+ function assertValidFeatureScope(scopeType, scopeId) {
643
+ if (scopeType !== "global" && scopeType !== "tenant") throw new InvalidFeatureScopeError(String(scopeType), String(scopeId), "scope type must be \"global\" or \"tenant\"");
644
+ if (typeof scopeId !== "string") throw new InvalidFeatureScopeError(scopeType, String(scopeId), "scope id must be a string");
645
+ if (scopeType === "global" && scopeId !== "*") throw new InvalidFeatureScopeError(scopeType, scopeId, `the global scope is only ever "*"`);
646
+ if (scopeType === "tenant" && (!scopeId.trim() || scopeId !== scopeId.trim())) throw new InvalidFeatureScopeError(scopeType, scopeId, "a tenant scope id must be non-blank and already trimmed");
647
+ }
648
+ function compareDefinitions(a, b) {
649
+ return a.packageName.localeCompare(b.packageName) || (a.label || a.featureKey).localeCompare(b.label || b.featureKey) || a.featureKey.localeCompare(b.featureKey);
650
+ }
651
+ //#endregion
499
652
  //#region src/feature-sync.ts
500
653
  var FeatureSyncService = class {
501
654
  options;
@@ -581,6 +734,6 @@ var FeatureSyncService = class {
581
734
  }
582
735
  };
583
736
  //#endregion
584
- export { FeatureDefinition, FeatureDefinitionCollection, FeatureOverride, FeatureOverrideAuthorizationError, FeatureOverrideCollection, FeatureOverrideEffect, FeatureOverrideService, FeatureResolver, FeatureSyncService, GLOBAL_FEATURE_SCOPE_ID, createFeatureKey, findFeatureDefaultInRegistry, parseFeatureKey, resolveFeatureKeyForTarget };
737
+ export { FeatureDefinition, FeatureDefinitionCollection, FeatureOverride, FeatureOverrideAuthorizationError, FeatureOverrideCollection, FeatureOverrideEffect, FeatureOverrideService, FeatureResolver, FeatureSettingsService, FeatureSyncService, GLOBAL_FEATURE_SCOPE_ID, InvalidFeatureScopeError, UnknownFeatureKeyError, createFeatureKey, featureOverrideEffectFromValue, findFeatureDefaultInRegistry, parseFeatureKey, resolveFeatureKeyForTarget };
585
738
 
586
739
  //# sourceMappingURL=index.js.map