teamplay 0.5.0-alpha.2 → 0.5.0-alpha.21

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 (44) hide show
  1. package/dist/index.d.ts +22 -8
  2. package/dist/index.js +1 -4
  3. package/dist/orm/Aggregation.d.ts +6 -4
  4. package/dist/orm/Aggregation.js +39 -11
  5. package/dist/orm/Compat/SignalCompat.js +141 -409
  6. package/dist/orm/Compat/queryReadiness.d.ts +13 -5
  7. package/dist/orm/Compat/silentContext.js +4 -22
  8. package/dist/orm/Compat/startStopCompat.js +33 -0
  9. package/dist/orm/Doc.js +48 -3
  10. package/dist/orm/Query.d.ts +1 -0
  11. package/dist/orm/Query.js +67 -22
  12. package/dist/orm/Signal.d.ts +3 -3
  13. package/dist/orm/SignalBase.d.ts +27 -2
  14. package/dist/orm/SignalBase.js +296 -5
  15. package/dist/orm/addModel.d.ts +9 -2
  16. package/dist/orm/getSignal.js +0 -2
  17. package/dist/orm/index.d.ts +2 -2
  18. package/dist/orm/privateData.d.ts +7 -22
  19. package/dist/orm/signalMetadata.d.ts +1 -1
  20. package/dist/orm/signalMetadata.js +29 -3
  21. package/dist/orm/signalReads.d.ts +1 -1
  22. package/dist/orm/signalReads.js +7 -7
  23. package/dist/orm/signalSymbols.js +1 -1
  24. package/dist/orm/sub.d.ts +9 -1
  25. package/dist/orm/subscriptionGcDelay.js +2 -6
  26. package/dist/orm/types/baseMethods.d.ts +2 -1
  27. package/dist/orm/types/jsonSchema.d.ts +3 -3
  28. package/dist/orm/types/modelManifest.d.ts +12 -1
  29. package/dist/orm/types/query.d.ts +7 -1
  30. package/dist/orm/types/signal.d.ts +44 -15
  31. package/dist/react/convertToObserver.js +1 -4
  32. package/dist/react/promiseBatcher.js +1 -1
  33. package/dist/react/renderAttemptDestroyer.d.ts +0 -8
  34. package/dist/react/renderAttemptDestroyer.js +2 -28
  35. package/dist/react/trapRender.js +3 -3
  36. package/dist/react/useSub.d.ts +104 -5
  37. package/dist/react/useSub.js +191 -32
  38. package/dist/react/useSuspendMemo.js +1 -5
  39. package/dist/server.d.ts +1 -1
  40. package/package.json +16 -10
  41. package/dist/orm/Compat/hooksCompat.d.ts +0 -33
  42. package/dist/orm/Compat/hooksCompat.js +0 -360
  43. package/dist/react/compatComponentRegistry.d.ts +0 -4
  44. package/dist/react/compatComponentRegistry.js +0 -19
@@ -1,5 +1,6 @@
1
1
  import type { Signal as BaseSignal } from '../SignalBase.js';
2
2
  import type { CollectionSpec, JsonSchemaSpec, SignalClass } from './signal.js';
3
+ import type { FromJsonSchema } from './jsonSchema.js';
3
4
  export interface ModelEntry<TModel extends SignalClass<any> = SignalClass<any>, TSchema = unknown> {
4
5
  default?: TModel;
5
6
  schema?: TSchema;
@@ -8,10 +9,14 @@ export interface ModelEntry<TModel extends SignalClass<any> = SignalClass<any>,
8
9
  }
9
10
  export type ModelManifest = Record<string, ModelEntry>;
10
11
  type StringKey<TValue> = Extract<keyof TValue, string>;
11
- type CollectionManifestKey<TKey extends string> = TKey extends '' ? never : TKey extends `${string}.${string}` ? never : TKey extends `${string}*${string}` ? never : TKey;
12
+ type CollectionManifestKey<TKey extends string> = TKey extends '' ? never : TKey extends `_${string}` | `$${string}` ? never : TKey extends `${string}.${string}` ? never : TKey extends `${string}*${string}` ? never : TKey;
13
+ type PrivateCollectionManifestKey<TKey extends string> = TKey extends '' ? never : TKey extends `${string}.${string}` ? never : TKey extends `${string}*${string}` ? never : TKey extends `_${string}` | `$${string}` ? TKey : never;
12
14
  type CollectionManifestKeys<TModels> = {
13
15
  [K in StringKey<TModels>]: CollectionManifestKey<K>;
14
16
  }[StringKey<TModels>];
17
+ type PrivateCollectionManifestKeys<TModels> = {
18
+ [K in StringKey<TModels>]: PrivateCollectionManifestKey<K>;
19
+ }[StringKey<TModels>];
15
20
  type ModelPathManifestKey<TKey extends string> = TKey extends '' ? never : TKey extends `${string}*${string}` ? TKey : never;
16
21
  type ModelPathManifestKeys<TModels> = {
17
22
  [K in StringKey<TModels>]: ModelPathManifestKey<K>;
@@ -26,9 +31,15 @@ type SchemaFromEntry<TEntry> = TEntry extends {
26
31
  type CollectionSpecFromManifestEntry<TModels, TCollection extends string> = [
27
32
  SchemaFromEntry<ManifestEntry<TModels, TCollection>>
28
33
  ] extends [never] ? CollectionSpec<unknown, ModelFromEntry<ManifestEntry<TModels, TCollection>>, ModelFromEntry<ManifestEntry<TModels, `${TCollection}.*`>>> : JsonSchemaSpec<SchemaFromEntry<ManifestEntry<TModels, TCollection>>, ModelFromEntry<ManifestEntry<TModels, TCollection>>, ModelFromEntry<ManifestEntry<TModels, `${TCollection}.*`>>>;
34
+ type PrivateCollectionValueFromManifestEntry<TModels, TCollection extends string> = [
35
+ SchemaFromEntry<ManifestEntry<TModels, TCollection>>
36
+ ] extends [never] ? unknown : FromJsonSchema<SchemaFromEntry<ManifestEntry<TModels, TCollection>>>;
29
37
  export type CollectionsFromManifest<TModels extends Record<string, any>> = {
30
38
  [K in CollectionManifestKeys<TModels>]: CollectionSpecFromManifestEntry<TModels, K>;
31
39
  };
40
+ export type PrivateCollectionsFromManifest<TModels extends Record<string, any>> = {
41
+ [K in PrivateCollectionManifestKeys<TModels>]: PrivateCollectionValueFromManifestEntry<TModels, K>;
42
+ };
32
43
  export type PathModelsFromManifest<TModels extends Record<string, any>> = {
33
44
  [K in ModelPathManifestKeys<TModels> as ManifestEntry<TModels, K> extends {
34
45
  default: any;
@@ -16,14 +16,20 @@ type QueryValue<TValue> = QueryComparable<TValue> | {
16
16
  $exists?: boolean;
17
17
  $regex?: TValue extends string ? string | RegExp : never;
18
18
  };
19
+ type QuerySortDirection = 1 | -1 | 'asc' | 'desc' | 'ascending' | 'descending';
20
+ type QuerySort<TDocument> = {
21
+ [K in QueryPath<TDocument> | '_id' | 'id']?: QuerySortDirection;
22
+ };
19
23
  export type QueryParams<TDocument> = {
20
24
  [K in QueryPath<TDocument>]?: QueryValue<QueryPathValue<TDocument, K>>;
21
25
  } & {
22
26
  _id?: QueryValue<string | number>;
23
27
  id?: QueryValue<string | number>;
24
28
  } & {
25
- [K in `${string}.${string}`]?: unknown;
29
+ $sort?: QuerySort<TDocument>;
26
30
  } & {
27
31
  [K in `$${string}`]?: unknown;
28
32
  };
33
+ export type ComputedQueryParamsInput<TParams extends object> = string extends keyof TParams ? TParams : never;
34
+ export type QueryParamsInput<TDocument, TParams extends object> = TParams extends QueryParams<TDocument> ? TParams : ComputedQueryParamsInput<TParams>;
29
35
  export {};
@@ -1,4 +1,4 @@
1
- import type { TeamplayCollections, TeamplayModels, TeamplaySignalFields } from '../../index.js';
1
+ import type { TeamplayCollections, TeamplayPrivateCollections, TeamplayPluginPrivateCollections, TeamplayModels, TeamplayPluginCollections, TeamplayPluginModels, TeamplayPluginSignalFields, TeamplaySignalFields } from '../../index.js';
2
2
  import type { Signal, GETTERS } from '../SignalBase.js';
3
3
  import type { FromJsonSchema, InferZodSchema, JsonSchema, ZodLikeSchema } from './jsonSchema.js';
4
4
  import type { AppendPath, JoinPath, PathSegment, WildcardSignalPath } from './path.js';
@@ -20,11 +20,29 @@ type SignalQueryMethodKeys = SignalArrayReaderMethodKeys | SignalArrayMutatorMet
20
20
  type BlockedArrayMutators = {
21
21
  readonly [K in SignalArrayMutatorMethodKeys]?: never;
22
22
  };
23
+ type UnionToIntersection<TValue> = (TValue extends unknown ? (value: TValue) => void : never) extends (value: infer Intersection) => void ? Intersection : never;
24
+ type RegistryValues<TRegistry> = TRegistry[keyof TRegistry & string];
25
+ type MergeRegistry<TRegistry> = [
26
+ RegistryValues<TRegistry>
27
+ ] extends [never] ? {} : UnionToIntersection<RegistryValues<TRegistry>>;
28
+ type EffectiveTeamplayCollections = TeamplayCollections & MergeRegistry<TeamplayPluginCollections>;
29
+ type EffectiveTeamplayPrivateCollections = TeamplayPrivateCollections & MergeRegistry<TeamplayPluginPrivateCollections>;
30
+ type EffectiveTeamplayModels = TeamplayModels & MergeRegistry<TeamplayPluginModels>;
31
+ type EffectiveTeamplaySignalFields = TeamplaySignalFields & MergeRegistry<TeamplayPluginSignalFields>;
32
+ type RootDollarAliases = {
33
+ readonly session: '_session';
34
+ readonly page: '_page';
35
+ readonly render: '$render';
36
+ readonly system: '$system';
37
+ };
23
38
  type SignalArrayLike<TItem> = SignalArrayReaderMethods<TItem>;
24
- type PathModel<TValue, TDefaultModel extends SignalClass<any>, TPath extends WildcardSignalPath> = JoinPath<TPath> extends keyof TeamplayModels ? TeamplayModels[JoinPath<TPath>] extends SignalClass<TValue> ? TeamplayModels[JoinPath<TPath>] : TeamplayModels[JoinPath<TPath>] extends SignalClass<any> ? TeamplayModels[JoinPath<TPath>] : TDefaultModel : TDefaultModel;
39
+ type PathModel<TValue, TDefaultModel extends SignalClass<any>, TPath extends WildcardSignalPath> = JoinPath<TPath> extends keyof EffectiveTeamplayModels ? EffectiveTeamplayModels[JoinPath<TPath>] extends SignalClass<TValue> ? EffectiveTeamplayModels[JoinPath<TPath>] : EffectiveTeamplayModels[JoinPath<TPath>] extends SignalClass<any> ? EffectiveTeamplayModels[JoinPath<TPath>] : TDefaultModel : TDefaultModel;
25
40
  type ArrayItemSignal<Item, TPath extends WildcardSignalPath> = DocumentSignal<Item, typeof Signal, AppendPath<TPath, '*'>>;
26
41
  type SignalArrayMethods<TValue, TPath extends WildcardSignalPath> = NonNullable<TValue> extends ReadonlyArray<infer Item> ? SignalArrayLike<ArrayItemSignal<Item, TPath>> : Pick<Signal<TValue>, SignalArrayReaderMethodKeys>;
27
- type SignalFieldsForPath<TPath extends WildcardSignalPath> = JoinPath<TPath> extends keyof TeamplaySignalFields ? TeamplaySignalFields[JoinPath<TPath>] : {};
42
+ type SignalFieldsForPath<TPath extends WildcardSignalPath> = JoinPath<TPath> extends keyof EffectiveTeamplaySignalFields ? EffectiveTeamplaySignalFields[JoinPath<TPath>] : {};
43
+ type DocumentSignalIdMethod = {
44
+ getId: () => string;
45
+ };
28
46
  export type AnySignal = Signal<any>;
29
47
  type IsAny<TValue> = 0 extends (1 & TValue) ? true : false;
30
48
  type IsUnknown<TValue> = IsAny<TValue> extends true ? false : unknown extends TValue ? true : false;
@@ -34,7 +52,7 @@ type IsUnion<TValue, TUnion = TValue> = [
34
52
  ] extends [never] ? false : TValue extends unknown ? [TUnion] extends [TValue] ? false : true : false;
35
53
  type SingleKey<TKey> = IsUnion<TKey> extends true ? never : TKey;
36
54
  export type SignalKind = 'root' | 'document' | 'collection' | 'nestedValue' | 'localArray' | 'array' | 'query' | 'aggregation' | 'collectionQuery';
37
- type DocumentSignalForKind<TValue, TModel extends SignalClass<any>, TPath extends WildcardSignalPath> = Omit<SignalModelInstance<TValue, PathModel<TValue, TModel, TPath>>, SignalArrayReaderMethodKeys> & SignalArrayMethods<TValue, TPath> & SignalChildren<TValue, TPath> & SignalFieldsForPath<TPath>;
55
+ type DocumentSignalForKind<TValue, TModel extends SignalClass<any>, TPath extends WildcardSignalPath> = Omit<SignalModelInstance<TValue, PathModel<TValue, TModel, TPath>>, SignalArrayReaderMethodKeys | 'getId'> & DocumentSignalIdMethod & SignalArrayMethods<TValue, TPath> & SignalChildren<TValue, TPath> & SignalFieldsForPath<TPath>;
38
56
  type CollectionSignalForKind<TDocument, TCollectionModel extends SignalClass<any>, TDocumentModel extends SignalClass<any>, TPath extends WildcardSignalPath> = Omit<SignalModelInstance<TDocument[], PathModel<TDocument[], TCollectionModel, TPath>>, SignalCollectionMethodKeys> & SignalArrayLike<CollectionDocumentSignal<TDocument, TDocumentModel, TPath>> & BlockedArrayMutators & {
39
57
  add: (value: TDocument) => Promise<string>;
40
58
  } & CollectionDocumentIndex<CollectionDocumentSignal<TDocument, TDocumentModel, TPath>>;
@@ -43,7 +61,7 @@ type ArraySignalForKind<TDocument, TDocumentModel extends SignalClass<any>, TDoc
43
61
  readonly [index: number]: DocumentSignal<TDocument, TDocumentModel, TDocumentPath>;
44
62
  } & BlockedArrayMutators;
45
63
  type QueryMetadataSignals = {
46
- readonly ids: Signal<Array<string | number>>;
64
+ readonly ids: Signal<string[]>;
47
65
  readonly extra: Signal<unknown>;
48
66
  };
49
67
  type QuerySignalForKind<TDocument, TDocumentModel extends SignalClass<any>, TDocumentPath extends WildcardSignalPath> = ArraySignalForKind<TDocument, TDocumentModel, TDocumentPath> & QueryMetadataSignals;
@@ -59,22 +77,22 @@ export type CollectionDocument<TSpec> = TSpec extends CollectionSpec<infer Docum
59
77
  export type CollectionDocumentModel<TSpec> = TSpec extends CollectionSpec<any, any, infer DocumentModel> ? DocumentModel : typeof Signal;
60
78
  export type CollectionQuerySignal<TDocument, TCollectionModel extends SignalClass<any>, TDocumentModel extends SignalClass<any>, TCollectionPath extends WildcardSignalPath> = CollectionSignalForKind<TDocument, TCollectionModel, TDocumentModel, TCollectionPath> & QueryMetadataSignals;
61
79
  type MatchingDocumentCollectionKeys<TValue> = IsAny<TValue> extends true ? never : {
62
- [K in keyof TeamplayCollections & string]: IsEqual<NonNullable<TValue>, NonNullable<CollectionDocument<TeamplayCollections[K]>>> extends true ? K : never;
63
- }[keyof TeamplayCollections & string];
80
+ [K in keyof EffectiveTeamplayCollections & string]: IsEqual<NonNullable<TValue>, NonNullable<CollectionDocument<EffectiveTeamplayCollections[K]>>> extends true ? K : never;
81
+ }[keyof EffectiveTeamplayCollections & string];
64
82
  type MatchingCollectionKeys<TValue> = IsAny<TValue> extends true ? never : NonNullable<TValue> extends ReadonlyArray<infer TDocument> ? MatchingDocumentCollectionKeys<TDocument> : never;
65
83
  type SingleDocumentCollectionKey<TValue> = SingleKey<MatchingDocumentCollectionKeys<TValue>>;
66
84
  type SingleCollectionKey<TValue> = SingleKey<MatchingCollectionKeys<TValue>>;
67
85
  type DocumentSignalModelForValue<TValue> = [
68
86
  SingleDocumentCollectionKey<TValue>
69
- ] extends [never] ? typeof Signal : SingleDocumentCollectionKey<TValue> extends keyof TeamplayCollections & string ? CollectionDocumentModel<TeamplayCollections[SingleDocumentCollectionKey<TValue>]> : typeof Signal;
87
+ ] extends [never] ? typeof Signal : SingleDocumentCollectionKey<TValue> extends keyof EffectiveTeamplayCollections & string ? CollectionDocumentModel<EffectiveTeamplayCollections[SingleDocumentCollectionKey<TValue>]> : typeof Signal;
70
88
  type DocumentSignalPathForValue<TValue> = [
71
89
  SingleDocumentCollectionKey<TValue>
72
- ] extends [never] ? readonly [] : SingleDocumentCollectionKey<TValue> extends keyof TeamplayCollections & string ? readonly [SingleDocumentCollectionKey<TValue>, '*'] : readonly [];
90
+ ] extends [never] ? readonly [] : SingleDocumentCollectionKey<TValue> extends keyof EffectiveTeamplayCollections & string ? readonly [SingleDocumentCollectionKey<TValue>, '*'] : readonly [];
73
91
  type SignalForDocumentValue<TValue> = TypedSignal<TValue, DocumentSignalModelForValue<TValue>, DocumentSignalPathForValue<TValue>>;
74
- type SignalForCollectionArrayValue<TCollection extends keyof TeamplayCollections & string> = CollectionSignal<CollectionDocument<TeamplayCollections[TCollection]>, TeamplayCollections[TCollection] extends CollectionSpec<any, infer CollectionModel, any> ? CollectionModel : typeof Signal, CollectionDocumentModel<TeamplayCollections[TCollection]>, readonly [TCollection]>;
92
+ type SignalForCollectionArrayValue<TCollection extends keyof EffectiveTeamplayCollections & string> = CollectionSignal<CollectionDocument<EffectiveTeamplayCollections[TCollection]>, EffectiveTeamplayCollections[TCollection] extends CollectionSpec<any, infer CollectionModel, any> ? CollectionModel : typeof Signal, CollectionDocumentModel<EffectiveTeamplayCollections[TCollection]>, readonly [TCollection]>;
75
93
  type SignalForArrayValue<TValue> = [
76
94
  SingleCollectionKey<TValue>
77
- ] extends [never] ? SignalForDocumentValue<TValue> : SingleCollectionKey<TValue> extends keyof TeamplayCollections & string ? SignalForCollectionArrayValue<SingleCollectionKey<TValue>> : SignalForDocumentValue<TValue>;
95
+ ] extends [never] ? SignalForDocumentValue<TValue> : SingleCollectionKey<TValue> extends keyof EffectiveTeamplayCollections & string ? SignalForCollectionArrayValue<SingleCollectionKey<TValue>> : SignalForDocumentValue<TValue>;
78
96
  export type PublicSignal<TValue = unknown> = IsAny<TValue> extends true ? TypedSignal<TValue> : NonNullable<TValue> extends ReadonlyArray<any> ? SignalForArrayValue<TValue> : SignalForDocumentValue<TValue>;
79
97
  export interface LocalSignalFactory {
80
98
  (): any;
@@ -82,12 +100,12 @@ export interface LocalSignalFactory {
82
100
  <TValue>(factory: () => TValue): TypedSignal<TValue>;
83
101
  <TValue>(value: TValue): TypedSignal<TValue>;
84
102
  }
85
- export type RootCollections<TCollections extends Record<string, any> = TeamplayCollections> = {
103
+ export type RootCollections<TCollections = EffectiveTeamplayCollections> = {
86
104
  readonly [K in keyof TCollections & string]: CollectionSignalFromSpec<TCollections[K], readonly [K]>;
87
105
  } & {
88
106
  readonly [K in keyof TCollections & string as `$${K}`]: CollectionSignalFromSpec<TCollections[K], readonly [K]>;
89
107
  };
90
- export type RootSignal<TCollections extends Record<string, any> = TeamplayCollections> = Signal<Record<string, unknown>> & LocalSignalFactory & RootCollections<TCollections>;
108
+ export type RootSignal<TCollections = EffectiveTeamplayCollections> = Signal<Record<string, unknown>> & LocalSignalFactory & RootCollections<TCollections> & RootPrivateCollections;
91
109
  export interface RegisteredAggregationInput<TCollection extends string = string, TOutput = unknown> {
92
110
  readonly __isAggregation: true;
93
111
  readonly collection: TCollection;
@@ -98,10 +116,10 @@ export interface TypedAggregationInput<TDocument = unknown, TDocumentModel exten
98
116
  readonly __teamplayDocument?: TDocument;
99
117
  readonly __teamplayDocumentModel?: TDocumentModel;
100
118
  }
101
- export type CollectionAggregationSignal<TCollection extends keyof TeamplayCollections & string> = AggregationSignal<CollectionDocument<TeamplayCollections[TCollection]>, CollectionDocumentModel<TeamplayCollections[TCollection]>, readonly [TCollection, '*']>;
119
+ export type CollectionAggregationSignal<TCollection extends keyof EffectiveTeamplayCollections & string> = AggregationSignal<CollectionDocument<EffectiveTeamplayCollections[TCollection]>, CollectionDocumentModel<EffectiveTeamplayCollections[TCollection]>, readonly [TCollection, '*']>;
102
120
  export type TypedAggregationSignal<TDocument, TDocumentModel extends SignalClass<any>> = AggregationSignal<TDocument, TDocumentModel>;
103
121
  export type AggregationOutputSignal<TOutput> = IsAny<TOutput> extends true ? QuerySignal : NonNullable<TOutput> extends ReadonlyArray<infer TDocument> ? AggregationSignal<TDocument, DocumentSignalModelForValue<TDocument>, DocumentSignalPathForValue<TDocument>> : SignalForDocumentValue<TOutput>;
104
- type RegisteredAggregationSignal<TCollection extends string, TOutput> = IsUnknown<TOutput> extends true ? TCollection extends keyof TeamplayCollections & string ? CollectionAggregationSignal<TCollection> : QuerySignal : AggregationOutputSignal<TOutput>;
122
+ type RegisteredAggregationSignal<TCollection extends string, TOutput> = IsUnknown<TOutput> extends true ? TCollection extends keyof EffectiveTeamplayCollections & string ? CollectionAggregationSignal<TCollection> : QuerySignal : AggregationOutputSignal<TOutput>;
105
123
  export type MaybePromise<TValue> = TValue | Promise<TValue>;
106
124
  export type SubResult<TSignal, TParams = undefined> = TSignal extends ClientAggregationFunction<infer TOutput, infer TCollection> ? RegisteredAggregationSignal<TCollection, TOutput> : TSignal extends AggregationFunction<infer TOutput, any> ? IsUnknown<TOutput> extends true ? QuerySignal : AggregationOutputSignal<TOutput> : TSignal extends TypedAggregationInput<infer TDocument, infer TDocumentModel> ? TypedAggregationSignal<TDocument, TDocumentModel> : TSignal extends RegisteredAggregationInput<infer TCollection, infer TOutput> ? RegisteredAggregationSignal<TCollection, TOutput> : [TParams] extends [undefined] ? TSignal extends DocumentSignal<any, any, any> ? TSignal : QuerySignal : TSignal extends CollectionSignal<infer TDocument, infer TCollectionModel, infer TDocumentModel, infer TCollectionPath> ? CollectionQuerySignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath> : QuerySignal;
107
125
  export type MaybePromiseSubResult<TSignal, TParams = undefined> = MaybePromise<SubResult<TSignal, TParams>>;
@@ -121,6 +139,17 @@ export interface CollectionSpec<TDocument = unknown, TCollectionModel extends Si
121
139
  export type JsonSchemaSpec<TSchema, TCollectionModel extends SignalClass<any> = typeof Signal, TDocumentModel extends SignalClass<any> = typeof Signal> = CollectionSpec<FromJsonSchema<TSchema>, TCollectionModel, TDocumentModel>;
122
140
  export type ZodSchemaSpec<TSchema extends ZodLikeSchema, TCollectionModel extends SignalClass<any> = typeof Signal, TDocumentModel extends SignalClass<any> = typeof Signal> = CollectionSpec<InferZodSchema<TSchema>, TCollectionModel, TDocumentModel>;
123
141
  export type CollectionSignalFromSpec<TSpec, TPath extends WildcardSignalPath = readonly []> = TSpec extends CollectionSpec<infer Document, infer CollectionModel, infer DocumentModel> ? CollectionSignal<Document, CollectionModel, DocumentModel, TPath> : TSpec extends JsonSchema ? CollectionSignal<FromJsonSchema<TSpec>, typeof Signal, typeof Signal, TPath> : CollectionSignal;
142
+ export type PrivateSignalFromSpec<TSpec, TPath extends WildcardSignalPath = readonly []> = Omit<DocumentSignal<TSpec, typeof Signal, TPath>, 'add'>;
143
+ type PrivateSignalForAlias<TPrivateCollections, TAlias extends keyof RootDollarAliases & string> = RootDollarAliases[TAlias] extends keyof TPrivateCollections & string ? PrivateSignalFromSpec<TPrivateCollections[RootDollarAliases[TAlias]], readonly [RootDollarAliases[TAlias]]> : never;
144
+ export type RootPrivateCollections<TPrivateCollections = EffectiveTeamplayPrivateCollections> = {
145
+ readonly [K in keyof TPrivateCollections & string]: PrivateSignalFromSpec<TPrivateCollections[K], readonly [K]>;
146
+ } & {
147
+ readonly [K in keyof TPrivateCollections & string as `$${K}`]: PrivateSignalFromSpec<TPrivateCollections[K], readonly [K]>;
148
+ } & {
149
+ readonly [K in keyof RootDollarAliases & string as RootDollarAliases[K] extends keyof TPrivateCollections & string ? K : never]: PrivateSignalForAlias<TPrivateCollections, K>;
150
+ } & {
151
+ readonly [K in keyof RootDollarAliases & string as RootDollarAliases[K] extends keyof TPrivateCollections & string ? `$${K}` : never]: PrivateSignalForAlias<TPrivateCollections, K>;
152
+ };
124
153
  export interface SignalConstructor {
125
154
  new <TValue = unknown>(segments: PathSegment[]): TypedSignal<TValue>;
126
155
  readonly ID_FIELDS: typeof Signal.ID_FIELDS;
@@ -7,7 +7,6 @@ import executionContextTracker from "./executionContextTracker.js";
7
7
  import { pipeComponentMeta, useUnmount, useId, useTriggerUpdate } from "./helpers.js";
8
8
  import trapRender from './trapRender.js';
9
9
  import { scheduleReaction } from '../orm/batchScheduler.js';
10
- import { isCompatComponent, unmarkCompatComponent } from "./compatComponentRegistry.js";
11
10
  const DEFAULT_THROTTLE_TIMEOUT = 100;
12
11
  export default function convertToObserver(BaseComponent, { forwardRef, cache: enableCache = true, throttle, ...options } = {}) {
13
12
  throttle = normalizeThrottle(throttle);
@@ -33,7 +32,7 @@ export default function convertToObserver(BaseComponent, { forwardRef, cache: en
33
32
  hasDeferredUpdateAfterExecutionContext = false;
34
33
  triggerUpdate();
35
34
  }
36
- else if (isCompatComponent(componentId)) {
35
+ else {
37
36
  if (hasDeferredUpdateAfterExecutionContext)
38
37
  return;
39
38
  hasDeferredUpdateAfterExecutionContext = true;
@@ -53,7 +52,6 @@ export default function convertToObserver(BaseComponent, { forwardRef, cache: en
53
52
  if (!reactionRef.current)
54
53
  throw Error(`NO REACTION REF - ${where}`);
55
54
  destroyRef.current = undefined;
56
- unmarkCompatComponent(componentId);
57
55
  unobserve(reactionRef.current);
58
56
  reactionRef.current = undefined;
59
57
  destroyCache(where);
@@ -71,7 +69,6 @@ export default function convertToObserver(BaseComponent, { forwardRef, cache: en
71
69
  }
72
70
  // clean up observer on unmount
73
71
  useUnmount(() => {
74
- unmarkCompatComponent(componentId);
75
72
  destroyRef.current?.('useUnmount()');
76
73
  });
77
74
  return reactionRef.current(...args);
@@ -95,7 +95,7 @@ function warnAboutChecksDelay(checks) {
95
95
  state
96
96
  };
97
97
  });
98
- console.warn('[teamplay] useBatch() is waiting for data materialization checks.', details);
98
+ console.warn('[teamplay] useBatchSub() is waiting for data materialization checks.', details);
99
99
  }
100
100
  function isDevMode() {
101
101
  const processLike = globalThis.process;
@@ -1,17 +1,9 @@
1
- type DestroyAttempt = () => unknown | Promise<unknown>;
2
1
  declare class RenderAttemptDestroyer {
3
- fns: DestroyAttempt[];
4
- compatAttemptCleanupArmed: boolean;
5
2
  suspenseGateArmed: boolean;
6
3
  constructor();
7
- add(fn: DestroyAttempt | undefined, { compat }?: {
8
- compat?: boolean;
9
- }): void;
10
- armCompatAttemptCleanup(): void;
11
4
  armSuspenseGate(): void;
12
5
  consumeThenableHandling(): {
13
6
  shouldKeepShellAlive: boolean;
14
- destroyAttempt?: () => Promise<void>;
15
7
  };
16
8
  reset(): void;
17
9
  }
@@ -1,45 +1,19 @@
1
1
  class RenderAttemptDestroyer {
2
- fns;
3
- compatAttemptCleanupArmed;
4
2
  suspenseGateArmed;
5
3
  constructor() {
6
- this.fns = [];
7
- this.compatAttemptCleanupArmed = false;
8
4
  this.suspenseGateArmed = false;
9
5
  }
10
- add(fn, { compat = false } = {}) {
11
- if (typeof fn !== 'function')
12
- return;
13
- this.fns.push(fn);
14
- if (compat)
15
- this.compatAttemptCleanupArmed = true;
16
- }
17
- armCompatAttemptCleanup() {
18
- this.compatAttemptCleanupArmed = true;
19
- }
20
6
  armSuspenseGate() {
21
7
  this.suspenseGateArmed = true;
22
8
  }
23
9
  consumeThenableHandling() {
24
- const shouldRunAttemptCleanup = this.compatAttemptCleanupArmed && this.fns.length > 0;
25
- const shouldKeepShellAlive = this.suspenseGateArmed || shouldRunAttemptCleanup;
26
- let destroyAttempt;
27
- if (shouldRunAttemptCleanup) {
28
- const fns = [...this.fns];
29
- destroyAttempt = async () => {
30
- await Promise.allSettled(fns.map(fn => fn()));
31
- fns.length = 0;
32
- };
33
- }
10
+ const shouldKeepShellAlive = this.suspenseGateArmed;
34
11
  this.reset();
35
12
  return {
36
- shouldKeepShellAlive,
37
- destroyAttempt
13
+ shouldKeepShellAlive
38
14
  };
39
15
  }
40
16
  reset() {
41
- this.fns.length = 0;
42
- this.compatAttemptCleanupArmed = false;
43
17
  this.suspenseGateArmed = false;
44
18
  }
45
19
  }
@@ -13,7 +13,7 @@ export default function trapRender({ render, cache, destroy, componentId }) {
13
13
  promiseBatcher.reset();
14
14
  const res = render(...args);
15
15
  if (isDevMode() && promiseBatcher.isActive()) {
16
- throw Error('[teamplay] useBatch* hooks were used without a closing useBatch() call.');
16
+ throw Error('[teamplay] batch subscriptions were used without a closing useBatchSub() call or useSub(undefined, undefined, { batch: true }) call.');
17
17
  }
18
18
  return res;
19
19
  }
@@ -24,9 +24,9 @@ export default function trapRender({ render, cache, destroy, componentId }) {
24
24
  destroyed = true;
25
25
  throw err;
26
26
  }
27
- const { shouldKeepShellAlive, destroyAttempt } = renderAttemptDestroyer.consumeThenableHandling();
27
+ const { shouldKeepShellAlive } = renderAttemptDestroyer.consumeThenableHandling();
28
28
  if (shouldKeepShellAlive) {
29
- throw Promise.resolve(err).then(() => destroyAttempt?.());
29
+ throw Promise.resolve(err);
30
30
  }
31
31
  // TODO: this might only be needed only if promise is thrown
32
32
  // (check if useUnmount in convertToObserver is called if a regular error is thrown)
@@ -1,5 +1,5 @@
1
1
  import type { AggregationFunction, AggregationParams, ClientAggregationFunction } from '@teamplay/utils/aggregation';
2
- import type { CollectionSignal, DocumentSignal, QueryParams, RegisteredAggregationInput, SignalModelConstructor, SubResult, TypedAggregationInput, TypedAggregationSignal, WildcardSignalPath } from '../orm/Signal.js';
2
+ import { type CollectionSignal, type ComputedQueryParamsInput, type DocumentSignal, type QueryParams, type RegisteredAggregationInput, type SignalModelConstructor, type SubResult, type TypedAggregationInput, type TypedAggregationSignal, type WildcardSignalPath } from '../orm/Signal.js';
3
3
  export interface UseSubOptions {
4
4
  /** Return `undefined` while loading instead of throwing a Suspense promise. */
5
5
  async?: boolean;
@@ -7,9 +7,14 @@ export interface UseSubOptions {
7
7
  defer?: boolean | number;
8
8
  /** Batch Suspense promises across multiple subscriptions in one render attempt. */
9
9
  batch?: boolean;
10
- /** Enable compatibility cleanup for legacy observer render attempts. */
11
- compatAttemptCleanup?: boolean;
12
10
  }
11
+ /**
12
+ * Subscribe to a document signal in React async mode.
13
+ * @param signal Document signal to subscribe to.
14
+ * @param params Must be omitted for document subscriptions.
15
+ * @param options Subscription behavior options.
16
+ */
17
+ export declare function useAsyncSub<TSignal extends DocumentSignal<any, any, any>>(signal: TSignal, options?: UseSubOptions): SubResult<TSignal>;
13
18
  /**
14
19
  * Subscribe to a document signal in React async mode.
15
20
  * @param signal Document signal to subscribe to.
@@ -24,6 +29,15 @@ export declare function useAsyncSub<TSignal extends DocumentSignal<any, any, any
24
29
  * @param options Subscription behavior options.
25
30
  */
26
31
  export declare function useAsyncSub<TDocument, TCollectionModel extends SignalModelConstructor<TDocument[]>, TDocumentModel extends SignalModelConstructor<TDocument>, TCollectionPath extends WildcardSignalPath>(signal: CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, params: QueryParams<TDocument>, options?: UseSubOptions): SubResult<CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, QueryParams<TDocument>>;
32
+ /**
33
+ * Subscribe to a collection query with computed string keys in React async mode.
34
+ * This fallback preserves Mongo-style computed paths such as `{ [`likes.${id}`]: true }`.
35
+ * Literal query objects should use the stricter overload above.
36
+ * @param signal Collection signal to query.
37
+ * @param params Mongo-style query params with a widened computed key.
38
+ * @param options Subscription behavior options.
39
+ */
40
+ export declare function useAsyncSub<TDocument, TCollectionModel extends SignalModelConstructor<TDocument[]>, TDocumentModel extends SignalModelConstructor<TDocument>, TCollectionPath extends WildcardSignalPath, TParams extends object>(signal: CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, params: TParams & ComputedQueryParamsInput<TParams>, options?: UseSubOptions): SubResult<CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, TParams>;
27
41
  /**
28
42
  * Subscribe to a registered collection aggregation in React async mode.
29
43
  * @param signal Aggregation header generated by StartupJS model loading.
@@ -52,6 +66,82 @@ export declare function useAsyncSub<TDocument, TDocumentModel extends SignalMode
52
66
  * @param options Subscription behavior options.
53
67
  */
54
68
  export declare function useAsyncSub<TOutput = unknown, TCollection extends string = string>(signal: AggregationFunction<TOutput, TCollection>, params?: AggregationParams, options?: UseSubOptions): SubResult<AggregationFunction<TOutput, TCollection>, AggregationParams | undefined>;
69
+ /**
70
+ * Close a batch subscription barrier opened by previous `useBatchSub()` calls in this render.
71
+ */
72
+ export declare function useBatchSub(): void;
73
+ /**
74
+ * Subscribe to a document signal in React batch mode.
75
+ * @param signal Document signal to subscribe to.
76
+ * @param params Must be omitted for document subscriptions.
77
+ * @param options Subscription behavior options.
78
+ */
79
+ export declare function useBatchSub<TSignal extends DocumentSignal<any, any, any>>(signal: TSignal, options?: UseSubOptions): SubResult<TSignal>;
80
+ /**
81
+ * Subscribe to a document signal in React batch mode.
82
+ * @param signal Document signal to subscribe to.
83
+ * @param params Must be omitted for document subscriptions.
84
+ * @param options Subscription behavior options.
85
+ */
86
+ export declare function useBatchSub<TSignal extends DocumentSignal<any, any, any>>(signal: TSignal, params?: undefined, options?: UseSubOptions): SubResult<TSignal>;
87
+ /**
88
+ * Subscribe to a collection query in React batch mode.
89
+ * @param signal Collection signal to query.
90
+ * @param params Mongo-style query params, including filters and `$sort`.
91
+ * @param options Subscription behavior options.
92
+ */
93
+ export declare function useBatchSub<TDocument, TCollectionModel extends SignalModelConstructor<TDocument[]>, TDocumentModel extends SignalModelConstructor<TDocument>, TCollectionPath extends WildcardSignalPath>(signal: CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, params: QueryParams<TDocument>, options?: UseSubOptions): SubResult<CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, QueryParams<TDocument>>;
94
+ /**
95
+ * Subscribe to a collection query with computed string keys in React batch mode.
96
+ * This fallback preserves Mongo-style computed paths such as `{ [`likes.${id}`]: true }`.
97
+ * Literal query objects should use the stricter overload above.
98
+ * @param signal Collection signal to query.
99
+ * @param params Mongo-style query params with a widened computed key.
100
+ * @param options Subscription behavior options.
101
+ */
102
+ export declare function useBatchSub<TDocument, TCollectionModel extends SignalModelConstructor<TDocument[]>, TDocumentModel extends SignalModelConstructor<TDocument>, TCollectionPath extends WildcardSignalPath, TParams extends object>(signal: CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, params: TParams & ComputedQueryParamsInput<TParams>, options?: UseSubOptions): SubResult<CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, TParams>;
103
+ /**
104
+ * Subscribe to a registered collection aggregation in React batch mode.
105
+ * @param signal Aggregation header generated by StartupJS model loading.
106
+ * @param params Parameters passed to the aggregation.
107
+ * @param options Subscription behavior options.
108
+ */
109
+ export declare function useBatchSub<TCollection extends string, TOutput = unknown>(signal: RegisteredAggregationInput<TCollection, TOutput>, params?: AggregationParams, options?: UseSubOptions): SubResult<RegisteredAggregationInput<TCollection, TOutput>>;
110
+ /**
111
+ * Subscribe to a client aggregation in React batch mode.
112
+ * @param signal Aggregation function created with `aggregation(collection, fn)`.
113
+ * @param params Parameters passed to the aggregation.
114
+ * @param options Subscription behavior options.
115
+ */
116
+ export declare function useBatchSub<TOutput, TCollection extends string>(signal: ClientAggregationFunction<TOutput, TCollection>, params?: AggregationParams, options?: UseSubOptions): SubResult<ClientAggregationFunction<TOutput, TCollection>>;
117
+ /**
118
+ * Subscribe to an aggregation with explicit output typing in React batch mode.
119
+ * @param signal Typed aggregation input.
120
+ * @param params Parameters passed to the aggregation.
121
+ * @param options Subscription behavior options.
122
+ */
123
+ export declare function useBatchSub<TDocument, TDocumentModel extends SignalModelConstructor<TDocument>>(signal: TypedAggregationInput<TDocument, TDocumentModel>, params?: AggregationParams, options?: UseSubOptions): TypedAggregationSignal<TDocument, TDocumentModel>;
124
+ /**
125
+ * Subscribe to an unregistered aggregation in React batch mode.
126
+ * @param signal Aggregation function.
127
+ * @param params Parameters passed to the aggregation.
128
+ * @param options Subscription behavior options.
129
+ */
130
+ export declare function useBatchSub<TOutput = unknown, TCollection extends string = string>(signal: AggregationFunction<TOutput, TCollection>, params?: AggregationParams, options?: UseSubOptions): SubResult<AggregationFunction<TOutput, TCollection>, AggregationParams | undefined>;
131
+ /**
132
+ * Close a batch subscription barrier opened by previous `useSub(..., { batch: true })`
133
+ * calls in this render.
134
+ */
135
+ export default function useSub(signal: undefined, params: undefined, options: UseSubOptions & {
136
+ batch: true;
137
+ }): void;
138
+ /**
139
+ * Subscribe to a document signal in React.
140
+ * @param signal Document signal to subscribe to.
141
+ * @param params Must be omitted for document subscriptions.
142
+ * @param options Subscription behavior options.
143
+ */
144
+ export default function useSub<TSignal extends DocumentSignal<any, any, any>>(signal: TSignal, options?: UseSubOptions): SubResult<TSignal>;
55
145
  /**
56
146
  * Subscribe to a document signal in React.
57
147
  * @param signal Document signal to subscribe to.
@@ -66,6 +156,15 @@ export default function useSub<TSignal extends DocumentSignal<any, any, any>>(si
66
156
  * @param options Subscription behavior options.
67
157
  */
68
158
  export default function useSub<TDocument, TCollectionModel extends SignalModelConstructor<TDocument[]>, TDocumentModel extends SignalModelConstructor<TDocument>, TCollectionPath extends WildcardSignalPath>(signal: CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, params: QueryParams<TDocument>, options?: UseSubOptions): SubResult<CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, QueryParams<TDocument>>;
159
+ /**
160
+ * Subscribe to a collection query with computed string keys in React.
161
+ * This fallback preserves Mongo-style computed paths such as `{ [`likes.${id}`]: true }`.
162
+ * Literal query objects should use the stricter overload above.
163
+ * @param signal Collection signal to query.
164
+ * @param params Mongo-style query params with a widened computed key.
165
+ * @param options Subscription behavior options.
166
+ */
167
+ export default function useSub<TDocument, TCollectionModel extends SignalModelConstructor<TDocument[]>, TDocumentModel extends SignalModelConstructor<TDocument>, TCollectionPath extends WildcardSignalPath, TParams extends object>(signal: CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, params: TParams & ComputedQueryParamsInput<TParams>, options?: UseSubOptions): SubResult<CollectionSignal<TDocument, TCollectionModel, TDocumentModel, TCollectionPath>, TParams>;
69
168
  /**
70
169
  * Subscribe to a registered collection aggregation in React.
71
170
  * @param signal Aggregation header generated by StartupJS model loading.
@@ -94,8 +193,8 @@ export default function useSub<TDocument, TDocumentModel extends SignalModelCons
94
193
  * @param options Subscription behavior options.
95
194
  */
96
195
  export default function useSub<TOutput = unknown, TCollection extends string = string>(signal: AggregationFunction<TOutput, TCollection>, params?: AggregationParams, options?: UseSubOptions): SubResult<AggregationFunction<TOutput, TCollection>, AggregationParams | undefined>;
97
- export declare function useSubDeferred(signal: unknown, params?: unknown, { async, defer, batch, compatAttemptCleanup }?: UseSubOptions): unknown;
98
- export declare function useSubClassic(signal: unknown, params?: unknown, { async, batch, compatAttemptCleanup }?: UseSubOptions): unknown;
196
+ export declare function useSubDeferred(signal: unknown, params?: unknown, { async, defer, batch }?: UseSubOptions): unknown;
197
+ export declare function useSubClassic(signal: unknown, params?: unknown, { async, batch }?: UseSubOptions): unknown;
99
198
  export declare function setTestThrottling(ms: number): void;
100
199
  export declare function resetTestThrottling(): void;
101
200
  export declare function setUseDeferredValue(value: boolean): void;