gemi 0.56.0 → 0.58.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/dist/app/index.js +1 -1
- package/dist/broadcasting/index.js +1 -1
- package/dist/bun/plugin.js +1 -1
- package/dist/bun/preload.js +1 -1
- package/dist/{chunk-jdj7k3r9.js → chunk-0a2xgcj3.js} +2 -2
- package/dist/{chunk-jdj7k3r9.js.map → chunk-0a2xgcj3.js.map} +1 -1
- package/dist/{chunk-3e88tyee.js → chunk-3337e5g0.js} +2 -2
- package/dist/{chunk-3e88tyee.js.map → chunk-3337e5g0.js.map} +1 -1
- package/dist/chunk-3aa287k7.js +6 -0
- package/dist/{chunk-cv9w5cmb.js.map → chunk-3aa287k7.js.map} +2 -2
- package/dist/{chunk-01am9k5v.js → chunk-3g5bjvdf.js} +2 -2
- package/dist/{chunk-01am9k5v.js.map → chunk-3g5bjvdf.js.map} +1 -1
- package/dist/{chunk-w9k9s4wh.js → chunk-3xadx444.js} +2 -2
- package/dist/{chunk-w9k9s4wh.js.map → chunk-3xadx444.js.map} +1 -1
- package/dist/{chunk-npg72mez.js → chunk-3zxwscmf.js} +2 -2
- package/dist/{chunk-kgmr9qxx.js.map → chunk-3zxwscmf.js.map} +1 -1
- package/dist/{chunk-64s1pzz1.js → chunk-437085pe.js} +2 -2
- package/dist/{chunk-64s1pzz1.js.map → chunk-437085pe.js.map} +1 -1
- package/dist/{chunk-eqrd31ye.js → chunk-4yt5x8s2.js} +2 -2
- package/dist/{chunk-eqrd31ye.js.map → chunk-4yt5x8s2.js.map} +1 -1
- package/dist/{chunk-9r0sb4zn.js → chunk-5athahgr.js} +2 -2
- package/dist/{chunk-9r0sb4zn.js.map → chunk-5athahgr.js.map} +1 -1
- package/dist/{chunk-g30q4n5y.js → chunk-5n2rvfh3.js} +2 -2
- package/dist/{chunk-g30q4n5y.js.map → chunk-5n2rvfh3.js.map} +1 -1
- package/dist/{chunk-1zfsgffv.js → chunk-6235kb30.js} +3 -3
- package/dist/{chunk-1zfsgffv.js.map → chunk-6235kb30.js.map} +1 -1
- package/dist/{chunk-javjeayw.js → chunk-7b0x860b.js} +2 -2
- package/dist/{chunk-javjeayw.js.map → chunk-7b0x860b.js.map} +1 -1
- package/dist/{chunk-4qwwy968.js → chunk-7ef5n8k2.js} +2 -2
- package/dist/{chunk-4qwwy968.js.map → chunk-7ef5n8k2.js.map} +1 -1
- package/dist/{chunk-q0waxxz5.js → chunk-7j6wbv12.js} +2 -2
- package/dist/{chunk-q0waxxz5.js.map → chunk-7j6wbv12.js.map} +1 -1
- package/dist/chunk-86jebsm4.js +9 -0
- package/dist/{chunk-kry5vwam.js.map → chunk-86jebsm4.js.map} +3 -3
- package/dist/chunk-87qab82w.js +5 -0
- package/dist/chunk-87qab82w.js.map +37 -0
- package/dist/{chunk-36pg61vt.js → chunk-8gew8b9a.js} +2 -2
- package/dist/{chunk-36pg61vt.js.map → chunk-8gew8b9a.js.map} +1 -1
- package/dist/{chunk-v6v6sem5.js → chunk-9m2tbf3n.js} +2 -2
- package/dist/{chunk-v6v6sem5.js.map → chunk-9m2tbf3n.js.map} +1 -1
- package/dist/{chunk-gzdf2025.js → chunk-a2sgjpvq.js} +2 -2
- package/dist/{chunk-gzdf2025.js.map → chunk-a2sgjpvq.js.map} +1 -1
- package/dist/chunk-b35e128b.js +5 -0
- package/dist/{chunk-b50zmz3t.js.map → chunk-b35e128b.js.map} +1 -1
- package/dist/{chunk-ct274qts.js → chunk-cyaz97p5.js} +2 -2
- package/dist/{chunk-ct274qts.js.map → chunk-cyaz97p5.js.map} +1 -1
- package/dist/{chunk-v06qcyj5.js → chunk-d125j8t0.js} +3 -3
- package/dist/{chunk-v06qcyj5.js.map → chunk-d125j8t0.js.map} +1 -1
- package/dist/{chunk-hs5v3eqj.js → chunk-dgsgjg53.js} +2 -2
- package/dist/{chunk-hs5v3eqj.js.map → chunk-dgsgjg53.js.map} +1 -1
- package/dist/{chunk-xjy5apyr.js → chunk-eejmhtnc.js} +2 -2
- package/dist/{chunk-xjy5apyr.js.map → chunk-eejmhtnc.js.map} +1 -1
- package/dist/{chunk-3y75q5a2.js → chunk-fjm4y8bn.js} +2 -2
- package/dist/{chunk-3y75q5a2.js.map → chunk-fjm4y8bn.js.map} +1 -1
- package/dist/{chunk-9c89q2mz.js → chunk-grdahng8.js} +2 -2
- package/dist/{chunk-9c89q2mz.js.map → chunk-grdahng8.js.map} +1 -1
- package/dist/{chunk-699z6d8y.js → chunk-gw6agevz.js} +3 -3
- package/dist/{chunk-699z6d8y.js.map → chunk-gw6agevz.js.map} +1 -1
- package/dist/{chunk-62ke19q4.js → chunk-hppagzz4.js} +4 -4
- package/dist/{chunk-62ke19q4.js.map → chunk-hppagzz4.js.map} +1 -1
- package/dist/chunk-hwa5sqw5.js +19 -0
- package/dist/{chunk-tmnhkphv.js.map → chunk-hwa5sqw5.js.map} +12 -6
- package/dist/chunk-hxf1re93.js +4 -0
- package/dist/{chunk-vkngcrzq.js.map → chunk-hxf1re93.js.map} +6 -5
- package/dist/{chunk-d36dfqxw.js → chunk-j0c6ytkj.js} +3 -3
- package/dist/{chunk-d36dfqxw.js.map → chunk-j0c6ytkj.js.map} +1 -1
- package/dist/{chunk-kgmr9qxx.js → chunk-jhkjz9jr.js} +2 -2
- package/dist/{chunk-npg72mez.js.map → chunk-jhkjz9jr.js.map} +1 -1
- package/dist/{chunk-62723jyy.js → chunk-k0fvsyeh.js} +1 -1
- package/dist/{chunk-31kcf7dq.js → chunk-keehyx51.js} +2 -2
- package/dist/{chunk-31kcf7dq.js.map → chunk-keehyx51.js.map} +1 -1
- package/dist/{chunk-enhkf60v.js → chunk-m3xy5xyf.js} +2 -2
- package/dist/{chunk-enhkf60v.js.map → chunk-m3xy5xyf.js.map} +1 -1
- package/dist/{chunk-c75mymmq.js → chunk-mkfpnymy.js} +1 -1
- package/dist/{chunk-rgb69nh1.js → chunk-mwpdp09e.js} +2 -2
- package/dist/{chunk-rgb69nh1.js.map → chunk-mwpdp09e.js.map} +1 -1
- package/dist/chunk-pmhd6zfc.js +37 -0
- package/dist/chunk-pmhd6zfc.js.map +20 -0
- package/dist/chunk-qb5mv6pj.js +5 -0
- package/dist/chunk-qb5mv6pj.js.map +12 -0
- package/dist/{chunk-1pwwrpa3.js → chunk-qgxr0g36.js} +2 -2
- package/dist/{chunk-1pwwrpa3.js.map → chunk-qgxr0g36.js.map} +1 -1
- package/dist/{chunk-4yafsffx.js → chunk-sy7jbdeb.js} +2 -2
- package/dist/{chunk-4yafsffx.js.map → chunk-sy7jbdeb.js.map} +1 -1
- package/dist/{chunk-gasdfwva.js → chunk-szss069z.js} +2 -2
- package/dist/{chunk-gasdfwva.js.map → chunk-szss069z.js.map} +1 -1
- package/dist/{chunk-m0ggfy1m.js → chunk-tss5svjr.js} +2 -2
- package/dist/{chunk-m0ggfy1m.js.map → chunk-tss5svjr.js.map} +1 -1
- package/dist/{chunk-dzzmqv0j.js → chunk-vr90r27j.js} +2 -2
- package/dist/{chunk-dzzmqv0j.js.map → chunk-vr90r27j.js.map} +1 -1
- package/dist/{chunk-pvdbrt4z.js → chunk-w62m5f0n.js} +3 -3
- package/dist/{chunk-pvdbrt4z.js.map → chunk-w62m5f0n.js.map} +1 -1
- package/dist/{chunk-cn2r5jfj.js → chunk-w7rf99w6.js} +2 -2
- package/dist/{chunk-cn2r5jfj.js.map → chunk-w7rf99w6.js.map} +1 -1
- package/dist/{chunk-tja0c815.js → chunk-wbrj0gya.js} +2 -2
- package/dist/{chunk-tja0c815.js.map → chunk-wbrj0gya.js.map} +1 -1
- package/dist/{chunk-rsdg619q.js → chunk-xdv1b8mr.js} +2 -2
- package/dist/{chunk-rsdg619q.js.map → chunk-xdv1b8mr.js.map} +1 -1
- package/dist/{chunk-h3mwgbg7.js → chunk-xey9cbap.js} +2 -2
- package/dist/{chunk-h3mwgbg7.js.map → chunk-xey9cbap.js.map} +1 -1
- package/dist/{chunk-wgpa04jb.js → chunk-xzk827r3.js} +2 -2
- package/dist/{chunk-wgpa04jb.js.map → chunk-xzk827r3.js.map} +1 -1
- package/dist/{chunk-x14sk95v.js → chunk-y6a8r2bn.js} +3 -3
- package/dist/{chunk-x14sk95v.js.map → chunk-y6a8r2bn.js.map} +1 -1
- package/dist/{chunk-33wjsw4r.js → chunk-yed5whgs.js} +3 -3
- package/dist/{chunk-33wjsw4r.js.map → chunk-yed5whgs.js.map} +1 -1
- package/dist/{chunk-02gdzs5t.js → chunk-yf7vz71n.js} +1 -1
- package/dist/{chunk-y9fp58bg.js → chunk-yjzs247s.js} +2 -2
- package/dist/{chunk-y9fp58bg.js.map → chunk-yjzs247s.js.map} +1 -1
- package/dist/{chunk-kgg1eqne.js → chunk-yy0eb9wn.js} +2 -2
- package/dist/{chunk-kgg1eqne.js.map → chunk-yy0eb9wn.js.map} +1 -1
- package/dist/{chunk-4xx78ba9.js → chunk-zbxgbr12.js} +2 -2
- package/dist/{chunk-4xx78ba9.js.map → chunk-zbxgbr12.js.map} +1 -1
- package/dist/{chunk-8k1zqrvh.js → chunk-zh2egcyb.js} +2 -2
- package/dist/{chunk-8k1zqrvh.js.map → chunk-zh2egcyb.js.map} +1 -1
- package/dist/chunks/ThemeProvider-li1J_igh.js.map +1 -1
- package/dist/client/ClientRouter.d.ts.map +1 -1
- package/dist/client/ProgressManager.d.ts +1 -1
- package/dist/client/RouteStateContext.d.ts +9 -0
- package/dist/client/RouteStateContext.d.ts.map +1 -1
- package/dist/client/ServerDataProvider.d.ts +7 -0
- package/dist/client/ServerDataProvider.d.ts.map +1 -1
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +68 -10
- package/dist/client/index.js.map +1 -1
- package/dist/client/rpc.d.ts +42 -0
- package/dist/client/rpc.d.ts.map +1 -1
- package/dist/client/useFeature.d.ts +40 -0
- package/dist/client/useFeature.d.ts.map +1 -0
- package/dist/config/index.js +1 -1
- package/dist/console/run.js +2 -2
- package/dist/console/run.js.map +1 -1
- package/dist/container/index.js +2 -2
- package/dist/container/index.js.map +1 -1
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/email/index.js +2 -2
- package/dist/email/index.js.map +1 -1
- package/dist/facades/Features.d.ts +57 -0
- package/dist/facades/Features.d.ts.map +1 -0
- package/dist/facades/index.d.ts +1 -0
- package/dist/facades/index.d.ts.map +1 -1
- package/dist/facades/index.js +2 -2
- package/dist/facades/index.js.map +1 -1
- package/dist/foundation/index.js +2 -2
- package/dist/foundation/index.js.map +1 -1
- package/dist/gemi.d.ts +13 -5
- package/dist/http/ApiRouter.d.ts +3 -2
- package/dist/http/ApiRouter.d.ts.map +1 -1
- package/dist/http/HttpRequest.d.ts +4 -0
- package/dist/http/HttpRequest.d.ts.map +1 -1
- package/dist/http/ViewRouter.d.ts +127 -4
- package/dist/http/ViewRouter.d.ts.map +1 -1
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +2 -2
- package/dist/http/index.js.map +1 -1
- package/dist/http/middlewareList.d.ts +25 -0
- package/dist/http/middlewareList.d.ts.map +1 -0
- package/dist/http/requestContext.d.ts +57 -0
- package/dist/http/requestContext.d.ts.map +1 -1
- package/dist/i18n/dictionaryRuntime.js +2 -2
- package/dist/i18n/dictionaryRuntime.js.map +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +1 -1
- package/dist/ide/typescript-plugin/index.js +1206 -0
- package/dist/ide/typescript-plugin/index.js.map +17 -0
- package/dist/kernel/index.js +3 -3
- package/dist/kernel/index.js.map +3 -3
- package/dist/kernel/providers.d.ts +16 -4
- package/dist/kernel/providers.d.ts.map +1 -1
- package/dist/orm/context.d.ts +65 -0
- package/dist/orm/context.d.ts.map +1 -1
- package/dist/orm/index.js +2 -2
- package/dist/orm/index.js.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/services/discovery.d.ts +27 -0
- package/dist/services/discovery.d.ts.map +1 -1
- package/dist/services/events/Event.d.ts +208 -0
- package/dist/services/events/Event.d.ts.map +1 -0
- package/dist/services/events/EventManager.d.ts +285 -0
- package/dist/services/events/EventManager.d.ts.map +1 -0
- package/dist/services/events/EventServiceProvider.d.ts +46 -0
- package/dist/services/events/EventServiceProvider.d.ts.map +1 -0
- package/dist/services/events/FakeEventManager.d.ts +155 -0
- package/dist/services/events/FakeEventManager.d.ts.map +1 -0
- package/dist/services/events/FakeEventManager.test-d.d.ts +2 -0
- package/dist/services/events/FakeEventManager.test-d.d.ts.map +1 -0
- package/dist/services/events/Listener.d.ts +189 -0
- package/dist/services/events/Listener.d.ts.map +1 -0
- package/dist/services/events/Listener.test-d.d.ts +2 -0
- package/dist/services/events/Listener.test-d.d.ts.map +1 -0
- package/dist/services/events/config.d.ts +55 -0
- package/dist/services/events/config.d.ts.map +1 -0
- package/dist/services/events/listenerJob.d.ts +43 -0
- package/dist/services/events/listenerJob.d.ts.map +1 -0
- package/dist/services/features/FeatureFlagStore.d.ts +60 -0
- package/dist/services/features/FeatureFlagStore.d.ts.map +1 -0
- package/dist/services/features/FeatureManager.d.ts +82 -0
- package/dist/services/features/FeatureManager.d.ts.map +1 -0
- package/dist/services/features/FeaturesServiceProvider.d.ts +6 -0
- package/dist/services/features/FeaturesServiceProvider.d.ts.map +1 -0
- package/dist/services/features/bucket.d.ts +57 -0
- package/dist/services/features/bucket.d.ts.map +1 -0
- package/dist/services/features/config.d.ts +57 -0
- package/dist/services/features/config.d.ts.map +1 -0
- package/dist/services/features/context.d.ts +31 -0
- package/dist/services/features/context.d.ts.map +1 -0
- package/dist/services/features/defineFeature.d.ts +145 -0
- package/dist/services/features/defineFeature.d.ts.map +1 -0
- package/dist/services/features/evaluate.d.ts +74 -0
- package/dist/services/features/evaluate.d.ts.map +1 -0
- package/dist/services/features/sources/DatabaseFeatureFlagSource.d.ts +19 -0
- package/dist/services/features/sources/DatabaseFeatureFlagSource.d.ts.map +1 -0
- package/dist/services/features/sources/FeatureFlagSource.d.ts +30 -0
- package/dist/services/features/sources/FeatureFlagSource.d.ts.map +1 -0
- package/dist/services/features/sources/StaticFeatureFlagSource.d.ts +24 -0
- package/dist/services/features/sources/StaticFeatureFlagSource.d.ts.map +1 -0
- package/dist/services/features/types.d.ts +63 -0
- package/dist/services/features/types.d.ts.map +1 -0
- package/dist/services/index.d.ts +18 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +8 -8
- package/dist/services/index.js.map +8 -4
- package/dist/services/queue/QueueManager.d.ts +31 -0
- package/dist/services/queue/QueueManager.d.ts.map +1 -1
- package/dist/services/router/ViewRouteDispatcher.d.ts +8 -0
- package/dist/services/router/ViewRouteDispatcher.d.ts.map +1 -1
- package/dist/services/router/createFlatViewRoutes.d.ts +14 -0
- package/dist/services/router/createFlatViewRoutes.d.ts.map +1 -1
- package/dist/services/router/streamQueryInjection.d.ts.map +1 -1
- package/dist/support/index.js +2 -2
- package/dist/support/index.js.map +1 -1
- package/dist/testing/Page.d.ts +12 -0
- package/dist/testing/Page.d.ts.map +1 -1
- package/dist/testing/index.d.ts +24 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +7 -3
- package/dist/testing/index.js.map +1 -1
- package/ide/typescript-plugin/package.json +5 -0
- package/package.json +4 -2
- package/dist/chunk-4t80js0n.js +0 -33
- package/dist/chunk-4t80js0n.js.map +0 -18
- package/dist/chunk-98a576s9.js +0 -5
- package/dist/chunk-98a576s9.js.map +0 -30
- package/dist/chunk-b50zmz3t.js +0 -5
- package/dist/chunk-cv9w5cmb.js +0 -6
- package/dist/chunk-f9mfw82d.js +0 -5
- package/dist/chunk-f9mfw82d.js.map +0 -12
- package/dist/chunk-kry5vwam.js +0 -9
- package/dist/chunk-tmnhkphv.js +0 -19
- package/dist/chunk-vkngcrzq.js +0 -4
- /package/dist/{chunk-62723jyy.js.map → chunk-k0fvsyeh.js.map} +0 -0
- /package/dist/{chunk-c75mymmq.js.map → chunk-mkfpnymy.js.map} +0 -0
- /package/dist/{chunk-02gdzs5t.js.map → chunk-yf7vz71n.js.map} +0 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { FeatureContext } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Decides a feature for one context, ahead of the percentage rollout.
|
|
4
|
+
*
|
|
5
|
+
* Return `true` or `false` to answer outright. Return nothing — `undefined` —
|
|
6
|
+
* to abstain, which falls through to `rollout`. The three-way return is what
|
|
7
|
+
* lets one function express "always on for staff, always off for free plans,
|
|
8
|
+
* everybody else takes their chances" without a second mechanism.
|
|
9
|
+
*
|
|
10
|
+
* Synchronous on purpose. This runs once per feature per request inside the
|
|
11
|
+
* render path, and an `async` signature is an invitation to put a query there —
|
|
12
|
+
* at which point every page load pays for every declared feature. Anything it
|
|
13
|
+
* needs should already be on the context: `user` is the resolved session user,
|
|
14
|
+
* and `attributes` is whatever `app/config/features.ts` puts there.
|
|
15
|
+
*/
|
|
16
|
+
export type FeatureAttribution = (ctx: FeatureContext) => boolean | undefined | void;
|
|
17
|
+
export interface FeatureOptions {
|
|
18
|
+
/** Free text for humans — an admin list, a CLI, a code reader. */
|
|
19
|
+
describe?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Percentage of subjects the feature is on for, `0`–`100`.
|
|
22
|
+
*
|
|
23
|
+
* Applied only when `when` abstains. Omitting it means "everyone", which is
|
|
24
|
+
* the common case: most features are shipped dark and then turned on for all
|
|
25
|
+
* traffic at once.
|
|
26
|
+
*
|
|
27
|
+
* The assignment is a pure function of the subject, so it is stable without
|
|
28
|
+
* being stored anywhere, and raising the number only ever adds subjects. See
|
|
29
|
+
* `bucket.ts`.
|
|
30
|
+
*/
|
|
31
|
+
rollout?: number;
|
|
32
|
+
/** Targeting, evaluated before `rollout`. */
|
|
33
|
+
when?: FeatureAttribution;
|
|
34
|
+
/**
|
|
35
|
+
* Keeps the feature out of the SSR payload while still evaluating it on the
|
|
36
|
+
* server.
|
|
37
|
+
*
|
|
38
|
+
* Feature *keys* are public: every client-visible key is embedded in the HTML
|
|
39
|
+
* of every page, so a key named after an unannounced product announces it.
|
|
40
|
+
* This is the answer whenever the existence of the feature is the secret.
|
|
41
|
+
*/
|
|
42
|
+
serverOnly?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Overrides the bucketing salt, which is the feature's own key by default.
|
|
45
|
+
*
|
|
46
|
+
* Two reasons to set it. Changing it deliberately re-randomises who is in the
|
|
47
|
+
* rollout — the way to start a second experiment on the same surface without
|
|
48
|
+
* reusing the first one's cohort. And sharing it between two features holds
|
|
49
|
+
* their populations together, so a rollout split across a client and a server
|
|
50
|
+
* feature lands on the same subjects.
|
|
51
|
+
*/
|
|
52
|
+
salt?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* One declared feature.
|
|
56
|
+
*
|
|
57
|
+
* The declaration owns the key, the targeting and the rollout. The database owns
|
|
58
|
+
* one thing only — whether the feature is switched on at all — which is what
|
|
59
|
+
* makes shipping a feature a deploy and turning it on an `UPDATE`.
|
|
60
|
+
*/
|
|
61
|
+
export declare class Feature<ServerOnly extends boolean = boolean> {
|
|
62
|
+
readonly describe?: string;
|
|
63
|
+
readonly rollout?: number;
|
|
64
|
+
readonly when?: FeatureAttribution;
|
|
65
|
+
/**
|
|
66
|
+
* Carried in the type as well as the value, so `CreateFeatures` can tell a
|
|
67
|
+
* server-only declaration from a client-visible one and `useFeature` can
|
|
68
|
+
* reject the keys that never reach the browser.
|
|
69
|
+
*/
|
|
70
|
+
readonly serverOnly: ServerOnly;
|
|
71
|
+
readonly salt?: string;
|
|
72
|
+
constructor(options?: FeatureOptions);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Declares a feature.
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* // app/features/index.ts
|
|
79
|
+
* import { defineFeature } from "gemi/services";
|
|
80
|
+
*
|
|
81
|
+
* export default {
|
|
82
|
+
* // On for everyone, once switched on in the database.
|
|
83
|
+
* "new-nav": defineFeature(),
|
|
84
|
+
*
|
|
85
|
+
* // A deterministic 20% of subjects.
|
|
86
|
+
* "new-checkout": defineFeature({
|
|
87
|
+
* describe: "Rebuilt checkout flow",
|
|
88
|
+
* rollout: 20,
|
|
89
|
+
* }),
|
|
90
|
+
*
|
|
91
|
+
* // Targeting lives next to the declaration.
|
|
92
|
+
* "pricing-redesign": defineFeature({
|
|
93
|
+
* rollout: 50,
|
|
94
|
+
* when: (ctx) => {
|
|
95
|
+
* if (ctx.user?.email.endsWith("@acme.com")) return true;
|
|
96
|
+
* if (ctx.user?.plan === "free") return false;
|
|
97
|
+
* // abstain -> fall through to `rollout`
|
|
98
|
+
* },
|
|
99
|
+
* }),
|
|
100
|
+
* };
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* The default export of `app/features/index.ts` is a plain object, and its keys
|
|
104
|
+
* are the feature keys — no nesting, no prefix joining. That is deliberate: the
|
|
105
|
+
* key you look up is the key that appears literally in the source, so answering
|
|
106
|
+
* "is this feature still referenced?" — the one chore every feature eventually
|
|
107
|
+
* needs — stays a grep.
|
|
108
|
+
*/
|
|
109
|
+
export declare function defineFeature(options: FeatureOptions & {
|
|
110
|
+
serverOnly: true;
|
|
111
|
+
}): Feature<true>;
|
|
112
|
+
export declare function defineFeature(options?: FeatureOptions): Feature<false>;
|
|
113
|
+
/** The shape of `app/features/index.ts`'s default export. */
|
|
114
|
+
export type FeatureRegistry = Record<string, Feature>;
|
|
115
|
+
/**
|
|
116
|
+
* What a `serverOnly: true` feature occupies in `Features`.
|
|
117
|
+
*
|
|
118
|
+
* Deliberately not `boolean`. The key still has to be a `keyof Features` — the
|
|
119
|
+
* `Features` facade evaluates it server-side, which is the entire point of the
|
|
120
|
+
* option — but `useFeature` must reject it, because `forClient()` omits those
|
|
121
|
+
* keys from the payload and a client read would be `false` forever with no
|
|
122
|
+
* indication why. Being a distinct type is what lets `ClientFeatureKey` filter
|
|
123
|
+
* the one set out of the other without a second augmentation in `gemi.d.ts`.
|
|
124
|
+
*/
|
|
125
|
+
export interface ServerOnlyFeature {
|
|
126
|
+
readonly __gemiServerOnly: true;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The map a registry describes, consumed through module augmentation so
|
|
130
|
+
* `useFeature` and the `Features` facade are typed against the application's own
|
|
131
|
+
* keys:
|
|
132
|
+
*
|
|
133
|
+
* ```ts
|
|
134
|
+
* declare module "gemi/client" {
|
|
135
|
+
* export interface Features extends CreateFeatures<typeof AppFeatures> {}
|
|
136
|
+
* }
|
|
137
|
+
* ```
|
|
138
|
+
*
|
|
139
|
+
* Key extraction and nothing else — no tree to walk — except for the one bit
|
|
140
|
+
* that has to survive: whether the feature reaches the browser at all.
|
|
141
|
+
*/
|
|
142
|
+
export type CreateFeatures<T extends FeatureRegistry> = {
|
|
143
|
+
[K in keyof T]: T[K] extends Feature<true> ? ServerOnlyFeature : boolean;
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=defineFeature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defineFeature.d.ts","sourceRoot":"","sources":["../../../services/features/defineFeature.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;AAErF,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAE1B;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,qBAAa,OAAO,CAAC,UAAU,SAAS,OAAO,GAAG,OAAO;IACvD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEX,OAAO,GAAE,cAAmB;CAoBzC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG;IAAE,UAAU,EAAE,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7F,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;AAKxE,6DAA6D;AAC7D,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,gBAAgB,EAAE,IAAI,CAAC;CACjC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,eAAe,IAAI;KACrD,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,OAAO,CAAC,IAAI,CAAC,GAAG,iBAAiB,GAAG,OAAO;CACzE,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Feature } from "./defineFeature";
|
|
2
|
+
import type { FeatureContext, FeatureEvaluation } from "./types";
|
|
3
|
+
export interface EvaluateOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Whether the database says this feature is switched on. `undefined` means
|
|
6
|
+
* there is no row, which is the state a freshly deployed feature is in.
|
|
7
|
+
*/
|
|
8
|
+
active: boolean | undefined;
|
|
9
|
+
/** The store has never loaded successfully. */
|
|
10
|
+
unavailable?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Per-request memo of bucket computations, so a feature read in three
|
|
13
|
+
* components hashes once.
|
|
14
|
+
*/
|
|
15
|
+
buckets?: Map<string, number>;
|
|
16
|
+
/** Where a throwing `when` is reported. */
|
|
17
|
+
warn?: (message: string) => void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolves one feature against one context. Pure: no I/O, no container, and no
|
|
21
|
+
* clock of its own — `ctx.now` is the clock.
|
|
22
|
+
*
|
|
23
|
+
* ## Order
|
|
24
|
+
*
|
|
25
|
+
* 1. The store never loaded → **off**.
|
|
26
|
+
* 2. No row, or `active === false` → **off**. `when` and `rollout` are not
|
|
27
|
+
* consulted.
|
|
28
|
+
* 3. `when(ctx)` returned a boolean → that.
|
|
29
|
+
* 4. No `rollout` → **on**, crawlers included. There is nothing to sample, so
|
|
30
|
+
* every visit already resolves the same way.
|
|
31
|
+
* 5. A crawler, on a feature that *has* a rollout → **off**.
|
|
32
|
+
* 6. Inside the rollout bucket → on, otherwise off.
|
|
33
|
+
*
|
|
34
|
+
* ## Why an unreachable database means off
|
|
35
|
+
*
|
|
36
|
+
* The store keeps its last good snapshot across a failed refresh, so this only
|
|
37
|
+
* applies to a cold process that has never loaded — a deploy landing while the
|
|
38
|
+
* database is down. Answering "on" there would turn features on at the moment
|
|
39
|
+
* the operator has the least ability to turn them off again, which is the wrong
|
|
40
|
+
* direction to fail in. Answering "off" degrades to the behaviour of the release
|
|
41
|
+
* before the feature existed.
|
|
42
|
+
*
|
|
43
|
+
* ## Why `active` short-circuits
|
|
44
|
+
*
|
|
45
|
+
* It is the kill switch, and a kill switch that targeting could defeat is not
|
|
46
|
+
* one. Turning a feature off during an incident is a single column an on-call
|
|
47
|
+
* engineer flips, and it has to be true that nothing in application code can
|
|
48
|
+
* override it — including a `when` somebody wrote last month and forgot.
|
|
49
|
+
*
|
|
50
|
+
* ## Why `when` outranks `rollout`
|
|
51
|
+
*
|
|
52
|
+
* A rollout is a statement about strangers; `when` is a statement about someone
|
|
53
|
+
* you can name. Staff overrides and plan-level exclusions have to beat the dice,
|
|
54
|
+
* or they are not overrides. Abstaining — returning nothing — is how a `when`
|
|
55
|
+
* says it has no opinion about this subject and the dice should decide.
|
|
56
|
+
*/
|
|
57
|
+
export declare function evaluateFeature(key: string, feature: Feature, ctx: FeatureContext, options: EvaluateOptions): FeatureEvaluation;
|
|
58
|
+
/**
|
|
59
|
+
* The subject a rollout buckets on: the signed-in user, else the `session_id`
|
|
60
|
+
* cookie.
|
|
61
|
+
*
|
|
62
|
+
* Preferring the user id is what makes an assignment follow someone across
|
|
63
|
+
* devices, and it is why signing up can move a visitor from one side of a
|
|
64
|
+
* rollout to the other — there is no id that is both stable per person and
|
|
65
|
+
* known before they have an account. The trade is worth it in that direction;
|
|
66
|
+
* the reverse would give every logged-in user a different answer per browser.
|
|
67
|
+
*
|
|
68
|
+
* The empty string is the honest floor. Outside a request — a job, a cron tick —
|
|
69
|
+
* there is no subject at all, and every context then shares one bucket. A random
|
|
70
|
+
* value would be worse, not better: it would give the same subject a different
|
|
71
|
+
* answer on every call, which is the one thing bucketing exists to prevent.
|
|
72
|
+
*/
|
|
73
|
+
export declare function subjectFor(ctx: FeatureContext): string;
|
|
74
|
+
//# sourceMappingURL=evaluate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../../services/features/evaluate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjE,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,+CAA+C;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,2CAA2C;IAC3C,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,eAAe,GACvB,iBAAiB,CA8CnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAItD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FeatureFlagSource } from "./FeatureFlagSource";
|
|
2
|
+
/**
|
|
3
|
+
* Reads the application's `FeatureFlag` table — one row per feature, carrying
|
|
4
|
+
* one meaningful column.
|
|
5
|
+
*
|
|
6
|
+
* The model is resolved from the ORM registry **by name, at call time**, the way
|
|
7
|
+
* `auth/UserProvider` resolves `User`. The framework cannot import a class the
|
|
8
|
+
* application generates, and resolving lazily also means constructing this
|
|
9
|
+
* source does not require the app's models to have been imported yet — only
|
|
10
|
+
* loading does.
|
|
11
|
+
*/
|
|
12
|
+
export declare class DatabaseFeatureFlagSource extends FeatureFlagSource {
|
|
13
|
+
readonly modelName: string;
|
|
14
|
+
constructor(modelName?: string);
|
|
15
|
+
/** Whether the application has registered the model at all. */
|
|
16
|
+
get available(): boolean;
|
|
17
|
+
load(): Promise<Record<string, unknown>[]>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=DatabaseFeatureFlagSource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DatabaseFeatureFlagSource.d.ts","sourceRoot":"","sources":["../../../../services/features/sources/DatabaseFeatureFlagSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAA4B,MAAM,qBAAqB,CAAC;AAElF;;;;;;;;;GASG;AACH,qBAAa,yBAA0B,SAAQ,iBAAiB;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM;gBAAjB,SAAS,GAAE,MAAsB;IAItD,+DAA+D;IAC/D,IAAI,SAAS,IAAI,OAAO,CAEvB;IAEK,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CAajD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the on/off switches come from.
|
|
3
|
+
*
|
|
4
|
+
* A seam rather than a hardcoded query for two reasons that already exist: the
|
|
5
|
+
* database source cannot run in a unit test without a schema and a connection,
|
|
6
|
+
* and an application that outgrows a table — a control plane, a config service —
|
|
7
|
+
* should not have to fork the evaluator to move.
|
|
8
|
+
*
|
|
9
|
+
* `load()` returns **raw rows**, not booleans. A source fetches; the store
|
|
10
|
+
* interprets, because the store is the half that knows which keys are declared.
|
|
11
|
+
*/
|
|
12
|
+
export declare abstract class FeatureFlagSource {
|
|
13
|
+
/**
|
|
14
|
+
* Every row.
|
|
15
|
+
*
|
|
16
|
+
* Returning `[]` means "nothing is switched on", which is a normal state — it
|
|
17
|
+
* is what a fresh database looks like, and every feature is correctly off.
|
|
18
|
+
* **Throwing** means "I could not tell you", which is different: the store
|
|
19
|
+
* keeps serving whatever it last had rather than treating an outage as a mass
|
|
20
|
+
* switch-off.
|
|
21
|
+
*/
|
|
22
|
+
abstract load(): Promise<Record<string, unknown>[]>;
|
|
23
|
+
}
|
|
24
|
+
/** Raised when the application never added the model this source reads. */
|
|
25
|
+
export declare class FeatureModelMissingError extends Error {
|
|
26
|
+
readonly modelName: string;
|
|
27
|
+
readonly kind = "FeatureModelMissing";
|
|
28
|
+
constructor(modelName: string);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=FeatureFlagSource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FeatureFlagSource.d.ts","sourceRoot":"","sources":["../../../../services/features/sources/FeatureFlagSource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,8BAAsB,iBAAiB;IACrC;;;;;;;;OAQG;IACH,QAAQ,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CACpD;AAED,2EAA2E;AAC3E,qBAAa,wBAAyB,SAAQ,KAAK;IAGrC,QAAQ,CAAC,SAAS,EAAE,MAAM;IAFtC,QAAQ,CAAC,IAAI,yBAAyB;gBAEjB,SAAS,EAAE,MAAM;CAKvC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { FeatureFlagSource } from "./FeatureFlagSource";
|
|
2
|
+
/**
|
|
3
|
+
* Switches from a plain object instead of a database.
|
|
4
|
+
*
|
|
5
|
+
* This is how a test turns a feature on:
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* defineFeaturesConfig({
|
|
9
|
+
* source: new StaticFeatureFlagSource({ "new-checkout": true }),
|
|
10
|
+
* })
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Deliberately **not** a stub that returns canned answers: these rows go through
|
|
14
|
+
* the same store and the same evaluator the database source feeds. A test that
|
|
15
|
+
* pins `"new-checkout": true` therefore still exercises the feature's own `when`
|
|
16
|
+
* and `rollout`, which is the part worth testing — pinning the final answer
|
|
17
|
+
* would assert about a code path production never runs.
|
|
18
|
+
*/
|
|
19
|
+
export declare class StaticFeatureFlagSource extends FeatureFlagSource {
|
|
20
|
+
private readonly active;
|
|
21
|
+
constructor(active?: Record<string, boolean>);
|
|
22
|
+
load(): Promise<Record<string, unknown>[]>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=StaticFeatureFlagSource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StaticFeatureFlagSource.d.ts","sourceRoot":"","sources":["../../../../services/features/sources/StaticFeatureFlagSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,uBAAwB,SAAQ,iBAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAI3D,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CAMjD"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a feature is evaluated against.
|
|
3
|
+
*
|
|
4
|
+
* Assembled once per request and memoised on the request store, so declaring a
|
|
5
|
+
* hundred features costs one context, not a hundred.
|
|
6
|
+
*/
|
|
7
|
+
export interface FeatureContext {
|
|
8
|
+
/** The session user, or `null`. Never throws for an anonymous visitor. */
|
|
9
|
+
user: Record<string, any> | null;
|
|
10
|
+
/** Application-supplied extras from `app/config/features.ts`. */
|
|
11
|
+
attributes: Record<string, unknown>;
|
|
12
|
+
request: {
|
|
13
|
+
path: string | null;
|
|
14
|
+
routePath: string | null;
|
|
15
|
+
locale: string | null;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The stable anonymous subject — the `session_id` cookie.
|
|
19
|
+
*
|
|
20
|
+
* This is what makes a percentage rollout hold still for a logged-out
|
|
21
|
+
* visitor. It is minted at the top of every view request rather than at the
|
|
22
|
+
* end of one, so the id used to bucket is the id the browser is about to be
|
|
23
|
+
* given.
|
|
24
|
+
*/
|
|
25
|
+
anonymousId: string | null;
|
|
26
|
+
/**
|
|
27
|
+
* A crawler sent this request.
|
|
28
|
+
*
|
|
29
|
+
* Bots discard cookies, so every crawl of the same URL would otherwise mint a
|
|
30
|
+
* fresh `session_id`, land in a fresh bucket, and index a different variant
|
|
31
|
+
* than the last crawl. They are pinned off instead.
|
|
32
|
+
*/
|
|
33
|
+
isBot: boolean;
|
|
34
|
+
now: Date;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Why a feature resolved the way it did. Server-side diagnostics — never
|
|
38
|
+
* serialized, because "you are in the rollout" is a fact about the viewer.
|
|
39
|
+
*/
|
|
40
|
+
export type EvaluationReason =
|
|
41
|
+
/** No such key in `app/features`. */
|
|
42
|
+
"undeclared"
|
|
43
|
+
/** No row, or the row says off. The kill switch. */
|
|
44
|
+
| "inactive"
|
|
45
|
+
/** `when` returned a definite answer. */
|
|
46
|
+
| "attributed"
|
|
47
|
+
/** Inside the rollout bucket. */
|
|
48
|
+
| "rollout"
|
|
49
|
+
/** Outside the rollout bucket. */
|
|
50
|
+
| "excluded"
|
|
51
|
+
/** A crawler; rollouts are pinned off. */
|
|
52
|
+
| "bot"
|
|
53
|
+
/** Switched on with no `when` opinion and no `rollout`. */
|
|
54
|
+
| "on"
|
|
55
|
+
/** `when` threw. Treated as off. */
|
|
56
|
+
| "error"
|
|
57
|
+
/** The store has never loaded, so nothing is known. Fails closed. */
|
|
58
|
+
| "unavailable";
|
|
59
|
+
export interface FeatureEvaluation {
|
|
60
|
+
value: boolean;
|
|
61
|
+
reason: EvaluationReason;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../services/features/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACjC,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC;IACF;;;;;;;OAOG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;;;;;OAMG;IACH,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,IAAI,CAAC;CACX;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB;AAC1B,qCAAqC;AACnC,YAAY;AACd,oDAAoD;GAClD,UAAU;AACZ,yCAAyC;GACvC,YAAY;AACd,iCAAiC;GAC/B,SAAS;AACX,kCAAkC;GAChC,UAAU;AACZ,0CAA0C;GACxC,KAAK;AACP,2DAA2D;GACzD,IAAI;AACN,oCAAoC;GAClC,OAAO;AACT,qEAAqE;GACnE,aAAa,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,gBAAgB,CAAC;CAC1B"}
|
package/dist/services/index.d.ts
CHANGED
|
@@ -31,6 +31,10 @@ export type { LogEntry } from "./logging/types";
|
|
|
31
31
|
export { QueueServiceProvider } from "./queue/QueueServiceProvider";
|
|
32
32
|
export { QueueManager } from "./queue/QueueManager";
|
|
33
33
|
export { Job } from "./queue/Job";
|
|
34
|
+
export { EventServiceProvider } from "./events/EventServiceProvider";
|
|
35
|
+
export { EventManager } from "./events/EventManager";
|
|
36
|
+
export { Event, type EventClass } from "./events/Event";
|
|
37
|
+
export { Listener, type ListenerClass } from "./events/Listener";
|
|
34
38
|
export { ImageServiceProvider } from "./image-optimization/ImageServiceProvider";
|
|
35
39
|
export { ImageManager } from "./image-optimization/ImageManager";
|
|
36
40
|
export type { FitEnum, ResizeParameters, } from "./image-optimization/drivers/types";
|
|
@@ -54,9 +58,20 @@ export { Command, CommandFailed } from "../console/Command";
|
|
|
54
58
|
export type { ArgSpec, OptionSpec, CommandArgument, CommandOption, CommandClass, CommandResult, } from "../console/Command";
|
|
55
59
|
export type { CommandContext } from "../console/context";
|
|
56
60
|
export { CommandRegistry } from "../console/CommandRegistry";
|
|
57
|
-
export { discoverJobs, discoverCronJobs, discoverCommands } from "./discovery";
|
|
61
|
+
export { discoverJobs, discoverCronJobs, discoverCommands, discoverListeners, } from "./discovery";
|
|
58
62
|
export { RedisServiceProvider } from "./redis/RedisServiceProvider";
|
|
59
63
|
export { RedisManager } from "./redis/RedisManager";
|
|
64
|
+
export { defineFeature, Feature, type CreateFeatures, type FeatureAttribution, type FeatureOptions, type FeatureRegistry, type ServerOnlyFeature, } from "./features/defineFeature";
|
|
65
|
+
export { FeaturesServiceProvider } from "./features/FeaturesServiceProvider";
|
|
66
|
+
export { FeatureManager, FeatureScope } from "./features/FeatureManager";
|
|
67
|
+
export { FeatureFlagStore, type FlagSnapshot } from "./features/FeatureFlagStore";
|
|
68
|
+
export { FeatureFlagSource, FeatureModelMissingError } from "./features/sources/FeatureFlagSource";
|
|
69
|
+
export { DatabaseFeatureFlagSource } from "./features/sources/DatabaseFeatureFlagSource";
|
|
70
|
+
export { StaticFeatureFlagSource } from "./features/sources/StaticFeatureFlagSource";
|
|
71
|
+
export { evaluateFeature, subjectFor } from "./features/evaluate";
|
|
72
|
+
export { bucketKey, bucketOf, inRollout } from "./features/bucket";
|
|
73
|
+
export type { FeatureSubject } from "./features/context";
|
|
74
|
+
export type { EvaluationReason, FeatureContext, FeatureEvaluation, } from "./features/types";
|
|
60
75
|
export { defineFilesystemConfig, filesystemConfigDefaults, type FilesystemConfig, } from "./file-storage/config";
|
|
61
76
|
export { defineRateLimiterConfig, rateLimiterConfigDefaults, type RateLimiterConfig, } from "./rate-limiter/config";
|
|
62
77
|
export { defineMailConfig, mailConfigDefaults, type MailConfig, } from "./email/config";
|
|
@@ -64,10 +79,12 @@ export { defineBroadcastConfig, broadcastConfigDefaults, type BroadcastConfig, }
|
|
|
64
79
|
export { defineRouteConfig, apiRouteConfigDefaults, viewRouteConfigDefaults, type RouteConfig, type ApiRouteConfig, type ViewRouteConfig, } from "./router/config";
|
|
65
80
|
export { defineLogConfig, logConfigDefaults, type LogConfig, } from "./logging/config";
|
|
66
81
|
export { defineQueueConfig, queueConfigDefaults, type QueueConfig, } from "./queue/config";
|
|
82
|
+
export { defineEventConfig, eventConfigDefaults, type EventConfig, } from "./events/config";
|
|
67
83
|
export { defineImageConfig, imageConfigDefaults, type ImageConfig, } from "./image-optimization/config";
|
|
68
84
|
export { defineScheduleConfig, scheduleConfigDefaults, type ScheduleConfig, } from "./cron/config";
|
|
69
85
|
export { defineCommandConfig, commandConfigDefaults, type CommandConfig, } from "../console/config";
|
|
70
86
|
export { defineRedisConfig, redisConfigDefaults, type RedisConfig, } from "./redis/config";
|
|
87
|
+
export { defineFeaturesConfig, featuresConfigDefaults, type FeaturesConfig, } from "./features/config";
|
|
71
88
|
export { defineAuthConfig, authConfigDefaults, type AuthConfig, } from "../auth/config";
|
|
72
89
|
export { defineTranslationConfig, translationConfigDefaults, type TranslationConfig, } from "../i18n/config";
|
|
73
90
|
export { defineMiddlewareConfig, middlewareConfigDefaults, type MiddlewareConfig, } from "../http/middleware-config";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../services/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,GAC3B,MAAM,wCAAwC,CAAC;AAChD,YAAY,EACV,SAAS,EACT,YAAY,EACZ,aAAa,EACb,cAAc,EACd,UAAU,GACX,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAE7E,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAG7E,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,GAChC,MAAM,kDAAkD,CAAC;AAC1D,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAC7E,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC3E,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAG7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,YAAY,EACV,aAAa,EACb,kBAAkB,GACnB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../services/index.ts"],"names":[],"mappings":"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"}
|