@fougere/decorators 0.2.0-alpha.1 → 0.4.0-alpha.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/README.md CHANGED
@@ -12,4 +12,4 @@ pnpm add @fougere/decorators
12
12
 
13
13
  Part of [Fougere](https://github.com/chok/fougere) — one schema, a gradient from
14
14
  monolith to distributed, the same user code.
15
- Reference documentation: [the site](https://chok.github.io/fougere/) (en/fr).
15
+ Reference documentation: [the site](https://fougere.dev/) (en/fr).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fougere/decorators",
3
- "version": "0.2.0-alpha.1",
3
+ "version": "0.4.0-alpha.0",
4
4
  "description": "Configuration sugar (@config) — declarative, never hidden runtime.",
5
5
  "keywords": [
6
6
  "fougere",
@@ -25,7 +25,8 @@
25
25
  }
26
26
  },
27
27
  "files": [
28
- "dist"
28
+ "dist",
29
+ "src"
29
30
  ],
30
31
  "publishConfig": {
31
32
  "access": "public"
package/src/index.ts ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * TC39 Stage 3 decorator — marks a class or method as part of the frond's
3
+ * public contract.
4
+ *
5
+ * On a class: sets `__exposed = true` (readable via `isExposed()`).
6
+ * On a method: collects method name in a WeakMap keyed by class (readable via `getExposedMethods()`).
7
+ *
8
+ * This is syntactic sugar — the source of truth for exposure can also be
9
+ * `defineFrond({ expose: [...] })` in `frond.config.ts`, which takes precedence.
10
+ */
11
+
12
+ const exposedMethods = new WeakMap<object, Set<string>>();
13
+
14
+ export function expose(target: Function, context: ClassDecoratorContext): void;
15
+ export function expose(target: Function, context: ClassMethodDecoratorContext): void;
16
+ export function expose(
17
+ target: Function,
18
+ context: ClassDecoratorContext | ClassMethodDecoratorContext,
19
+ ): void {
20
+ if (context.kind === 'class') {
21
+ (target as any).__exposed = true;
22
+ }
23
+ if (context.kind === 'method') {
24
+ context.addInitializer(function (this: any) {
25
+ const ctor = this.constructor;
26
+ let set = exposedMethods.get(ctor);
27
+ if (!set) {
28
+ set = new Set();
29
+ exposedMethods.set(ctor, set);
30
+ }
31
+ set.add(context.name as string);
32
+ });
33
+ }
34
+ }
35
+
36
+ /** Check whether a class has been marked with `@expose`. */
37
+ export function isExposed(cls: Function): boolean {
38
+ return (cls as any).__exposed === true;
39
+ }
40
+
41
+ /** Get method names marked with `@expose` on a class. Requires one instantiation to populate. */
42
+ export function getExposedMethods(cls: Function): Set<string> {
43
+ // Trigger initializers if not already done
44
+ if (!exposedMethods.has(cls)) {
45
+ try { new (cls as any)(); } catch { /* best effort */ }
46
+ }
47
+ return exposedMethods.get(cls) ?? new Set<string>();
48
+ }