@interactors/core 1.0.1 → 1.1.0-alpha.1

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 (94) hide show
  1. package/esm/src/constructor.d.ts.map +1 -1
  2. package/esm/src/constructor.js +8 -1
  3. package/esm/src/constructor.js.map +1 -1
  4. package/esm/src/errors.d.ts.map +1 -1
  5. package/esm/src/errors.js.map +1 -1
  6. package/esm/src/index.d.ts +3 -0
  7. package/esm/src/index.d.ts.map +1 -1
  8. package/esm/src/index.js +2 -0
  9. package/esm/src/index.js.map +1 -1
  10. package/esm/src/matcher.d.ts +4 -0
  11. package/esm/src/matcher.d.ts.map +1 -1
  12. package/esm/src/matcher.js +8 -0
  13. package/esm/src/matcher.js.map +1 -1
  14. package/esm/src/matchers/and.d.ts.map +1 -1
  15. package/esm/src/matchers/and.js +2 -1
  16. package/esm/src/matchers/and.js.map +1 -1
  17. package/esm/src/matchers/every.d.ts.map +1 -1
  18. package/esm/src/matchers/every.js +2 -1
  19. package/esm/src/matchers/every.js.map +1 -1
  20. package/esm/src/matchers/including.d.ts.map +1 -1
  21. package/esm/src/matchers/including.js +2 -1
  22. package/esm/src/matchers/including.js.map +1 -1
  23. package/esm/src/matchers/matching.d.ts.map +1 -1
  24. package/esm/src/matchers/matching.js +2 -1
  25. package/esm/src/matchers/matching.js.map +1 -1
  26. package/esm/src/matchers/not.d.ts.map +1 -1
  27. package/esm/src/matchers/not.js +2 -1
  28. package/esm/src/matchers/not.js.map +1 -1
  29. package/esm/src/matchers/or.d.ts.map +1 -1
  30. package/esm/src/matchers/or.js +2 -1
  31. package/esm/src/matchers/or.js.map +1 -1
  32. package/esm/src/matchers/some.d.ts.map +1 -1
  33. package/esm/src/matchers/some.js +2 -1
  34. package/esm/src/matchers/some.js.map +1 -1
  35. package/esm/src/merge-objects.d.ts +1 -1
  36. package/esm/src/merge-objects.d.ts.map +1 -1
  37. package/esm/src/metadata.d.ts +50 -0
  38. package/esm/src/metadata.d.ts.map +1 -0
  39. package/esm/src/metadata.js +96 -0
  40. package/esm/src/metadata.js.map +1 -0
  41. package/package.json +1 -1
  42. package/script/src/constructor.d.ts.map +1 -1
  43. package/script/src/constructor.js +8 -1
  44. package/script/src/constructor.js.map +1 -1
  45. package/script/src/errors.d.ts.map +1 -1
  46. package/script/src/errors.js.map +1 -1
  47. package/script/src/index.d.ts +3 -0
  48. package/script/src/index.d.ts.map +1 -1
  49. package/script/src/index.js +9 -1
  50. package/script/src/index.js.map +1 -1
  51. package/script/src/matcher.d.ts +4 -0
  52. package/script/src/matcher.d.ts.map +1 -1
  53. package/script/src/matcher.js +9 -0
  54. package/script/src/matcher.js.map +1 -1
  55. package/script/src/matchers/and.d.ts.map +1 -1
  56. package/script/src/matchers/and.js +1 -0
  57. package/script/src/matchers/and.js.map +1 -1
  58. package/script/src/matchers/every.d.ts.map +1 -1
  59. package/script/src/matchers/every.js +1 -0
  60. package/script/src/matchers/every.js.map +1 -1
  61. package/script/src/matchers/including.d.ts.map +1 -1
  62. package/script/src/matchers/including.js +1 -0
  63. package/script/src/matchers/including.js.map +1 -1
  64. package/script/src/matchers/matching.d.ts.map +1 -1
  65. package/script/src/matchers/matching.js +1 -0
  66. package/script/src/matchers/matching.js.map +1 -1
  67. package/script/src/matchers/not.d.ts.map +1 -1
  68. package/script/src/matchers/not.js +1 -0
  69. package/script/src/matchers/not.js.map +1 -1
  70. package/script/src/matchers/or.d.ts.map +1 -1
  71. package/script/src/matchers/or.js +1 -0
  72. package/script/src/matchers/or.js.map +1 -1
  73. package/script/src/matchers/some.d.ts.map +1 -1
  74. package/script/src/matchers/some.js +1 -0
  75. package/script/src/matchers/some.js.map +1 -1
  76. package/script/src/merge-objects.d.ts +1 -1
  77. package/script/src/merge-objects.d.ts.map +1 -1
  78. package/script/src/metadata.d.ts +50 -0
  79. package/script/src/metadata.d.ts.map +1 -0
  80. package/script/src/metadata.js +105 -0
  81. package/script/src/metadata.js.map +1 -0
  82. package/src/src/constructor.ts +10 -1
  83. package/src/src/errors.ts +4 -4
  84. package/src/src/index.ts +12 -0
  85. package/src/src/matcher.ts +12 -0
  86. package/src/src/matchers/and.ts +3 -1
  87. package/src/src/matchers/every.ts +3 -1
  88. package/src/src/matchers/including.ts +3 -1
  89. package/src/src/matchers/matching.ts +3 -1
  90. package/src/src/matchers/not.ts +3 -1
  91. package/src/src/matchers/or.ts +3 -1
  92. package/src/src/matchers/some.ts +3 -1
  93. package/src/src/merge-objects.ts +3 -1
  94. package/src/src/metadata.ts +166 -0
@@ -0,0 +1,166 @@
1
+ import type { Matcher } from "./matcher.js";
2
+ import type { InteractorConstructor } from "./specification.js";
3
+
4
+ /**
5
+ * Version of the metadata attached to interactor and matcher constructors.
6
+ *
7
+ * Consumers should use the helpers in this module instead of reading the
8
+ * symbol properties directly.
9
+ */
10
+ export const CONSTRUCTOR_METADATA_VERSION = 1 as const;
11
+
12
+ /** @internal */
13
+ export const INTERACTOR_CONSTRUCTOR_METADATA = Symbol.for(
14
+ "@interactors/core/interactor-constructor-metadata",
15
+ );
16
+
17
+ /** @internal */
18
+ export const MATCHER_CONSTRUCTOR_METADATA = Symbol.for(
19
+ "@interactors/core/matcher-constructor-metadata",
20
+ );
21
+
22
+ export interface InteractorConstructorMetadata {
23
+ readonly kind: "interactor";
24
+ readonly version: typeof CONSTRUCTOR_METADATA_VERSION;
25
+ readonly name: string;
26
+ readonly actions: readonly string[];
27
+ readonly filters: readonly string[];
28
+ }
29
+
30
+ export interface MatcherConstructorMetadata {
31
+ readonly kind: "matcher";
32
+ readonly version: typeof CONSTRUCTOR_METADATA_VERSION;
33
+ readonly name: string;
34
+ }
35
+
36
+ type AnyInteractorConstructor = InteractorConstructor<
37
+ Element,
38
+ any,
39
+ any,
40
+ any
41
+ >;
42
+
43
+ type AnyMatcherConstructor = (...args: any[]) => Matcher<any>;
44
+
45
+ /**
46
+ * Return stable, serializable metadata for an interactor constructor.
47
+ */
48
+ export function getInteractorConstructorMetadata(
49
+ value: unknown,
50
+ ): InteractorConstructorMetadata | undefined {
51
+ if (typeof value !== "function") {
52
+ return undefined;
53
+ }
54
+
55
+ let metadata = Reflect.get(value, INTERACTOR_CONSTRUCTOR_METADATA);
56
+
57
+ return isInteractorConstructorMetadata(metadata) ? metadata : undefined;
58
+ }
59
+
60
+ /**
61
+ * Determine whether a value was created by {@link createInteractor}.
62
+ *
63
+ * The brand uses the global symbol registry so this works when the producer
64
+ * and consumer load different copies of `@interactors/core`.
65
+ */
66
+ export function isInteractorConstructor(
67
+ value: unknown,
68
+ ): value is AnyInteractorConstructor {
69
+ return getInteractorConstructorMetadata(value) !== undefined;
70
+ }
71
+
72
+ /**
73
+ * Return stable, serializable metadata for a matcher constructor.
74
+ */
75
+ export function getMatcherConstructorMetadata(
76
+ value: unknown,
77
+ ): MatcherConstructorMetadata | undefined {
78
+ if (typeof value !== "function") {
79
+ return undefined;
80
+ }
81
+
82
+ let metadata = Reflect.get(value, MATCHER_CONSTRUCTOR_METADATA);
83
+
84
+ return isMatcherConstructorMetadata(metadata) ? metadata : undefined;
85
+ }
86
+
87
+ /** Determine whether a value was created by {@link createMatcher}. */
88
+ export function isMatcherConstructor(
89
+ value: unknown,
90
+ ): value is AnyMatcherConstructor {
91
+ return getMatcherConstructorMetadata(value) !== undefined;
92
+ }
93
+
94
+ /** @internal */
95
+ export function defineInteractorConstructorMetadata(
96
+ constructor: Function,
97
+ metadata: Omit<InteractorConstructorMetadata, "kind" | "version">,
98
+ ): void {
99
+ defineMetadata(constructor, INTERACTOR_CONSTRUCTOR_METADATA, {
100
+ kind: "interactor",
101
+ version: CONSTRUCTOR_METADATA_VERSION,
102
+ name: metadata.name,
103
+ actions: Object.freeze([...metadata.actions].sort()),
104
+ filters: Object.freeze([...metadata.filters].sort()),
105
+ });
106
+ }
107
+
108
+ /** @internal */
109
+ export function defineMatcherConstructorMetadata(
110
+ constructor: Function,
111
+ metadata: Omit<MatcherConstructorMetadata, "kind" | "version">,
112
+ ): void {
113
+ defineMetadata(constructor, MATCHER_CONSTRUCTOR_METADATA, {
114
+ kind: "matcher",
115
+ version: CONSTRUCTOR_METADATA_VERSION,
116
+ name: metadata.name,
117
+ });
118
+ }
119
+
120
+ function defineMetadata(
121
+ constructor: Function,
122
+ key: symbol,
123
+ metadata: InteractorConstructorMetadata | MatcherConstructorMetadata,
124
+ ): void {
125
+ Object.defineProperty(constructor, key, {
126
+ configurable: false,
127
+ enumerable: false,
128
+ writable: false,
129
+ value: Object.freeze(metadata),
130
+ });
131
+ }
132
+
133
+ function isInteractorConstructorMetadata(
134
+ value: unknown,
135
+ ): value is InteractorConstructorMetadata {
136
+ if (!isRecord(value)) {
137
+ return false;
138
+ }
139
+
140
+ return value.kind === "interactor" &&
141
+ value.version === CONSTRUCTOR_METADATA_VERSION &&
142
+ typeof value.name === "string" &&
143
+ isStringArray(value.actions) &&
144
+ isStringArray(value.filters);
145
+ }
146
+
147
+ function isMatcherConstructorMetadata(
148
+ value: unknown,
149
+ ): value is MatcherConstructorMetadata {
150
+ if (!isRecord(value)) {
151
+ return false;
152
+ }
153
+
154
+ return value.kind === "matcher" &&
155
+ value.version === CONSTRUCTOR_METADATA_VERSION &&
156
+ typeof value.name === "string";
157
+ }
158
+
159
+ function isRecord(value: unknown): value is Record<PropertyKey, unknown> {
160
+ return typeof value === "object" && value !== null;
161
+ }
162
+
163
+ function isStringArray(value: unknown): value is readonly string[] {
164
+ return Array.isArray(value) &&
165
+ value.every((item) => typeof item === "string");
166
+ }