@toyz/loom-flags 0.1.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/events.d.ts +15 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +20 -0
- package/dist/events.js.map +1 -0
- package/dist/flag-component.d.ts +24 -0
- package/dist/flag-component.d.ts.map +1 -0
- package/dist/flag-component.js +122 -0
- package/dist/flag-component.js.map +1 -0
- package/dist/flag.d.ts +28 -0
- package/dist/flag.d.ts.map +1 -0
- package/dist/flag.js +81 -0
- package/dist/flag.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/provider.d.ts +29 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +33 -0
- package/dist/provider.js.map +1 -0
- package/dist/testing.d.ts +44 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +75 -0
- package/dist/testing.js.map +1 -0
- package/package.json +52 -0
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomFlags — FlagChanged event
|
|
3
|
+
*
|
|
4
|
+
* Dispatched on the Loom bus when a flag's state changes.
|
|
5
|
+
* Consumed by @flag decorators and <loom-flag> components
|
|
6
|
+
* to reactively update the UI.
|
|
7
|
+
*/
|
|
8
|
+
import { LoomEvent } from "@toyz/loom";
|
|
9
|
+
export declare class FlagChanged extends LoomEvent {
|
|
10
|
+
readonly flag: string;
|
|
11
|
+
readonly enabled: boolean;
|
|
12
|
+
readonly variant?: string | undefined;
|
|
13
|
+
constructor(flag: string, enabled: boolean, variant?: string | undefined);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,qBAAa,WAAY,SAAQ,SAAS;aAEtB,IAAI,EAAE,MAAM;aACZ,OAAO,EAAE,OAAO;aAChB,OAAO,CAAC,EAAE,MAAM;gBAFhB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,MAAM,YAAA;CAInC"}
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomFlags — FlagChanged event
|
|
3
|
+
*
|
|
4
|
+
* Dispatched on the Loom bus when a flag's state changes.
|
|
5
|
+
* Consumed by @flag decorators and <loom-flag> components
|
|
6
|
+
* to reactively update the UI.
|
|
7
|
+
*/
|
|
8
|
+
import { LoomEvent } from "@toyz/loom";
|
|
9
|
+
export class FlagChanged extends LoomEvent {
|
|
10
|
+
flag;
|
|
11
|
+
enabled;
|
|
12
|
+
variant;
|
|
13
|
+
constructor(flag, enabled, variant) {
|
|
14
|
+
super();
|
|
15
|
+
this.flag = flag;
|
|
16
|
+
this.enabled = enabled;
|
|
17
|
+
this.variant = variant;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,OAAO,WAAY,SAAQ,SAAS;IAEtB;IACA;IACA;IAHlB,YACkB,IAAY,EACZ,OAAgB,EAChB,OAAgB;QAEhC,KAAK,EAAE,CAAC;QAJQ,SAAI,GAAJ,IAAI,CAAQ;QACZ,YAAO,GAAP,OAAO,CAAS;QAChB,YAAO,GAAP,OAAO,CAAS;IAGlC,CAAC;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomFlags — <loom-flag> component
|
|
3
|
+
*
|
|
4
|
+
* Conditional rendering via named slots:
|
|
5
|
+
*
|
|
6
|
+
* ```tsx
|
|
7
|
+
* <loom-flag name="beta-feature">
|
|
8
|
+
* <new-widget slot="enabled" />
|
|
9
|
+
* <span slot="disabled">Coming soon…</span>
|
|
10
|
+
* </loom-flag>
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Listens for FlagChanged bus events to swap slots reactively.
|
|
14
|
+
*/
|
|
15
|
+
import { LoomElement } from "@toyz/loom";
|
|
16
|
+
declare class LoomFlagElement extends LoomElement {
|
|
17
|
+
accessor name: string;
|
|
18
|
+
accessor enabled: boolean;
|
|
19
|
+
private _init;
|
|
20
|
+
private _onFlagChanged;
|
|
21
|
+
update(): import("@toyz/loom/jsx-runtime").JSX.Element;
|
|
22
|
+
}
|
|
23
|
+
export { LoomFlagElement };
|
|
24
|
+
//# sourceMappingURL=flag-component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag-component.d.ts","sourceRoot":"","sources":["../src/flag-component.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,WAAW,EAA0D,MAAM,YAAY,CAAC;AAQjG,cAEM,eAAgB,SAAQ,WAAW;IACjC,QAAQ,CAAC,IAAI,SAAM;IACf,QAAQ,CAAC,OAAO,UAAS;IAGnC,OAAO,CAAC,KAAK;IAUb,OAAO,CAAC,cAAc;IAMtB,MAAM;CAKP;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
2
|
+
var useValue = arguments.length > 2;
|
|
3
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
4
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
5
|
+
}
|
|
6
|
+
return useValue ? value : void 0;
|
|
7
|
+
};
|
|
8
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
9
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
10
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
11
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
12
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
13
|
+
var _, done = false;
|
|
14
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
15
|
+
var context = {};
|
|
16
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
17
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
18
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
19
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
20
|
+
if (kind === "accessor") {
|
|
21
|
+
if (result === void 0) continue;
|
|
22
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
23
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
24
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
25
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
26
|
+
}
|
|
27
|
+
else if (_ = accept(result)) {
|
|
28
|
+
if (kind === "field") initializers.unshift(_);
|
|
29
|
+
else descriptor[key] = _;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
33
|
+
done = true;
|
|
34
|
+
};
|
|
35
|
+
import { jsx as _jsx } from "@toyz/loom/jsx-runtime";
|
|
36
|
+
/**
|
|
37
|
+
* LoomFlags — <loom-flag> component
|
|
38
|
+
*
|
|
39
|
+
* Conditional rendering via named slots:
|
|
40
|
+
*
|
|
41
|
+
* ```tsx
|
|
42
|
+
* <loom-flag name="beta-feature">
|
|
43
|
+
* <new-widget slot="enabled" />
|
|
44
|
+
* <span slot="disabled">Coming soon…</span>
|
|
45
|
+
* </loom-flag>
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* Listens for FlagChanged bus events to swap slots reactively.
|
|
49
|
+
*/
|
|
50
|
+
import { LoomElement, component, prop, css, styles, reactive, app, on, mount } from "@toyz/loom";
|
|
51
|
+
import { FlagProvider } from "./provider";
|
|
52
|
+
import { FlagChanged } from "./events";
|
|
53
|
+
const flagStyles = css `
|
|
54
|
+
:host { display: contents; }
|
|
55
|
+
`;
|
|
56
|
+
let LoomFlagElement = (() => {
|
|
57
|
+
let _classDecorators = [component("loom-flag"), styles(flagStyles)];
|
|
58
|
+
let _classDescriptor;
|
|
59
|
+
let _classExtraInitializers = [];
|
|
60
|
+
let _classThis;
|
|
61
|
+
let _classSuper = LoomElement;
|
|
62
|
+
let _instanceExtraInitializers = [];
|
|
63
|
+
let _name_decorators;
|
|
64
|
+
let _name_initializers = [];
|
|
65
|
+
let _name_extraInitializers = [];
|
|
66
|
+
let _enabled_decorators;
|
|
67
|
+
let _enabled_initializers = [];
|
|
68
|
+
let _enabled_extraInitializers = [];
|
|
69
|
+
let __init_decorators;
|
|
70
|
+
let __onFlagChanged_decorators;
|
|
71
|
+
var LoomFlagElement = class extends _classSuper {
|
|
72
|
+
static { _classThis = this; }
|
|
73
|
+
static {
|
|
74
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
75
|
+
_name_decorators = [prop];
|
|
76
|
+
_enabled_decorators = [reactive];
|
|
77
|
+
__init_decorators = [mount];
|
|
78
|
+
__onFlagChanged_decorators = [on(FlagChanged)];
|
|
79
|
+
__esDecorate(this, null, _name_decorators, { kind: "accessor", name: "name", static: false, private: false, access: { has: obj => "name" in obj, get: obj => obj.name, set: (obj, value) => { obj.name = value; } }, metadata: _metadata }, _name_initializers, _name_extraInitializers);
|
|
80
|
+
__esDecorate(this, null, _enabled_decorators, { kind: "accessor", name: "enabled", static: false, private: false, access: { has: obj => "enabled" in obj, get: obj => obj.enabled, set: (obj, value) => { obj.enabled = value; } }, metadata: _metadata }, _enabled_initializers, _enabled_extraInitializers);
|
|
81
|
+
__esDecorate(this, null, __init_decorators, { kind: "method", name: "_init", static: false, private: false, access: { has: obj => "_init" in obj, get: obj => obj._init }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
82
|
+
__esDecorate(this, null, __onFlagChanged_decorators, { kind: "method", name: "_onFlagChanged", static: false, private: false, access: { has: obj => "_onFlagChanged" in obj, get: obj => obj._onFlagChanged }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
83
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
84
|
+
LoomFlagElement = _classThis = _classDescriptor.value;
|
|
85
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
86
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
87
|
+
}
|
|
88
|
+
#name_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _name_initializers, ""));
|
|
89
|
+
get name() { return this.#name_accessor_storage; }
|
|
90
|
+
set name(value) { this.#name_accessor_storage = value; }
|
|
91
|
+
#enabled_accessor_storage = (__runInitializers(this, _name_extraInitializers), __runInitializers(this, _enabled_initializers, false));
|
|
92
|
+
get enabled() { return this.#enabled_accessor_storage; }
|
|
93
|
+
set enabled(value) { this.#enabled_accessor_storage = value; }
|
|
94
|
+
_init() {
|
|
95
|
+
if (!this.name)
|
|
96
|
+
return;
|
|
97
|
+
try {
|
|
98
|
+
this.enabled = app.get(FlagProvider).isEnabled(this.name);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
this.enabled = false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
_onFlagChanged(event) {
|
|
105
|
+
if (event.flag === this.name) {
|
|
106
|
+
this.enabled = event.enabled;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
update() {
|
|
110
|
+
return this.enabled
|
|
111
|
+
? _jsx("slot", { name: "enabled" })
|
|
112
|
+
: _jsx("slot", { name: "disabled" });
|
|
113
|
+
}
|
|
114
|
+
constructor() {
|
|
115
|
+
super(...arguments);
|
|
116
|
+
__runInitializers(this, _enabled_extraInitializers);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
return LoomFlagElement = _classThis;
|
|
120
|
+
})();
|
|
121
|
+
export { LoomFlagElement };
|
|
122
|
+
//# sourceMappingURL=flag-component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag-component.js","sourceRoot":"","sources":["../src/flag-component.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACjG,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,UAAU,GAAG,GAAG,CAAA;;CAErB,CAAC;IAII,eAAe;4BAFpB,SAAS,CAAC,WAAW,CAAC,EACtB,MAAM,CAAC,UAAU,CAAC;;;;sBACW,WAAW;;;;;;;;;;+BAAnB,SAAQ,WAAW;;;;gCACtC,IAAI;mCACJ,QAAQ;iCAER,KAAK;0CAUL,EAAE,CAAC,WAAW,CAAC;YAbV,iKAAS,IAAI,6BAAJ,IAAI,mFAAM;YACf,0KAAS,OAAO,6BAAP,OAAO,yFAAS;YAGnC,kKAAQ,KAAK,6DAOZ;YAGD,6LAAQ,cAAc,6DAIrB;YAnBH,6KA0BC;;;YA1BK,uDAAe;;QACb,0BADF,mDAAe,8CACG,EAAE,GAAC;QAAnB,IAAS,IAAI,0CAAM;QAAnB,IAAS,IAAI,gDAAM;QACf,8HAAmB,KAAK,GAAC;QAAzB,IAAS,OAAO,6CAAS;QAAzB,IAAS,OAAO,mDAAS;QAG3B,KAAK;YACX,IAAI,CAAC,IAAI,CAAC,IAAI;gBAAE,OAAO;YACvB,IAAI,CAAC;gBACH,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5D,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACvB,CAAC;QACH,CAAC;QAGO,cAAc,CAAC,KAAkB;YACvC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC7B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;YAC/B,CAAC;QACH,CAAC;QAED,MAAM;YACJ,OAAO,IAAI,CAAC,OAAO;gBACjB,CAAC,CAAC,eAAM,IAAI,EAAC,SAAS,GAAG;gBACzB,CAAC,CAAC,eAAM,IAAI,EAAC,UAAU,GAAG,CAAC;QAC/B,CAAC;;;;;;;;AAGH,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
package/dist/flag.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomFlags — @flag decorator
|
|
3
|
+
*
|
|
4
|
+
* Raw TC39 Stage 3 decorator for feature flag gating.
|
|
5
|
+
* Dispatches on `context.kind` to support class and method targets.
|
|
6
|
+
*
|
|
7
|
+
* - **class**: injects a reactive `flagEnabled` boolean property
|
|
8
|
+
* - **method**: guards execution — no-op when flag is off
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* // Class — injects flagEnabled property
|
|
12
|
+
* @flag("new-dashboard")
|
|
13
|
+
* class Dashboard extends LoomElement { ... }
|
|
14
|
+
*
|
|
15
|
+
* // Method — no-op when flag is off
|
|
16
|
+
* @flag("beta-export")
|
|
17
|
+
* handleExport() { ... }
|
|
18
|
+
*
|
|
19
|
+
* // Dynamic context from element instance
|
|
20
|
+
* @flag("premium", el => ({ plan: el.plan }))
|
|
21
|
+
* class PremiumWidget extends LoomElement { ... }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
/** Second arg: static context or a function returning context from element */
|
|
25
|
+
type ContextArg = Record<string, any> | ((el: any) => Record<string, any>);
|
|
26
|
+
export declare function flag(name: string, context?: ContextArg): (value: any, decoratorContext: DecoratorContext) => any;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=flag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag.d.ts","sourceRoot":"","sources":["../src/flag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,8EAA8E;AAC9E,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,KAAK,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;AAQ3E,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,IAC7C,OAAO,GAAG,EAAE,kBAAkB,gBAAgB,KAAG,GAAG,CAkD7D"}
|
package/dist/flag.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomFlags — @flag decorator
|
|
3
|
+
*
|
|
4
|
+
* Raw TC39 Stage 3 decorator for feature flag gating.
|
|
5
|
+
* Dispatches on `context.kind` to support class and method targets.
|
|
6
|
+
*
|
|
7
|
+
* - **class**: injects a reactive `flagEnabled` boolean property
|
|
8
|
+
* - **method**: guards execution — no-op when flag is off
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* // Class — injects flagEnabled property
|
|
12
|
+
* @flag("new-dashboard")
|
|
13
|
+
* class Dashboard extends LoomElement { ... }
|
|
14
|
+
*
|
|
15
|
+
* // Method — no-op when flag is off
|
|
16
|
+
* @flag("beta-export")
|
|
17
|
+
* handleExport() { ... }
|
|
18
|
+
*
|
|
19
|
+
* // Dynamic context from element instance
|
|
20
|
+
* @flag("premium", el => ({ plan: el.plan }))
|
|
21
|
+
* class PremiumWidget extends LoomElement { ... }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
import { app, bus } from "@toyz/loom";
|
|
25
|
+
import { FlagProvider } from "./provider";
|
|
26
|
+
import { FlagChanged } from "./events";
|
|
27
|
+
function resolveContext(ctx, el) {
|
|
28
|
+
if (!ctx)
|
|
29
|
+
return undefined;
|
|
30
|
+
if (typeof ctx === "function")
|
|
31
|
+
return ctx(el);
|
|
32
|
+
return { ...ctx };
|
|
33
|
+
}
|
|
34
|
+
export function flag(name, context) {
|
|
35
|
+
return (value, decoratorContext) => {
|
|
36
|
+
switch (decoratorContext.kind) {
|
|
37
|
+
case "class": {
|
|
38
|
+
const ctor = value;
|
|
39
|
+
const originalConnected = ctor.prototype.connectedCallback;
|
|
40
|
+
ctor.prototype.connectedCallback = function () {
|
|
41
|
+
if (originalConnected)
|
|
42
|
+
originalConnected.call(this);
|
|
43
|
+
// Set initial flag state
|
|
44
|
+
const ctx = resolveContext(context, this);
|
|
45
|
+
this.flagEnabled = app.get(FlagProvider).isEnabled(name, ctx);
|
|
46
|
+
this.flagName = name;
|
|
47
|
+
// Listen for flag changes — re-evaluate reactively
|
|
48
|
+
const handler = (event) => {
|
|
49
|
+
if (event.flag === name) {
|
|
50
|
+
this.flagEnabled = event.enabled;
|
|
51
|
+
this.scheduleUpdate?.();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
bus.on(FlagChanged, handler);
|
|
55
|
+
// Cleanup on disconnect
|
|
56
|
+
if (this.track) {
|
|
57
|
+
this.track(() => bus.off(FlagChanged, handler));
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
case "method": {
|
|
63
|
+
const method = value;
|
|
64
|
+
const key = String(decoratorContext.name);
|
|
65
|
+
decoratorContext.addInitializer(function () {
|
|
66
|
+
const original = method;
|
|
67
|
+
const self = this;
|
|
68
|
+
this[key] = function (...args) {
|
|
69
|
+
const ctx = resolveContext(context, self);
|
|
70
|
+
if (!app.get(FlagProvider).isEnabled(name, ctx)) {
|
|
71
|
+
return; // Flag is off — no-op
|
|
72
|
+
}
|
|
73
|
+
return original.apply(self, args);
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=flag.js.map
|
package/dist/flag.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag.js","sourceRoot":"","sources":["../src/flag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAKvC,SAAS,cAAc,CAAC,GAA2B,EAAE,EAAO;IAC1D,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,IAAI,OAAO,GAAG,KAAK,UAAU;QAAE,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9C,OAAO,EAAE,GAAG,GAAG,EAAE,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,OAAoB;IACrD,OAAO,CAAC,KAAU,EAAE,gBAAkC,EAAO,EAAE;QAC7D,QAAQ,gBAAgB,CAAC,IAAI,EAAE,CAAC;YAC9B,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,IAAI,GAAG,KAAiB,CAAC;gBAC/B,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC;gBAE3D,IAAI,CAAC,SAAS,CAAC,iBAAiB,GAAG;oBACjC,IAAI,iBAAiB;wBAAE,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAEpD,yBAAyB;oBACzB,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;oBAC1C,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;oBAC9D,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;oBAErB,mDAAmD;oBACnD,MAAM,OAAO,GAAG,CAAC,KAAkB,EAAE,EAAE;wBACrC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;4BACxB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC;4BACjC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;wBAC1B,CAAC;oBACH,CAAC,CAAC;oBACF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;oBAE7B,wBAAwB;oBACxB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;wBACf,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;oBAClD,CAAC;gBACH,CAAC,CAAC;gBACF,MAAM;YACR,CAAC;YAED,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,MAAM,MAAM,GAAG,KAAiB,CAAC;gBACjC,MAAM,GAAG,GAAG,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBAE1C,gBAAgB,CAAC,cAAc,CAAC;oBAC9B,MAAM,QAAQ,GAAG,MAAM,CAAC;oBACxB,MAAM,IAAI,GAAG,IAAI,CAAC;oBACjB,IAAY,CAAC,GAAG,CAAC,GAAG,UAAU,GAAG,IAAW;wBAC3C,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;wBAC1C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;4BAChD,OAAO,CAAC,sBAAsB;wBAChC,CAAC;wBACD,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBACpC,CAAC,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @toyz/loom-flags — Feature flags for Loom
|
|
3
|
+
*
|
|
4
|
+
* Decorator-driven feature flags with real-time reactive updates.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
export { FlagProvider } from "./provider";
|
|
9
|
+
export { flag } from "./flag";
|
|
10
|
+
export { FlagChanged } from "./events";
|
|
11
|
+
export { LoomFlagElement } from "./flag-component.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @toyz/loom-flags — Feature flags for Loom
|
|
3
|
+
*
|
|
4
|
+
* Decorator-driven feature flags with real-time reactive updates.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
export { FlagProvider } from "./provider";
|
|
9
|
+
export { flag } from "./flag";
|
|
10
|
+
export { FlagChanged } from "./events";
|
|
11
|
+
export { LoomFlagElement } from "./flag-component.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomFlags — FlagProvider abstract class
|
|
3
|
+
*
|
|
4
|
+
* Base class for all flag providers. Extend this and implement
|
|
5
|
+
* isEnabled() and getVariant(). Register via DI:
|
|
6
|
+
*
|
|
7
|
+
* app.use(FlagProvider, new MyProvider());
|
|
8
|
+
*
|
|
9
|
+
* Providers can call set() to update flags at runtime — this fires
|
|
10
|
+
* FlagChanged on the Loom bus, causing all @flag decorators and
|
|
11
|
+
* <loom-flag> components to re-evaluate reactively.
|
|
12
|
+
*/
|
|
13
|
+
export declare abstract class FlagProvider {
|
|
14
|
+
/** Internal flag cache — providers maintain their own state */
|
|
15
|
+
protected flags: Map<string, boolean>;
|
|
16
|
+
protected variants: Map<string, string>;
|
|
17
|
+
/** Check if a flag is enabled */
|
|
18
|
+
abstract isEnabled(flag: string, context?: Record<string, any>): boolean;
|
|
19
|
+
/** Get a flag's variant value */
|
|
20
|
+
abstract getVariant<T = string>(flag: string, fallback: T): T;
|
|
21
|
+
/**
|
|
22
|
+
* Update a flag at runtime — fires FlagChanged on the bus.
|
|
23
|
+
* Call this from WebSocket handlers, SSE listeners, polling loops, etc.
|
|
24
|
+
*/
|
|
25
|
+
set(flag: string, enabled: boolean): void;
|
|
26
|
+
/** Update a variant at runtime — fires FlagChanged on the bus */
|
|
27
|
+
setVariant(flag: string, value: string): void;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,8BAAsB,YAAY;IAChC,+DAA+D;IAC/D,SAAS,CAAC,KAAK,uBAA8B;IAC7C,SAAS,CAAC,QAAQ,sBAA6B;IAE/C,iCAAiC;IACjC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO;IAExE,iCAAiC;IACjC,QAAQ,CAAC,UAAU,CAAC,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC;IAE7D;;;OAGG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAKzC,iEAAiE;IACjE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;CAI9C"}
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomFlags — FlagProvider abstract class
|
|
3
|
+
*
|
|
4
|
+
* Base class for all flag providers. Extend this and implement
|
|
5
|
+
* isEnabled() and getVariant(). Register via DI:
|
|
6
|
+
*
|
|
7
|
+
* app.use(FlagProvider, new MyProvider());
|
|
8
|
+
*
|
|
9
|
+
* Providers can call set() to update flags at runtime — this fires
|
|
10
|
+
* FlagChanged on the Loom bus, causing all @flag decorators and
|
|
11
|
+
* <loom-flag> components to re-evaluate reactively.
|
|
12
|
+
*/
|
|
13
|
+
import { bus } from "@toyz/loom";
|
|
14
|
+
import { FlagChanged } from "./events";
|
|
15
|
+
export class FlagProvider {
|
|
16
|
+
/** Internal flag cache — providers maintain their own state */
|
|
17
|
+
flags = new Map();
|
|
18
|
+
variants = new Map();
|
|
19
|
+
/**
|
|
20
|
+
* Update a flag at runtime — fires FlagChanged on the bus.
|
|
21
|
+
* Call this from WebSocket handlers, SSE listeners, polling loops, etc.
|
|
22
|
+
*/
|
|
23
|
+
set(flag, enabled) {
|
|
24
|
+
this.flags.set(flag, enabled);
|
|
25
|
+
bus.emit(new FlagChanged(flag, enabled));
|
|
26
|
+
}
|
|
27
|
+
/** Update a variant at runtime — fires FlagChanged on the bus */
|
|
28
|
+
setVariant(flag, value) {
|
|
29
|
+
this.variants.set(flag, value);
|
|
30
|
+
bus.emit(new FlagChanged(flag, this.isEnabled(flag), value));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAO,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,OAAgB,YAAY;IAChC,+DAA+D;IACrD,KAAK,GAAG,IAAI,GAAG,EAAmB,CAAC;IACnC,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAQ/C;;;OAGG;IACH,GAAG,CAAC,IAAY,EAAE,OAAgB;QAChC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9B,GAAG,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,iEAAiE;IACjE,UAAU,CAAC,IAAY,EAAE,KAAa;QACpC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/D,CAAC;CACF"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomFlags — MockFlags (testing transport)
|
|
3
|
+
*
|
|
4
|
+
* Drop-in test provider for @toyz/loom-flags.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { MockFlags } from "@toyz/loom-flags/testing";
|
|
8
|
+
*
|
|
9
|
+
* const flags = new MockFlags();
|
|
10
|
+
* flags.enable("dark-mode");
|
|
11
|
+
* flags.disable("beta-export");
|
|
12
|
+
* flags.setVariant("checkout-flow", "variant-b");
|
|
13
|
+
*
|
|
14
|
+
* app.use(FlagProvider, flags);
|
|
15
|
+
*
|
|
16
|
+
* flags.assertChecked("dark-mode");
|
|
17
|
+
* flags.assertEnabled("dark-mode");
|
|
18
|
+
* flags.reset();
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
import { FlagProvider } from "./provider";
|
|
22
|
+
export declare class MockFlags extends FlagProvider {
|
|
23
|
+
/** Track which flags were checked (for assertions) */
|
|
24
|
+
readonly checked: string[];
|
|
25
|
+
/** Enable a flag */
|
|
26
|
+
enable(flag: string): void;
|
|
27
|
+
/** Disable a flag */
|
|
28
|
+
disable(flag: string): void;
|
|
29
|
+
/** Check if a flag is enabled */
|
|
30
|
+
isEnabled(flag: string, _context?: Record<string, any>): boolean;
|
|
31
|
+
/** Get a flag's variant value */
|
|
32
|
+
getVariant<T = string>(flag: string, fallback: T): T;
|
|
33
|
+
/** Assert a flag was checked at least once */
|
|
34
|
+
assertChecked(flag: string): void;
|
|
35
|
+
/** Assert a flag was NOT checked */
|
|
36
|
+
assertNotChecked(flag: string): void;
|
|
37
|
+
/** Assert a flag is currently enabled */
|
|
38
|
+
assertEnabled(flag: string): void;
|
|
39
|
+
/** Assert a flag is currently disabled */
|
|
40
|
+
assertDisabled(flag: string): void;
|
|
41
|
+
/** Reset all state */
|
|
42
|
+
reset(): void;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,qBAAa,SAAU,SAAQ,YAAY;IACzC,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAM;IAEhC,oBAAoB;IACpB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI1B,qBAAqB;IACrB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI3B,iCAAiC;IACjC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO;IAKhE,iCAAiC;IACjC,UAAU,CAAC,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC;IAMpD,8CAA8C;IAC9C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMjC,oCAAoC;IACpC,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMpC,yCAAyC;IACzC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMjC,0CAA0C;IAC1C,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMlC,sBAAsB;IACtB,KAAK,IAAI,IAAI;CAKd"}
|
package/dist/testing.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomFlags — MockFlags (testing transport)
|
|
3
|
+
*
|
|
4
|
+
* Drop-in test provider for @toyz/loom-flags.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { MockFlags } from "@toyz/loom-flags/testing";
|
|
8
|
+
*
|
|
9
|
+
* const flags = new MockFlags();
|
|
10
|
+
* flags.enable("dark-mode");
|
|
11
|
+
* flags.disable("beta-export");
|
|
12
|
+
* flags.setVariant("checkout-flow", "variant-b");
|
|
13
|
+
*
|
|
14
|
+
* app.use(FlagProvider, flags);
|
|
15
|
+
*
|
|
16
|
+
* flags.assertChecked("dark-mode");
|
|
17
|
+
* flags.assertEnabled("dark-mode");
|
|
18
|
+
* flags.reset();
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
import { FlagProvider } from "./provider";
|
|
22
|
+
export class MockFlags extends FlagProvider {
|
|
23
|
+
/** Track which flags were checked (for assertions) */
|
|
24
|
+
checked = [];
|
|
25
|
+
/** Enable a flag */
|
|
26
|
+
enable(flag) {
|
|
27
|
+
this.set(flag, true);
|
|
28
|
+
}
|
|
29
|
+
/** Disable a flag */
|
|
30
|
+
disable(flag) {
|
|
31
|
+
this.set(flag, false);
|
|
32
|
+
}
|
|
33
|
+
/** Check if a flag is enabled */
|
|
34
|
+
isEnabled(flag, _context) {
|
|
35
|
+
this.checked.push(flag);
|
|
36
|
+
return this.flags.get(flag) ?? false;
|
|
37
|
+
}
|
|
38
|
+
/** Get a flag's variant value */
|
|
39
|
+
getVariant(flag, fallback) {
|
|
40
|
+
this.checked.push(flag);
|
|
41
|
+
const val = this.variants.get(flag);
|
|
42
|
+
return (val !== undefined ? val : fallback);
|
|
43
|
+
}
|
|
44
|
+
/** Assert a flag was checked at least once */
|
|
45
|
+
assertChecked(flag) {
|
|
46
|
+
if (!this.checked.includes(flag)) {
|
|
47
|
+
throw new Error(`Expected flag "${flag}" to be checked, but it was not.`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Assert a flag was NOT checked */
|
|
51
|
+
assertNotChecked(flag) {
|
|
52
|
+
if (this.checked.includes(flag)) {
|
|
53
|
+
throw new Error(`Expected flag "${flag}" to NOT be checked, but it was.`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Assert a flag is currently enabled */
|
|
57
|
+
assertEnabled(flag) {
|
|
58
|
+
if (!this.flags.get(flag)) {
|
|
59
|
+
throw new Error(`Expected flag "${flag}" to be enabled, but it is ${this.flags.get(flag) ?? "unset"}.`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Assert a flag is currently disabled */
|
|
63
|
+
assertDisabled(flag) {
|
|
64
|
+
if (this.flags.get(flag) === true) {
|
|
65
|
+
throw new Error(`Expected flag "${flag}" to be disabled, but it is enabled.`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Reset all state */
|
|
69
|
+
reset() {
|
|
70
|
+
this.flags.clear();
|
|
71
|
+
this.variants.clear();
|
|
72
|
+
this.checked.length = 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,OAAO,SAAU,SAAQ,YAAY;IACzC,sDAAsD;IAC7C,OAAO,GAAa,EAAE,CAAC;IAEhC,oBAAoB;IACpB,MAAM,CAAC,IAAY;QACjB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACvB,CAAC;IAED,qBAAqB;IACrB,OAAO,CAAC,IAAY;QAClB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACxB,CAAC;IAED,iCAAiC;IACjC,SAAS,CAAC,IAAY,EAAE,QAA8B;QACpD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;IACvC,CAAC;IAED,iCAAiC;IACjC,UAAU,CAAa,IAAY,EAAE,QAAW;QAC9C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAM,CAAC;IACnD,CAAC;IAED,8CAA8C;IAC9C,aAAa,CAAC,IAAY;QACxB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,kCAAkC,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED,oCAAoC;IACpC,gBAAgB,CAAC,IAAY;QAC3B,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,kCAAkC,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED,yCAAyC;IACzC,aAAa,CAAC,IAAY;QACxB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,8BAA8B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC;QAC1G,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,cAAc,CAAC,IAAY;QACzB,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,sCAAsC,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1B,CAAC;CACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@toyz/loom-flags",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Feature flags for Loom — decorator-driven with real-time reactive updates",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "toyz",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/Toyz/loom.git",
|
|
11
|
+
"directory": "loom-flags"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"module": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./testing": {
|
|
26
|
+
"types": "./dist/testing.d.ts",
|
|
27
|
+
"import": "./dist/testing.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc",
|
|
32
|
+
"dev": "tsc --watch",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"clean": "rm -rf dist",
|
|
35
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@toyz/loom": "^0.12.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"happy-dom": "^20.7.0",
|
|
42
|
+
"typescript": "^5.7.0",
|
|
43
|
+
"vitest": "^3.0.0"
|
|
44
|
+
},
|
|
45
|
+
"keywords": [
|
|
46
|
+
"loom",
|
|
47
|
+
"feature-flags",
|
|
48
|
+
"decorators",
|
|
49
|
+
"reactive",
|
|
50
|
+
"web-components"
|
|
51
|
+
]
|
|
52
|
+
}
|