@signalium/query 0.0.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.
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+
3
+ /**
4
+ * Helper utilities for React tests in the query package
5
+ */
6
+
7
+ export interface RenderCounter<Props extends Record<string, unknown>> {
8
+ (props: Props): React.ReactNode;
9
+ testId: number;
10
+ renderCount: number;
11
+ }
12
+
13
+ let CURRENT_ID = 0;
14
+
15
+ export type ComponentType<P = any> = (props: P) => React.ReactNode;
16
+ export type HOC<InProps = any, OutProps = InProps> = (Component: ComponentType<InProps>) => ComponentType<OutProps>;
17
+
18
+ /**
19
+ * The wrapper passed to createRenderCounter is a HOC that will wrap the component
20
+ * with additional functionality. The reason we don't pass a component directly is
21
+ * because introducing additional components would mess with the real render counts.
22
+ */
23
+ const EmptyWrapper: HOC = Component => props => Component(props);
24
+
25
+ /**
26
+ * Creates a component that tracks how many times it renders.
27
+ * Useful for verifying that components only re-render when expected.
28
+ */
29
+ export function createRenderCounter<Props extends Record<string, unknown>>(
30
+ Component: (props: Props) => React.ReactNode,
31
+ wrapper: HOC<Props> = EmptyWrapper,
32
+ ): RenderCounter<Props> {
33
+ const id = CURRENT_ID++;
34
+
35
+ const RenderCounterComponent = wrapper((props: Props) => {
36
+ RenderCounterComponent.renderCount++;
37
+
38
+ // Call the component manually so it's not a separate React component
39
+ const children = Component(props);
40
+
41
+ return <div data-testid={id}>{children}</div>;
42
+ }) as RenderCounter<Props>;
43
+
44
+ RenderCounterComponent.testId = id;
45
+ RenderCounterComponent.renderCount = 0;
46
+
47
+ return RenderCounterComponent;
48
+ }
49
+
50
+ /**
51
+ * Mock user data factory
52
+ */
53
+ export function createUser(id: number, overrides?: Partial<{ name: string; email: string }>) {
54
+ return {
55
+ id,
56
+ name: overrides?.name ?? `User ${id}`,
57
+ email: overrides?.email ?? `user${id}@example.com`,
58
+ };
59
+ }
60
+
61
+ /**
62
+ * Mock post data factory
63
+ */
64
+ export function createPost(id: number, authorId: number, overrides?: Partial<{ title: string; content: string }>) {
65
+ return {
66
+ id,
67
+ authorId,
68
+ title: overrides?.title ?? `Post ${id}`,
69
+ content: overrides?.content ?? `Content for post ${id}`,
70
+ };
71
+ }
@@ -0,0 +1,351 @@
1
+ import {
2
+ APITypes,
3
+ ARRAY_KEY,
4
+ ArrayDef,
5
+ ComplexTypeDef,
6
+ EntityDef,
7
+ Mask,
8
+ ObjectDef,
9
+ ObjectShape,
10
+ RECORD_KEY,
11
+ RecordDef,
12
+ TypeDef,
13
+ ObjectFieldTypeDef,
14
+ UnionDef,
15
+ UnionTypeDefs,
16
+ } from './types.js';
17
+ import { extractShape, extractShapeMetadata } from './utils.js';
18
+
19
+ export class ValidatorDef<T> {
20
+ private _optional: ValidatorDef<T | undefined> | undefined;
21
+ private _nullable: ValidatorDef<T | null> | undefined;
22
+ private _nullish: ValidatorDef<T | null | undefined> | undefined;
23
+
24
+ constructor(
25
+ public mask: Mask,
26
+ public shape: ObjectFieldTypeDef | ObjectShape | ((t: APITypes) => ObjectShape) | UnionTypeDefs | undefined,
27
+ public subEntityPaths: undefined | string | string[] = undefined,
28
+ public values: Set<string | boolean | number> | undefined = undefined,
29
+ public typenameField: string | undefined = undefined,
30
+ public typenameValue: string | undefined = undefined,
31
+ public idField: string | undefined = undefined,
32
+ ) {}
33
+
34
+ get optional(): ValidatorDef<T | undefined> {
35
+ if (this._optional === undefined) {
36
+ this._optional = new ValidatorDef(
37
+ this.mask | Mask.UNDEFINED,
38
+ this.shape,
39
+ this.subEntityPaths,
40
+ this.values,
41
+ this.typenameField,
42
+ this.typenameValue,
43
+ this.idField,
44
+ );
45
+ }
46
+ return this._optional;
47
+ }
48
+
49
+ get nullable(): ValidatorDef<T | null> {
50
+ if (this._nullable === undefined) {
51
+ this._nullable = new ValidatorDef(
52
+ this.mask | Mask.NULL,
53
+ this.shape,
54
+ this.subEntityPaths,
55
+ this.values,
56
+ this.typenameField,
57
+ this.typenameValue,
58
+ this.idField,
59
+ );
60
+ }
61
+ return this._nullable;
62
+ }
63
+
64
+ get nullish(): ValidatorDef<T | null | undefined> {
65
+ if (this._nullish === undefined) {
66
+ this._nullish = new ValidatorDef(
67
+ this.mask | Mask.UNDEFINED | Mask.NULL,
68
+ this.shape,
69
+ this.subEntityPaths,
70
+ this.values,
71
+ this.typenameField,
72
+ this.typenameValue,
73
+ this.idField,
74
+ );
75
+ }
76
+ return this._nullish;
77
+ }
78
+ }
79
+
80
+ // -----------------------------------------------------------------------------
81
+ // Complex Type Definitions
82
+ // -----------------------------------------------------------------------------
83
+
84
+ export function defineArray<T extends TypeDef>(shape: T): ArrayDef<T> {
85
+ let mask = Mask.ARRAY;
86
+
87
+ // Propagate HAS_SUB_ENTITY flag if the shape contains entities
88
+ if (shape instanceof ValidatorDef && (shape.mask & (Mask.ENTITY | Mask.HAS_SUB_ENTITY)) !== 0) {
89
+ mask |= Mask.HAS_SUB_ENTITY;
90
+ }
91
+
92
+ return new ValidatorDef(mask, shape) as unknown as ArrayDef<T>;
93
+ }
94
+
95
+ export function defineRecord<T extends TypeDef>(shape: T): RecordDef<T> {
96
+ // The mask should be OBJECT | RECORD so that values match when compared
97
+ let mask = Mask.RECORD | Mask.OBJECT;
98
+
99
+ // Propagate HAS_SUB_ENTITY flag if the shape contains entities
100
+ if (shape instanceof ValidatorDef && (shape.mask & (Mask.ENTITY | Mask.HAS_SUB_ENTITY)) !== 0) {
101
+ mask |= Mask.HAS_SUB_ENTITY;
102
+ }
103
+
104
+ return new ValidatorDef(mask, shape) as unknown as RecordDef<T>;
105
+ }
106
+
107
+ export function defineObject<T extends ObjectShape>(shape: T): ObjectDef<T> {
108
+ const def = new ValidatorDef(Mask.OBJECT, shape);
109
+
110
+ extractShapeMetadata(def, shape);
111
+
112
+ return def as unknown as ObjectDef<T>;
113
+ }
114
+
115
+ const addShapeToUnion = (
116
+ shape: UnionTypeDefs,
117
+ definition: ObjectDef | EntityDef | RecordDef | UnionDef | ArrayDef,
118
+ unionTypenameField: string | undefined,
119
+ ) => {
120
+ const mask = definition.mask;
121
+
122
+ if ((mask & Mask.UNION) !== 0) {
123
+ // Merge nested union into parent union
124
+ const nestedUnion = definition as UnionDef;
125
+
126
+ // Check typename field consistency
127
+ if (nestedUnion.typenameField !== undefined) {
128
+ if (unionTypenameField !== undefined && unionTypenameField !== nestedUnion.typenameField) {
129
+ throw new Error(
130
+ `Union typename field conflict: Cannot merge unions with different typename fields ('${unionTypenameField}' vs '${nestedUnion.typenameField}')`,
131
+ );
132
+ }
133
+ unionTypenameField = nestedUnion.typenameField;
134
+ }
135
+
136
+ // Merge nested union's shape into parent
137
+ if (nestedUnion.shape !== undefined) {
138
+ for (const key of [...Object.keys(nestedUnion.shape), ARRAY_KEY, RECORD_KEY] as const) {
139
+ // Check for conflicts
140
+ const value = nestedUnion.shape[key];
141
+
142
+ if (shape[key] !== undefined && shape[key] !== value) {
143
+ throw new Error(
144
+ `Union merge conflict: Duplicate typename value '${String(key)}' found when merging nested unions`,
145
+ );
146
+ }
147
+
148
+ // coerce type because we know the value is the same type as the key
149
+ shape[key] = value as any;
150
+ }
151
+ }
152
+
153
+ return unionTypenameField;
154
+ } else if ((mask & Mask.ARRAY) !== 0) {
155
+ if (shape[ARRAY_KEY] !== undefined) {
156
+ throw new Error('Array shape already defined');
157
+ }
158
+
159
+ shape[ARRAY_KEY] = definition.shape as TypeDef;
160
+
161
+ return unionTypenameField;
162
+ } else if ((mask & Mask.RECORD) !== 0) {
163
+ if (shape[RECORD_KEY] !== undefined) {
164
+ throw new Error('Record shape already defined');
165
+ }
166
+
167
+ shape[RECORD_KEY] = definition.shape as TypeDef;
168
+
169
+ return unionTypenameField;
170
+ } else {
171
+ // Make sure the type is fully extracted, so we can get the typename field and value
172
+ extractShape(definition);
173
+
174
+ // definition is ObjectDef | EntityDef
175
+ const typenameField = (definition as ObjectDef).typenameField;
176
+ const typename = (definition as ObjectDef).typenameValue;
177
+
178
+ if (typename === undefined) {
179
+ throw new Error(
180
+ 'Object definitions must have a typename to be in a union with other objects, records, or arrays',
181
+ );
182
+ }
183
+
184
+ if (unionTypenameField !== undefined && typenameField !== unionTypenameField) {
185
+ throw new Error('Object definitions must have the same typename field to be in the same union');
186
+ }
187
+
188
+ shape[typename] = definition as ObjectDef;
189
+
190
+ return typenameField;
191
+ }
192
+ };
193
+
194
+ function defineUnion<T extends readonly TypeDef[]>(...types: T): UnionDef<T> {
195
+ let mask = 0;
196
+ let definition: ObjectDef | EntityDef | RecordDef | UnionDef | ArrayDef | undefined;
197
+ let shape: UnionTypeDefs | undefined;
198
+ let values: Set<string | boolean | number> | undefined;
199
+ let unionTypenameField: string | undefined;
200
+
201
+ for (const type of types) {
202
+ if (typeof type === 'number') {
203
+ mask |= type;
204
+ continue;
205
+ }
206
+
207
+ const isSet = type instanceof Set;
208
+ const typeValues = isSet ? type : type.values;
209
+
210
+ // Handle Set-based constants/enums
211
+ if (typeValues !== undefined) {
212
+ if (values === undefined) {
213
+ values = new Set(typeValues);
214
+ } else {
215
+ for (const val of typeValues) {
216
+ values.add(val);
217
+ }
218
+ }
219
+
220
+ if (isSet) {
221
+ continue;
222
+ }
223
+ }
224
+
225
+ // We know it's a complex type at this point because if it was a Set,
226
+ // we would have already handled it above.
227
+ const typeDef = type as ComplexTypeDef;
228
+
229
+ mask |= typeDef.mask;
230
+
231
+ if (definition === undefined) {
232
+ definition = typeDef;
233
+ continue;
234
+ }
235
+
236
+ if (shape === undefined) {
237
+ shape = Object.create(null) as UnionTypeDefs;
238
+
239
+ unionTypenameField = addShapeToUnion(shape, definition, unionTypenameField);
240
+ }
241
+
242
+ unionTypenameField = addShapeToUnion(shape, typeDef, unionTypenameField);
243
+ }
244
+
245
+ // It was a union of primitives, so return the mask
246
+ if (definition === undefined && values === undefined) {
247
+ // This type coercion is incorrect, but we can't return the mask as a Mask
248
+ // because that loses the type information about the union, which breaks
249
+ // inference.
250
+ //
251
+ // TODO: Figure out how to make this correct type-wise
252
+ return mask as unknown as UnionDef<T>;
253
+ }
254
+
255
+ return new ValidatorDef(
256
+ mask | Mask.UNION,
257
+ shape ?? definition?.shape,
258
+ undefined,
259
+ values,
260
+ unionTypenameField,
261
+ ) as UnionDef;
262
+ }
263
+
264
+ // -----------------------------------------------------------------------------
265
+ // Marker Functions
266
+ // -----------------------------------------------------------------------------
267
+
268
+ function defineTypename<T extends string>(value: T): T {
269
+ return value;
270
+ }
271
+
272
+ function defineConst<T extends string | boolean | number>(value: T): Set<T> {
273
+ return new Set([value]);
274
+ }
275
+
276
+ function defineEnum<T extends readonly (string | boolean | number)[]>(...values: T): Set<T[number]> {
277
+ return new Set(values as unknown as T[number][]);
278
+ }
279
+
280
+ // -----------------------------------------------------------------------------
281
+ // Formatted Values
282
+ // -----------------------------------------------------------------------------
283
+
284
+ const FORMAT_MASK_SHIFT = 16;
285
+
286
+ let nextFormatId = 0;
287
+ const FORMAT_PARSERS: ((value: unknown) => unknown)[] = [];
288
+ const FORMAT_SERIALIZERS: ((value: unknown) => unknown)[] = [];
289
+ const FORMAT_MAP = new Map<string, number>();
290
+
291
+ function defineFormatted(format: string): number {
292
+ const mask = FORMAT_MAP.get(format);
293
+
294
+ if (mask === undefined) {
295
+ throw new Error(`Format ${format} not registered`);
296
+ }
297
+
298
+ return mask;
299
+ }
300
+
301
+ export function getFormat(mask: number): (value: unknown) => unknown {
302
+ const formatId = mask >> FORMAT_MASK_SHIFT;
303
+
304
+ return FORMAT_PARSERS[formatId];
305
+ }
306
+
307
+ export function registerFormat<Input extends string | boolean, T>(
308
+ name: string,
309
+ type: Input extends string ? Mask.STRING : Mask.BOOLEAN,
310
+ parse: (value: Input) => T,
311
+ serialize: (value: T) => Input,
312
+ ) {
313
+ const maskId = nextFormatId++;
314
+ FORMAT_PARSERS[maskId] = parse as (value: unknown) => unknown;
315
+ FORMAT_SERIALIZERS[maskId] = serialize as (value: unknown) => unknown;
316
+
317
+ const shiftedId = maskId << FORMAT_MASK_SHIFT;
318
+ const formatMask = type === Mask.STRING ? Mask.HAS_STRING_FORMAT : Mask.HAS_NUMBER_FORMAT;
319
+ const mask = shiftedId | type | formatMask;
320
+
321
+ FORMAT_MAP.set(name, mask);
322
+ }
323
+
324
+ // -----------------------------------------------------------------------------
325
+ // Entity Definitions
326
+ // -----------------------------------------------------------------------------
327
+
328
+ export function entity<T extends ObjectShape>(shape: (t: APITypes) => T): EntityDef<T> {
329
+ return new ValidatorDef(
330
+ // The mask should be OBJECT | ENTITY so that values match when compared
331
+ Mask.ENTITY | Mask.OBJECT,
332
+ shape,
333
+ ) as unknown as EntityDef<T>;
334
+ }
335
+
336
+ export const t: APITypes = {
337
+ format: defineFormatted,
338
+ typename: defineTypename,
339
+ const: defineConst,
340
+ enum: defineEnum,
341
+ id: Mask.ID | Mask.STRING | Mask.NUMBER,
342
+ string: Mask.STRING,
343
+ number: Mask.NUMBER,
344
+ boolean: Mask.BOOLEAN,
345
+ null: Mask.NULL,
346
+ undefined: Mask.UNDEFINED,
347
+ array: defineArray,
348
+ object: defineObject,
349
+ record: defineRecord,
350
+ union: defineUnion,
351
+ };
package/src/types.ts ADDED
@@ -0,0 +1,121 @@
1
+ import { PendingReactivePromise, ReadyReactivePromise } from 'signalium';
2
+ import { ReactivePromise } from 'signalium';
3
+
4
+ export const enum Mask {
5
+ // Fundamental types
6
+ UNDEFINED = 1 << 0,
7
+ NULL = 1 << 1,
8
+ NUMBER = 1 << 2,
9
+ STRING = 1 << 3,
10
+ BOOLEAN = 1 << 4,
11
+ OBJECT = 1 << 5,
12
+ ARRAY = 1 << 6,
13
+ ID = 1 << 7,
14
+
15
+ // Complex types
16
+ RECORD = 1 << 8,
17
+ UNION = 1 << 9,
18
+ ENTITY = 1 << 10,
19
+
20
+ // Flags
21
+ HAS_SUB_ENTITY = 1 << 11,
22
+ HAS_NUMBER_FORMAT = 1 << 12,
23
+ HAS_STRING_FORMAT = 1 << 13,
24
+ }
25
+
26
+ export type SimpleTypeDef =
27
+ // Sets are constant values
28
+ | Set<string | boolean | number>
29
+
30
+ // Numbers are primitive type masks (potentially multiple masks combined)
31
+ | Mask;
32
+
33
+ export type ComplexTypeDef =
34
+ // Objects, arrays, records, and unions are definitions
35
+ ObjectDef | EntityDef | ArrayDef | RecordDef | UnionDef;
36
+
37
+ export type TypeDef = SimpleTypeDef | ComplexTypeDef;
38
+
39
+ export type ObjectFieldTypeDef = TypeDef | string;
40
+
41
+ export type ObjectShape = Record<string, ObjectFieldTypeDef>;
42
+
43
+ export const ARRAY_KEY = Symbol('array');
44
+ export const RECORD_KEY = Symbol('record');
45
+
46
+ export interface UnionTypeDefs {
47
+ [ARRAY_KEY]?: TypeDef;
48
+ [RECORD_KEY]?: TypeDef;
49
+ [key: string]: ObjectDef | EntityDef;
50
+ }
51
+
52
+ export interface BaseTypeDef {
53
+ mask: Mask;
54
+ typenameField: string;
55
+ typenameValue: string;
56
+ idField: string;
57
+ subEntityPaths: undefined | string | string[];
58
+ values: Set<string | boolean | number> | undefined;
59
+
60
+ optional: this | Mask.UNDEFINED;
61
+ nullable: this | Mask.NULL;
62
+ nullish: this | Mask.UNDEFINED | Mask.NULL;
63
+ }
64
+
65
+ export interface EntityDef<T extends ObjectShape = ObjectShape> extends BaseTypeDef {
66
+ mask: Mask.ENTITY;
67
+ shape: T | ((t: APITypes) => T);
68
+ }
69
+
70
+ export interface ObjectDef<T extends ObjectShape = ObjectShape> extends BaseTypeDef {
71
+ mask: Mask.OBJECT;
72
+ shape: T;
73
+ }
74
+
75
+ export interface ArrayDef<T extends TypeDef = TypeDef> extends BaseTypeDef {
76
+ mask: Mask.ARRAY;
77
+ shape: T;
78
+ }
79
+
80
+ export interface UnionDef<_T extends readonly TypeDef[] = readonly TypeDef[]> extends BaseTypeDef {
81
+ mask: Mask.UNION;
82
+ shape: UnionTypeDefs | undefined;
83
+ }
84
+
85
+ export interface RecordDef<T extends TypeDef = TypeDef> extends BaseTypeDef {
86
+ mask: Mask.RECORD;
87
+ shape: T;
88
+ }
89
+
90
+ export interface APITypes {
91
+ format: (format: string) => number;
92
+ typename: <T extends string>(value: T) => T;
93
+ const: <T extends string | boolean | number>(value: T) => Set<T>;
94
+ enum: <T extends readonly (string | boolean | number)[]>(...values: T) => Set<T[number]>;
95
+
96
+ id: Mask.ID;
97
+ string: Mask.STRING;
98
+ number: Mask.NUMBER;
99
+ boolean: Mask.BOOLEAN;
100
+ null: Mask.NULL;
101
+ undefined: Mask.UNDEFINED;
102
+
103
+ array: <T extends TypeDef>(shape: T) => ArrayDef<T>;
104
+
105
+ object: <T extends ObjectShape>(shape: T) => ObjectDef<T>;
106
+ record: <T extends TypeDef>(shape: T) => RecordDef<T>;
107
+
108
+ union: <VS extends readonly TypeDef[]>(...types: VS) => UnionDef<VS>;
109
+ }
110
+
111
+ type QueryResultExtensions<T> = {
112
+ refetch: () => Promise<T>;
113
+ };
114
+
115
+ export type QueryResult<T> = ReactivePromise<T> & QueryResultExtensions<T>;
116
+
117
+ export type PendingQueryResult<T> = PendingReactivePromise<T> & QueryResultExtensions<T>;
118
+
119
+ export type ReadyQueryResult<T> = ReadyReactivePromise<T> & QueryResultExtensions<T>;
120
+
121
+ export type DiscriminatedQueryResult<T> = PendingQueryResult<T> | ReadyQueryResult<T>;
package/src/utils.ts ADDED
@@ -0,0 +1,66 @@
1
+ import { t, ValidatorDef } from './typeDefs.js';
2
+ import { ComplexTypeDef, EntityDef, Mask, ObjectShape } from './types.js';
3
+
4
+ const entries = Object.entries;
5
+ const isArray = Array.isArray;
6
+
7
+ export function extractShapeMetadata(def: ValidatorDef<any>, shape: ObjectShape): void {
8
+ for (const [key, value] of Object.entries(shape)) {
9
+ if (value instanceof ValidatorDef && (value.mask & (Mask.ENTITY | Mask.HAS_SUB_ENTITY)) !== 0) {
10
+ if (def.subEntityPaths === undefined) {
11
+ def.subEntityPaths = key;
12
+ } else if (isArray(def.subEntityPaths)) {
13
+ def.subEntityPaths.push(key);
14
+ } else {
15
+ def.subEntityPaths = [def.subEntityPaths, key];
16
+ }
17
+ }
18
+ // Check if this is a typename field (plain string value)
19
+ if (typeof value === 'string') {
20
+ if (def.typenameField !== undefined) {
21
+ throw new Error(`Duplicate typename field: ${key}`);
22
+ }
23
+
24
+ def.typenameField = key;
25
+ def.typenameValue = value;
26
+ }
27
+ // Check if this is an id field (Mask.ID)
28
+ else if (typeof value === 'number' && (value & Mask.ID) !== 0) {
29
+ if (def.idField !== undefined) {
30
+ throw new Error(`Duplicate id field: ${key}`);
31
+ }
32
+
33
+ def.idField = key;
34
+ }
35
+ }
36
+ }
37
+
38
+ export function extractShape<T extends ComplexTypeDef>(def: T): T extends EntityDef ? ObjectShape : T['shape'] {
39
+ let shape = def.shape;
40
+
41
+ if (typeof shape === 'function') {
42
+ shape = def.shape = shape(t);
43
+ extractShapeMetadata(def as ValidatorDef<any>, shape);
44
+ }
45
+
46
+ return shape as T extends EntityDef ? ObjectShape : T['shape'];
47
+ }
48
+
49
+ export function typeMaskOf(value: unknown): Mask {
50
+ if (value === null) return Mask.NULL;
51
+
52
+ switch (typeof value) {
53
+ case 'number':
54
+ return Mask.NUMBER;
55
+ case 'string':
56
+ return Mask.STRING;
57
+ case 'boolean':
58
+ return Mask.BOOLEAN;
59
+ case 'undefined':
60
+ return Mask.UNDEFINED;
61
+ case 'object':
62
+ return isArray(value) ? Mask.ARRAY : Mask.OBJECT;
63
+ default:
64
+ throw new Error(`Invalid type: ${typeof value}`);
65
+ }
66
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist/cjs",
5
+ "declaration": false,
6
+ "declarationMap": false,
7
+ "sourceMap": true,
8
+ "jsx": "react-jsx",
9
+ "module": "commonjs",
10
+ "moduleResolution": "node"
11
+ },
12
+ "include": ["src"],
13
+ "exclude": ["**/__tests__"]
14
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist/esm",
5
+ "rootDir": "src",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "sourceMap": true,
9
+ "jsx": "react-jsx"
10
+ },
11
+ "include": ["src"],
12
+ "exclude": ["**/__tests__"]
13
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist/esm",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "emitDeclarationOnly": false,
8
+ "jsx": "react-jsx",
9
+ "baseUrl": ".",
10
+ "paths": {
11
+ "signalium": ["../signalium/src/index.ts"],
12
+ "signalium/utils": ["../signalium/src/utils.ts"],
13
+ "signalium/config": ["../signalium/src/config.ts"],
14
+ "signalium/debug": ["../signalium/src/debug.ts"],
15
+ "signalium/react": ["../signalium/src/react/index.ts"],
16
+ "signalium/transform": ["../signalium/src/transform/index.ts"]
17
+ }
18
+ },
19
+ "include": ["src", "vitest.config.ts"]
20
+ }