@constructive-io/sdk 0.20.6 → 0.20.8

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 (41) hide show
  1. package/admin/orm/client.d.ts +30 -0
  2. package/admin/orm/client.js +41 -1
  3. package/admin/orm/realtime.d.ts +142 -0
  4. package/admin/orm/realtime.js +104 -0
  5. package/auth/orm/client.d.ts +30 -0
  6. package/auth/orm/client.js +41 -1
  7. package/auth/orm/realtime.d.ts +142 -0
  8. package/auth/orm/realtime.js +104 -0
  9. package/esm/admin/orm/client.d.ts +30 -0
  10. package/esm/admin/orm/client.js +39 -0
  11. package/esm/admin/orm/realtime.d.ts +142 -0
  12. package/esm/admin/orm/realtime.js +100 -0
  13. package/esm/auth/orm/client.d.ts +30 -0
  14. package/esm/auth/orm/client.js +39 -0
  15. package/esm/auth/orm/realtime.d.ts +142 -0
  16. package/esm/auth/orm/realtime.js +100 -0
  17. package/esm/objects/orm/client.d.ts +30 -0
  18. package/esm/objects/orm/client.js +39 -0
  19. package/esm/objects/orm/realtime.d.ts +142 -0
  20. package/esm/objects/orm/realtime.js +100 -0
  21. package/esm/public/orm/client.d.ts +30 -0
  22. package/esm/public/orm/client.js +39 -0
  23. package/esm/public/orm/index.d.ts +8 -3
  24. package/esm/public/orm/input-types.d.ts +14 -3
  25. package/esm/public/orm/mutation/index.d.ts +14 -6
  26. package/esm/public/orm/mutation/index.js +18 -6
  27. package/esm/public/orm/realtime.d.ts +142 -0
  28. package/esm/public/orm/realtime.js +100 -0
  29. package/objects/orm/client.d.ts +30 -0
  30. package/objects/orm/client.js +41 -1
  31. package/objects/orm/realtime.d.ts +142 -0
  32. package/objects/orm/realtime.js +104 -0
  33. package/package.json +3 -3
  34. package/public/orm/client.d.ts +30 -0
  35. package/public/orm/client.js +41 -1
  36. package/public/orm/index.d.ts +8 -3
  37. package/public/orm/input-types.d.ts +14 -3
  38. package/public/orm/mutation/index.d.ts +14 -6
  39. package/public/orm/mutation/index.js +18 -6
  40. package/public/orm/realtime.d.ts +142 -0
  41. package/public/orm/realtime.js +104 -0
@@ -1,4 +1,6 @@
1
1
  import { createFetch } from '@constructive-io/graphql-query/runtime';
2
+ import { RealtimeManager } from './realtime';
3
+ export { RealtimeManager } from './realtime';
2
4
  /**
3
5
  * Default adapter that uses fetch for HTTP requests.
4
6
  *
@@ -73,6 +75,7 @@ export class GraphQLRequestError extends Error {
73
75
  }
74
76
  export class OrmClient {
75
77
  adapter;
78
+ realtimeManager;
76
79
  constructor(config) {
77
80
  if (config.adapter) {
78
81
  this.adapter = config.adapter;
@@ -83,10 +86,24 @@ export class OrmClient {
83
86
  else {
84
87
  throw new Error('OrmClientConfig requires either an endpoint or a custom adapter');
85
88
  }
89
+ if (config.realtime) {
90
+ this.realtimeManager = new RealtimeManager(config.realtime);
91
+ }
86
92
  }
87
93
  async execute(document, variables) {
88
94
  return this.adapter.execute(document, variables);
89
95
  }
96
+ /**
97
+ * Subscribe to a GraphQL subscription operation.
98
+ * Used by generated model subscribe() methods.
99
+ * @throws Error if realtime is not configured
100
+ */
101
+ subscribe(meta, document, variables, options) {
102
+ if (!this.realtimeManager) {
103
+ throw new Error('Realtime not configured. Pass a `realtime` option to createClient() to enable subscriptions.');
104
+ }
105
+ return this.realtimeManager.subscribe(meta, document, variables, options);
106
+ }
90
107
  /**
91
108
  * Set headers for requests.
92
109
  * Only works if the adapter supports headers.
@@ -103,4 +120,26 @@ export class OrmClient {
103
120
  getEndpoint() {
104
121
  return this.adapter.getEndpoint?.() ?? '';
105
122
  }
123
+ /** Get current WebSocket connection state */
124
+ getConnectionState() {
125
+ return this.realtimeManager?.getConnectionState() ?? 'disconnected';
126
+ }
127
+ /** Register a listener for WebSocket connection state changes */
128
+ onConnectionStateChange(listener) {
129
+ if (!this.realtimeManager)
130
+ return () => { };
131
+ return this.realtimeManager.onConnectionStateChange(listener);
132
+ }
133
+ /** Number of active subscriptions */
134
+ getActiveSubscriptionCount() {
135
+ return this.realtimeManager?.getActiveSubscriptionCount() ?? 0;
136
+ }
137
+ /** Whether realtime is configured */
138
+ get isRealtimeEnabled() {
139
+ return this.realtimeManager !== undefined;
140
+ }
141
+ /** Dispose the realtime manager (close WebSocket) */
142
+ dispose() {
143
+ this.realtimeManager?.dispose();
144
+ }
106
145
  }
@@ -569,10 +569,15 @@ export declare function createClient(config: OrmClientConfig): {
569
569
  } & import("./select-types").StrictSelect<S, import("./input-types").SetFieldOrderPayloadSelect>) => import("./query-builder").QueryBuilder<{
570
570
  setFieldOrder: import("./select-types").InferSelectResult<import("./input-types").SetFieldOrderPayload, S> | null;
571
571
  }>;
572
- appendSmartTags: <S extends import("./input-types").AppendSmartTagsPayloadSelect>(args: import("./mutation").AppendSmartTagsVariables, options: {
572
+ appendFieldSmartTags: <S extends import("./input-types").AppendFieldSmartTagsPayloadSelect>(args: import("./mutation").AppendFieldSmartTagsVariables, options: {
573
573
  select: S;
574
- } & import("./select-types").StrictSelect<S, import("./input-types").AppendSmartTagsPayloadSelect>) => import("./query-builder").QueryBuilder<{
575
- appendSmartTags: import("./select-types").InferSelectResult<import("./input-types").AppendSmartTagsPayload, S> | null;
574
+ } & import("./select-types").StrictSelect<S, import("./input-types").AppendFieldSmartTagsPayloadSelect>) => import("./query-builder").QueryBuilder<{
575
+ appendFieldSmartTags: import("./select-types").InferSelectResult<import("./input-types").AppendFieldSmartTagsPayload, S> | null;
576
+ }>;
577
+ appendTableSmartTags: <S extends import("./input-types").AppendTableSmartTagsPayloadSelect>(args: import("./mutation").AppendTableSmartTagsVariables, options: {
578
+ select: S;
579
+ } & import("./select-types").StrictSelect<S, import("./input-types").AppendTableSmartTagsPayloadSelect>) => import("./query-builder").QueryBuilder<{
580
+ appendTableSmartTags: import("./select-types").InferSelectResult<import("./input-types").AppendTableSmartTagsPayload, S> | null;
576
581
  }>;
577
582
  provisionUniqueConstraint: <S extends import("./input-types").ProvisionUniqueConstraintPayloadSelect>(args: import("./mutation").ProvisionUniqueConstraintVariables, options: {
578
583
  select: S;
@@ -19201,7 +19201,12 @@ export interface SetFieldOrderInput {
19201
19201
  clientMutationId?: string;
19202
19202
  fieldIds?: string[];
19203
19203
  }
19204
- export interface AppendSmartTagsInput {
19204
+ export interface AppendFieldSmartTagsInput {
19205
+ clientMutationId?: string;
19206
+ pFieldId?: string;
19207
+ pTags?: Record<string, unknown>;
19208
+ }
19209
+ export interface AppendTableSmartTagsInput {
19205
19210
  clientMutationId?: string;
19206
19211
  pTableId?: string;
19207
19212
  pTags?: Record<string, unknown>;
@@ -27717,10 +27722,16 @@ export interface SetFieldOrderPayload {
27717
27722
  export type SetFieldOrderPayloadSelect = {
27718
27723
  clientMutationId?: boolean;
27719
27724
  };
27720
- export interface AppendSmartTagsPayload {
27725
+ export interface AppendFieldSmartTagsPayload {
27726
+ clientMutationId?: string | null;
27727
+ }
27728
+ export type AppendFieldSmartTagsPayloadSelect = {
27729
+ clientMutationId?: boolean;
27730
+ };
27731
+ export interface AppendTableSmartTagsPayload {
27721
27732
  clientMutationId?: string | null;
27722
27733
  }
27723
- export type AppendSmartTagsPayloadSelect = {
27734
+ export type AppendTableSmartTagsPayloadSelect = {
27724
27735
  clientMutationId?: boolean;
27725
27736
  };
27726
27737
  export interface ProvisionUniqueConstraintPayload {
@@ -6,7 +6,7 @@
6
6
  import { OrmClient } from '../client';
7
7
  import { QueryBuilder } from '../query-builder';
8
8
  import type { InferSelectResult, StrictSelect } from '../select-types';
9
- import type { SendAccountDeletionEmailInput, SignOutInput, AcceptDatabaseTransferInput, CancelDatabaseTransferInput, RejectDatabaseTransferInput, DisconnectAccountInput, RevokeApiKeyInput, RevokeSessionInput, VerifyPasswordInput, VerifyTotpInput, SubmitAppInviteCodeInput, SubmitOrgInviteCodeInput, CheckPasswordInput, ConfirmDeleteAccountInput, SetPasswordInput, VerifyEmailInput, FreezeObjectsInput, InitEmptyRepoInput, ConstructBlueprintInput, ProvisionNewUserInput, ResetPasswordInput, RemoveNodeAtPathInput, CopyTemplateToBlueprintInput, ProvisionSpatialRelationInput, BootstrapUserInput, SetFieldOrderInput, AppendSmartTagsInput, ProvisionUniqueConstraintInput, ProvisionFullTextSearchInput, ProvisionIndexInput, SetDataAtPathInput, SetPropsAndCommitInput, ProvisionDatabaseWithUserInput, InsertNodeAtPathInput, UpdateNodeAtPathInput, SetAndCommitInput, ProvisionRelationInput, ApplyRlsInput, SignInCrossOriginInput, CreateUserDatabaseInput, ExtendTokenExpiresInput, CreateApiKeyInput, SendVerificationEmailInput, ForgotPasswordInput, SignUpInput, RequestCrossOriginTokenInput, SignInInput, ProvisionTableInput, ProvisionBucketInput, SendAccountDeletionEmailPayload, SignOutPayload, AcceptDatabaseTransferPayload, CancelDatabaseTransferPayload, RejectDatabaseTransferPayload, DisconnectAccountPayload, RevokeApiKeyPayload, RevokeSessionPayload, VerifyPasswordPayload, VerifyTotpPayload, SubmitAppInviteCodePayload, SubmitOrgInviteCodePayload, CheckPasswordPayload, ConfirmDeleteAccountPayload, SetPasswordPayload, VerifyEmailPayload, FreezeObjectsPayload, InitEmptyRepoPayload, ConstructBlueprintPayload, ProvisionNewUserPayload, ResetPasswordPayload, RemoveNodeAtPathPayload, CopyTemplateToBlueprintPayload, ProvisionSpatialRelationPayload, BootstrapUserPayload, SetFieldOrderPayload, AppendSmartTagsPayload, ProvisionUniqueConstraintPayload, ProvisionFullTextSearchPayload, ProvisionIndexPayload, SetDataAtPathPayload, SetPropsAndCommitPayload, ProvisionDatabaseWithUserPayload, InsertNodeAtPathPayload, UpdateNodeAtPathPayload, SetAndCommitPayload, ProvisionRelationPayload, ApplyRlsPayload, SignInCrossOriginPayload, CreateUserDatabasePayload, ExtendTokenExpiresPayload, CreateApiKeyPayload, SendVerificationEmailPayload, ForgotPasswordPayload, SignUpPayload, RequestCrossOriginTokenPayload, SignInPayload, ProvisionTablePayload, ProvisionBucketPayload, SendAccountDeletionEmailPayloadSelect, SignOutPayloadSelect, AcceptDatabaseTransferPayloadSelect, CancelDatabaseTransferPayloadSelect, RejectDatabaseTransferPayloadSelect, DisconnectAccountPayloadSelect, RevokeApiKeyPayloadSelect, RevokeSessionPayloadSelect, VerifyPasswordPayloadSelect, VerifyTotpPayloadSelect, SubmitAppInviteCodePayloadSelect, SubmitOrgInviteCodePayloadSelect, CheckPasswordPayloadSelect, ConfirmDeleteAccountPayloadSelect, SetPasswordPayloadSelect, VerifyEmailPayloadSelect, FreezeObjectsPayloadSelect, InitEmptyRepoPayloadSelect, ConstructBlueprintPayloadSelect, ProvisionNewUserPayloadSelect, ResetPasswordPayloadSelect, RemoveNodeAtPathPayloadSelect, CopyTemplateToBlueprintPayloadSelect, ProvisionSpatialRelationPayloadSelect, BootstrapUserPayloadSelect, SetFieldOrderPayloadSelect, AppendSmartTagsPayloadSelect, ProvisionUniqueConstraintPayloadSelect, ProvisionFullTextSearchPayloadSelect, ProvisionIndexPayloadSelect, SetDataAtPathPayloadSelect, SetPropsAndCommitPayloadSelect, ProvisionDatabaseWithUserPayloadSelect, InsertNodeAtPathPayloadSelect, UpdateNodeAtPathPayloadSelect, SetAndCommitPayloadSelect, ProvisionRelationPayloadSelect, ApplyRlsPayloadSelect, SignInCrossOriginPayloadSelect, CreateUserDatabasePayloadSelect, ExtendTokenExpiresPayloadSelect, CreateApiKeyPayloadSelect, SendVerificationEmailPayloadSelect, ForgotPasswordPayloadSelect, SignUpPayloadSelect, RequestCrossOriginTokenPayloadSelect, SignInPayloadSelect, ProvisionTablePayloadSelect, ProvisionBucketPayloadSelect } from '../input-types';
9
+ import type { SendAccountDeletionEmailInput, SignOutInput, AcceptDatabaseTransferInput, CancelDatabaseTransferInput, RejectDatabaseTransferInput, DisconnectAccountInput, RevokeApiKeyInput, RevokeSessionInput, VerifyPasswordInput, VerifyTotpInput, SubmitAppInviteCodeInput, SubmitOrgInviteCodeInput, CheckPasswordInput, ConfirmDeleteAccountInput, SetPasswordInput, VerifyEmailInput, FreezeObjectsInput, InitEmptyRepoInput, ConstructBlueprintInput, ProvisionNewUserInput, ResetPasswordInput, RemoveNodeAtPathInput, CopyTemplateToBlueprintInput, ProvisionSpatialRelationInput, BootstrapUserInput, SetFieldOrderInput, AppendFieldSmartTagsInput, AppendTableSmartTagsInput, ProvisionUniqueConstraintInput, ProvisionFullTextSearchInput, ProvisionIndexInput, SetDataAtPathInput, SetPropsAndCommitInput, ProvisionDatabaseWithUserInput, InsertNodeAtPathInput, UpdateNodeAtPathInput, SetAndCommitInput, ProvisionRelationInput, ApplyRlsInput, SignInCrossOriginInput, CreateUserDatabaseInput, ExtendTokenExpiresInput, CreateApiKeyInput, SendVerificationEmailInput, ForgotPasswordInput, SignUpInput, RequestCrossOriginTokenInput, SignInInput, ProvisionTableInput, ProvisionBucketInput, SendAccountDeletionEmailPayload, SignOutPayload, AcceptDatabaseTransferPayload, CancelDatabaseTransferPayload, RejectDatabaseTransferPayload, DisconnectAccountPayload, RevokeApiKeyPayload, RevokeSessionPayload, VerifyPasswordPayload, VerifyTotpPayload, SubmitAppInviteCodePayload, SubmitOrgInviteCodePayload, CheckPasswordPayload, ConfirmDeleteAccountPayload, SetPasswordPayload, VerifyEmailPayload, FreezeObjectsPayload, InitEmptyRepoPayload, ConstructBlueprintPayload, ProvisionNewUserPayload, ResetPasswordPayload, RemoveNodeAtPathPayload, CopyTemplateToBlueprintPayload, ProvisionSpatialRelationPayload, BootstrapUserPayload, SetFieldOrderPayload, AppendFieldSmartTagsPayload, AppendTableSmartTagsPayload, ProvisionUniqueConstraintPayload, ProvisionFullTextSearchPayload, ProvisionIndexPayload, SetDataAtPathPayload, SetPropsAndCommitPayload, ProvisionDatabaseWithUserPayload, InsertNodeAtPathPayload, UpdateNodeAtPathPayload, SetAndCommitPayload, ProvisionRelationPayload, ApplyRlsPayload, SignInCrossOriginPayload, CreateUserDatabasePayload, ExtendTokenExpiresPayload, CreateApiKeyPayload, SendVerificationEmailPayload, ForgotPasswordPayload, SignUpPayload, RequestCrossOriginTokenPayload, SignInPayload, ProvisionTablePayload, ProvisionBucketPayload, SendAccountDeletionEmailPayloadSelect, SignOutPayloadSelect, AcceptDatabaseTransferPayloadSelect, CancelDatabaseTransferPayloadSelect, RejectDatabaseTransferPayloadSelect, DisconnectAccountPayloadSelect, RevokeApiKeyPayloadSelect, RevokeSessionPayloadSelect, VerifyPasswordPayloadSelect, VerifyTotpPayloadSelect, SubmitAppInviteCodePayloadSelect, SubmitOrgInviteCodePayloadSelect, CheckPasswordPayloadSelect, ConfirmDeleteAccountPayloadSelect, SetPasswordPayloadSelect, VerifyEmailPayloadSelect, FreezeObjectsPayloadSelect, InitEmptyRepoPayloadSelect, ConstructBlueprintPayloadSelect, ProvisionNewUserPayloadSelect, ResetPasswordPayloadSelect, RemoveNodeAtPathPayloadSelect, CopyTemplateToBlueprintPayloadSelect, ProvisionSpatialRelationPayloadSelect, BootstrapUserPayloadSelect, SetFieldOrderPayloadSelect, AppendFieldSmartTagsPayloadSelect, AppendTableSmartTagsPayloadSelect, ProvisionUniqueConstraintPayloadSelect, ProvisionFullTextSearchPayloadSelect, ProvisionIndexPayloadSelect, SetDataAtPathPayloadSelect, SetPropsAndCommitPayloadSelect, ProvisionDatabaseWithUserPayloadSelect, InsertNodeAtPathPayloadSelect, UpdateNodeAtPathPayloadSelect, SetAndCommitPayloadSelect, ProvisionRelationPayloadSelect, ApplyRlsPayloadSelect, SignInCrossOriginPayloadSelect, CreateUserDatabasePayloadSelect, ExtendTokenExpiresPayloadSelect, CreateApiKeyPayloadSelect, SendVerificationEmailPayloadSelect, ForgotPasswordPayloadSelect, SignUpPayloadSelect, RequestCrossOriginTokenPayloadSelect, SignInPayloadSelect, ProvisionTablePayloadSelect, ProvisionBucketPayloadSelect } from '../input-types';
10
10
  export interface SendAccountDeletionEmailVariables {
11
11
  input: SendAccountDeletionEmailInput;
12
12
  }
@@ -97,8 +97,11 @@ export interface BootstrapUserVariables {
97
97
  export interface SetFieldOrderVariables {
98
98
  input: SetFieldOrderInput;
99
99
  }
100
- export interface AppendSmartTagsVariables {
101
- input: AppendSmartTagsInput;
100
+ export interface AppendFieldSmartTagsVariables {
101
+ input: AppendFieldSmartTagsInput;
102
+ }
103
+ export interface AppendTableSmartTagsVariables {
104
+ input: AppendTableSmartTagsInput;
102
105
  }
103
106
  /**
104
107
  * Variables for provisionUniqueConstraint
@@ -343,10 +346,15 @@ export declare function createMutationOperations(client: OrmClient): {
343
346
  } & StrictSelect<S, SetFieldOrderPayloadSelect>) => QueryBuilder<{
344
347
  setFieldOrder: InferSelectResult<SetFieldOrderPayload, S> | null;
345
348
  }>;
346
- appendSmartTags: <S extends AppendSmartTagsPayloadSelect>(args: AppendSmartTagsVariables, options: {
349
+ appendFieldSmartTags: <S extends AppendFieldSmartTagsPayloadSelect>(args: AppendFieldSmartTagsVariables, options: {
350
+ select: S;
351
+ } & StrictSelect<S, AppendFieldSmartTagsPayloadSelect>) => QueryBuilder<{
352
+ appendFieldSmartTags: InferSelectResult<AppendFieldSmartTagsPayload, S> | null;
353
+ }>;
354
+ appendTableSmartTags: <S extends AppendTableSmartTagsPayloadSelect>(args: AppendTableSmartTagsVariables, options: {
347
355
  select: S;
348
- } & StrictSelect<S, AppendSmartTagsPayloadSelect>) => QueryBuilder<{
349
- appendSmartTags: InferSelectResult<AppendSmartTagsPayload, S> | null;
356
+ } & StrictSelect<S, AppendTableSmartTagsPayloadSelect>) => QueryBuilder<{
357
+ appendTableSmartTags: InferSelectResult<AppendTableSmartTagsPayload, S> | null;
350
358
  }>;
351
359
  provisionUniqueConstraint: <S extends ProvisionUniqueConstraintPayloadSelect>(args: ProvisionUniqueConstraintVariables, options: {
352
360
  select: S;
@@ -314,17 +314,29 @@ export function createMutationOperations(client) {
314
314
  },
315
315
  ], connectionFieldsMap, 'SetFieldOrderPayload'),
316
316
  }),
317
- appendSmartTags: (args, options) => new QueryBuilder({
317
+ appendFieldSmartTags: (args, options) => new QueryBuilder({
318
318
  client,
319
319
  operation: 'mutation',
320
- operationName: 'AppendSmartTags',
321
- fieldName: 'appendSmartTags',
322
- ...buildCustomDocument('mutation', 'AppendSmartTags', 'appendSmartTags', options.select, args, [
320
+ operationName: 'AppendFieldSmartTags',
321
+ fieldName: 'appendFieldSmartTags',
322
+ ...buildCustomDocument('mutation', 'AppendFieldSmartTags', 'appendFieldSmartTags', options.select, args, [
323
323
  {
324
324
  name: 'input',
325
- type: 'AppendSmartTagsInput!',
325
+ type: 'AppendFieldSmartTagsInput!',
326
326
  },
327
- ], connectionFieldsMap, 'AppendSmartTagsPayload'),
327
+ ], connectionFieldsMap, 'AppendFieldSmartTagsPayload'),
328
+ }),
329
+ appendTableSmartTags: (args, options) => new QueryBuilder({
330
+ client,
331
+ operation: 'mutation',
332
+ operationName: 'AppendTableSmartTags',
333
+ fieldName: 'appendTableSmartTags',
334
+ ...buildCustomDocument('mutation', 'AppendTableSmartTags', 'appendTableSmartTags', options.select, args, [
335
+ {
336
+ name: 'input',
337
+ type: 'AppendTableSmartTagsInput!',
338
+ },
339
+ ], connectionFieldsMap, 'AppendTableSmartTagsPayload'),
328
340
  }),
329
341
  provisionUniqueConstraint: (args, options) => new QueryBuilder({
330
342
  client,
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Realtime Manager - WebSocket subscription support
3
+ * @generated by @constructive-io/graphql-codegen
4
+ * DO NOT EDIT - changes will be overwritten
5
+ */
6
+ interface WsGraphQLError {
7
+ readonly message: string;
8
+ readonly [key: string]: unknown;
9
+ }
10
+ interface WsExecutionResult<TData = Record<string, unknown>> {
11
+ data?: TData | null;
12
+ errors?: readonly WsGraphQLError[];
13
+ extensions?: Record<string, unknown>;
14
+ }
15
+ interface WsSink<T> {
16
+ next(value: T): void;
17
+ error(error: unknown): void;
18
+ complete(): void;
19
+ }
20
+ /**
21
+ * Minimal interface matching the graphql-ws Client.
22
+ * Consumers pass a concrete instance via RealtimeConfig.client.
23
+ */
24
+ export interface WsClient {
25
+ subscribe<TData = Record<string, unknown>>(payload: {
26
+ query: string;
27
+ variables?: Record<string, unknown>;
28
+ }, sink: WsSink<WsExecutionResult<TData>>): () => void;
29
+ dispose(): void;
30
+ }
31
+ /** The DML operation that triggered the subscription event */
32
+ export type SubscriptionOperation = 'INSERT' | 'UPDATE' | 'DELETE';
33
+ /** Connection state of the WebSocket */
34
+ export type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
35
+ /** Listener for connection state changes */
36
+ export type ConnectionStateListener = (state: ConnectionState) => void;
37
+ /** Function returned by subscribe() to cancel the subscription */
38
+ export type Unsubscribe = () => void;
39
+ /**
40
+ * A realtime subscription event delivered to the client.
41
+ *
42
+ * @typeParam T - The row type of the subscribed table
43
+ */
44
+ export interface SubscriptionEvent<T> {
45
+ /** The DML operation that triggered this event */
46
+ operation: SubscriptionOperation;
47
+ /** The current row data (null for DELETE if row is no longer visible) */
48
+ data: T | null;
49
+ /** Previous field values (populated on UPDATE when available) */
50
+ previousValues?: Partial<T>;
51
+ /** Server-side timestamp of when the change occurred */
52
+ timestamp: string;
53
+ }
54
+ /**
55
+ * Options for creating a subscription.
56
+ *
57
+ * @typeParam T - The row type of the subscribed table
58
+ * @typeParam TFilter - The filter type for the table
59
+ */
60
+ export interface SubscribeOptions<T, TFilter = Record<string, unknown>> {
61
+ /** Server-side filter to limit which events are delivered */
62
+ filter?: TFilter;
63
+ /** Called when a subscription event is received */
64
+ onEvent: (event: SubscriptionEvent<T>) => void;
65
+ /** Called when the subscription encounters an error */
66
+ onError?: (error: Error) => void;
67
+ /** Called when the subscription completes (server-initiated close) */
68
+ onComplete?: () => void;
69
+ }
70
+ /**
71
+ * Metadata about a subscription field, used internally to map
72
+ * table names to GraphQL subscription field names and types.
73
+ */
74
+ export interface SubscriptionFieldMeta {
75
+ /** The GraphQL subscription field name (e.g., 'onContactChanged') */
76
+ fieldName: string;
77
+ /** The table name in the source schema (e.g., 'contact') */
78
+ tableName: string;
79
+ /** The data field name inside the subscription payload (e.g., 'contact') */
80
+ dataFieldName: string;
81
+ }
82
+ /**
83
+ * Configuration for the realtime (WebSocket) connection.
84
+ * Pass this as the `realtime` option in OrmClientConfig.
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * import { createClient } from 'graphql-ws';
89
+ *
90
+ * const client = createOrmClient({
91
+ * endpoint: 'https://api.example.com/graphql',
92
+ * realtime: {
93
+ * client: createClient({ url: 'wss://api.example.com/graphql' }),
94
+ * },
95
+ * });
96
+ * ```
97
+ */
98
+ export interface RealtimeConfig {
99
+ /**
100
+ * A graphql-ws Client instance (or any object satisfying WsClient).
101
+ * The consumer creates this themselves, giving full control over
102
+ * connection options, auth, and transport.
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * import { createClient } from 'graphql-ws';
107
+ * const wsClient = createClient({ url: 'wss://...' });
108
+ * ```
109
+ */
110
+ client: WsClient;
111
+ }
112
+ /**
113
+ * Manages a graphql-ws WebSocket client and multiplexes
114
+ * subscriptions over it. Created by OrmClient when `realtime`
115
+ * config is provided.
116
+ */
117
+ export declare class RealtimeManager {
118
+ private wsClient;
119
+ private connectionState;
120
+ private stateListeners;
121
+ private activeSubscriptions;
122
+ constructor(config: RealtimeConfig);
123
+ /**
124
+ * Subscribe to a GraphQL subscription operation.
125
+ * Models call this with typed metadata and documents.
126
+ */
127
+ subscribe<T>(meta: SubscriptionFieldMeta, document: string, variables: Record<string, unknown>, options: {
128
+ onEvent: (event: SubscriptionEvent<T>) => void;
129
+ onError?: (error: Error) => void;
130
+ onComplete?: () => void;
131
+ }): Unsubscribe;
132
+ /** Register a listener for connection state changes */
133
+ onConnectionStateChange(listener: ConnectionStateListener): Unsubscribe;
134
+ /** Get current connection state */
135
+ getConnectionState(): ConnectionState;
136
+ /** Number of active subscriptions */
137
+ getActiveSubscriptionCount(): number;
138
+ /** Dispose the manager and close the WebSocket connection */
139
+ dispose(): void;
140
+ private setConnectionState;
141
+ }
142
+ export {};
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Realtime Manager - WebSocket subscription support
3
+ * @generated by @constructive-io/graphql-codegen
4
+ * DO NOT EDIT - changes will be overwritten
5
+ */
6
+ // Minimal type shims so this module compiles without graphql-ws
7
+ // installed. Consumers supply a WsClient via RealtimeConfig;
8
+ // the SDK itself never imports or requires graphql-ws.
9
+ // ============================================================================
10
+ // RealtimeManager
11
+ // ============================================================================
12
+ /**
13
+ * Manages a graphql-ws WebSocket client and multiplexes
14
+ * subscriptions over it. Created by OrmClient when `realtime`
15
+ * config is provided.
16
+ */
17
+ export class RealtimeManager {
18
+ wsClient;
19
+ connectionState = 'disconnected';
20
+ stateListeners = new Set();
21
+ activeSubscriptions = 0;
22
+ constructor(config) {
23
+ this.wsClient = config.client;
24
+ }
25
+ /**
26
+ * Subscribe to a GraphQL subscription operation.
27
+ * Models call this with typed metadata and documents.
28
+ */
29
+ subscribe(meta, document, variables, options) {
30
+ this.activeSubscriptions++;
31
+ let disposed = false;
32
+ const cleanup = this.wsClient.subscribe({ query: document, variables }, {
33
+ next: (result) => {
34
+ if (disposed)
35
+ return;
36
+ if (result.errors) {
37
+ options.onError?.(new Error(result.errors.map((e) => e.message).join('; ')));
38
+ return;
39
+ }
40
+ const payload = result.data?.[meta.fieldName];
41
+ if (!payload)
42
+ return;
43
+ const event = {
44
+ operation: payload.event ?? 'UPDATE',
45
+ data: payload[meta.dataFieldName] ?? null,
46
+ previousValues: payload.previousValues,
47
+ timestamp: payload.timestamp ?? new Date().toISOString(),
48
+ };
49
+ options.onEvent(event);
50
+ },
51
+ error: (err) => {
52
+ if (disposed)
53
+ return;
54
+ options.onError?.(err instanceof Error ? err : new Error(String(err)));
55
+ },
56
+ complete: () => {
57
+ if (disposed)
58
+ return;
59
+ options.onComplete?.();
60
+ },
61
+ });
62
+ return () => {
63
+ if (disposed)
64
+ return;
65
+ disposed = true;
66
+ this.activeSubscriptions--;
67
+ cleanup();
68
+ };
69
+ }
70
+ /** Register a listener for connection state changes */
71
+ onConnectionStateChange(listener) {
72
+ this.stateListeners.add(listener);
73
+ return () => {
74
+ this.stateListeners.delete(listener);
75
+ };
76
+ }
77
+ /** Get current connection state */
78
+ getConnectionState() {
79
+ return this.connectionState;
80
+ }
81
+ /** Number of active subscriptions */
82
+ getActiveSubscriptionCount() {
83
+ return this.activeSubscriptions;
84
+ }
85
+ /** Dispose the manager and close the WebSocket connection */
86
+ dispose() {
87
+ this.wsClient.dispose();
88
+ this.stateListeners.clear();
89
+ this.activeSubscriptions = 0;
90
+ this.setConnectionState('disconnected');
91
+ }
92
+ setConnectionState(state) {
93
+ if (this.connectionState === state)
94
+ return;
95
+ this.connectionState = state;
96
+ for (const listener of this.stateListeners) {
97
+ listener(state);
98
+ }
99
+ }
100
+ }
@@ -4,7 +4,10 @@
4
4
  * DO NOT EDIT - changes will be overwritten
5
5
  */
6
6
  import type { GraphQLAdapter, GraphQLError, QueryResult } from '@constructive-io/graphql-query/runtime';
7
+ import type { ConnectionState, ConnectionStateListener, RealtimeConfig, SubscriptionEvent, SubscriptionFieldMeta, Unsubscribe } from './realtime';
7
8
  export type { GraphQLAdapter, GraphQLError, QueryResult, } from '@constructive-io/graphql-query/runtime';
9
+ export type { ConnectionState, ConnectionStateListener, RealtimeConfig, SubscribeOptions, SubscriptionEvent, SubscriptionFieldMeta, SubscriptionOperation, Unsubscribe, WsClient, } from './realtime';
10
+ export { RealtimeManager } from './realtime';
8
11
  /**
9
12
  * Default adapter that uses fetch for HTTP requests.
10
13
  *
@@ -41,6 +44,12 @@ export interface OrmClientConfig {
41
44
  fetch?: typeof globalThis.fetch;
42
45
  /** Custom adapter for GraphQL execution (overrides endpoint/headers/fetch) */
43
46
  adapter?: GraphQLAdapter;
47
+ /**
48
+ * Optional realtime (WebSocket) configuration.
49
+ * When provided, enables subscription methods on models.
50
+ * The WebSocket connection is created lazily on first subscribe().
51
+ */
52
+ realtime?: RealtimeConfig;
44
53
  }
45
54
  /**
46
55
  * Error thrown when GraphQL request fails
@@ -52,8 +61,19 @@ export declare class GraphQLRequestError extends Error {
52
61
  }
53
62
  export declare class OrmClient {
54
63
  private adapter;
64
+ private realtimeManager?;
55
65
  constructor(config: OrmClientConfig);
56
66
  execute<T>(document: string, variables?: Record<string, unknown>): Promise<QueryResult<T>>;
67
+ /**
68
+ * Subscribe to a GraphQL subscription operation.
69
+ * Used by generated model subscribe() methods.
70
+ * @throws Error if realtime is not configured
71
+ */
72
+ subscribe<T>(meta: SubscriptionFieldMeta, document: string, variables: Record<string, unknown>, options: {
73
+ onEvent: (event: SubscriptionEvent<T>) => void;
74
+ onError?: (error: Error) => void;
75
+ onComplete?: () => void;
76
+ }): Unsubscribe;
57
77
  /**
58
78
  * Set headers for requests.
59
79
  * Only works if the adapter supports headers.
@@ -64,4 +84,14 @@ export declare class OrmClient {
64
84
  * Returns empty string if the adapter doesn't have an endpoint.
65
85
  */
66
86
  getEndpoint(): string;
87
+ /** Get current WebSocket connection state */
88
+ getConnectionState(): ConnectionState;
89
+ /** Register a listener for WebSocket connection state changes */
90
+ onConnectionStateChange(listener: ConnectionStateListener): Unsubscribe;
91
+ /** Number of active subscriptions */
92
+ getActiveSubscriptionCount(): number;
93
+ /** Whether realtime is configured */
94
+ get isRealtimeEnabled(): boolean;
95
+ /** Dispose the realtime manager (close WebSocket) */
96
+ dispose(): void;
67
97
  }
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OrmClient = exports.GraphQLRequestError = exports.FetchAdapter = void 0;
3
+ exports.OrmClient = exports.GraphQLRequestError = exports.FetchAdapter = exports.RealtimeManager = void 0;
4
4
  const runtime_1 = require("@constructive-io/graphql-query/runtime");
5
+ const realtime_1 = require("./realtime");
6
+ var realtime_2 = require("./realtime");
7
+ Object.defineProperty(exports, "RealtimeManager", { enumerable: true, get: function () { return realtime_2.RealtimeManager; } });
5
8
  /**
6
9
  * Default adapter that uses fetch for HTTP requests.
7
10
  *
@@ -78,6 +81,7 @@ class GraphQLRequestError extends Error {
78
81
  exports.GraphQLRequestError = GraphQLRequestError;
79
82
  class OrmClient {
80
83
  adapter;
84
+ realtimeManager;
81
85
  constructor(config) {
82
86
  if (config.adapter) {
83
87
  this.adapter = config.adapter;
@@ -88,10 +92,24 @@ class OrmClient {
88
92
  else {
89
93
  throw new Error('OrmClientConfig requires either an endpoint or a custom adapter');
90
94
  }
95
+ if (config.realtime) {
96
+ this.realtimeManager = new realtime_1.RealtimeManager(config.realtime);
97
+ }
91
98
  }
92
99
  async execute(document, variables) {
93
100
  return this.adapter.execute(document, variables);
94
101
  }
102
+ /**
103
+ * Subscribe to a GraphQL subscription operation.
104
+ * Used by generated model subscribe() methods.
105
+ * @throws Error if realtime is not configured
106
+ */
107
+ subscribe(meta, document, variables, options) {
108
+ if (!this.realtimeManager) {
109
+ throw new Error('Realtime not configured. Pass a `realtime` option to createClient() to enable subscriptions.');
110
+ }
111
+ return this.realtimeManager.subscribe(meta, document, variables, options);
112
+ }
95
113
  /**
96
114
  * Set headers for requests.
97
115
  * Only works if the adapter supports headers.
@@ -108,5 +126,27 @@ class OrmClient {
108
126
  getEndpoint() {
109
127
  return this.adapter.getEndpoint?.() ?? '';
110
128
  }
129
+ /** Get current WebSocket connection state */
130
+ getConnectionState() {
131
+ return this.realtimeManager?.getConnectionState() ?? 'disconnected';
132
+ }
133
+ /** Register a listener for WebSocket connection state changes */
134
+ onConnectionStateChange(listener) {
135
+ if (!this.realtimeManager)
136
+ return () => { };
137
+ return this.realtimeManager.onConnectionStateChange(listener);
138
+ }
139
+ /** Number of active subscriptions */
140
+ getActiveSubscriptionCount() {
141
+ return this.realtimeManager?.getActiveSubscriptionCount() ?? 0;
142
+ }
143
+ /** Whether realtime is configured */
144
+ get isRealtimeEnabled() {
145
+ return this.realtimeManager !== undefined;
146
+ }
147
+ /** Dispose the realtime manager (close WebSocket) */
148
+ dispose() {
149
+ this.realtimeManager?.dispose();
150
+ }
111
151
  }
112
152
  exports.OrmClient = OrmClient;