@constructive-io/graphql-codegen 4.38.1 → 4.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/codegen/barrel.d.ts +6 -0
- package/core/codegen/barrel.js +26 -1
- package/core/codegen/index.d.ts +3 -1
- package/core/codegen/index.js +33 -1
- package/core/codegen/orm/client-generator.d.ts +6 -0
- package/core/codegen/orm/client-generator.js +12 -0
- package/core/codegen/orm/client.d.ts +43 -0
- package/core/codegen/orm/client.js +16 -0
- package/core/codegen/orm/index.d.ts +1 -1
- package/core/codegen/orm/index.js +5 -2
- package/core/codegen/subscriptions.d.ts +30 -0
- package/core/codegen/subscriptions.js +270 -0
- package/core/codegen/templates/orm-client.ts +90 -0
- package/core/codegen/templates/orm-realtime.ts +295 -0
- package/core/codegen/utils.d.ts +15 -0
- package/core/codegen/utils.js +26 -0
- package/esm/core/codegen/barrel.d.ts +6 -0
- package/esm/core/codegen/barrel.js +26 -2
- package/esm/core/codegen/index.d.ts +3 -1
- package/esm/core/codegen/index.js +30 -2
- package/esm/core/codegen/orm/client-generator.d.ts +6 -0
- package/esm/core/codegen/orm/client-generator.js +11 -0
- package/esm/core/codegen/orm/client.d.ts +43 -0
- package/esm/core/codegen/orm/client.js +16 -0
- package/esm/core/codegen/orm/index.d.ts +1 -1
- package/esm/core/codegen/orm/index.js +5 -3
- package/esm/core/codegen/subscriptions.d.ts +30 -0
- package/esm/core/codegen/subscriptions.js +232 -0
- package/esm/core/codegen/utils.d.ts +15 -0
- package/esm/core/codegen/utils.js +23 -0
- package/esm/types/schema.d.ts +2 -0
- package/package.json +4 -4
- package/types/schema.d.ts +2 -0
package/core/codegen/barrel.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export declare function generateMutationsBarrel(tables: Table[]): string;
|
|
|
15
15
|
*/
|
|
16
16
|
export interface MainBarrelOptions {
|
|
17
17
|
hasMutations?: boolean;
|
|
18
|
+
/** Whether subscriptions/ directory was generated */
|
|
19
|
+
hasSubscriptions?: boolean;
|
|
18
20
|
/** Whether query-keys.ts was generated */
|
|
19
21
|
hasQueryKeys?: boolean;
|
|
20
22
|
/** Whether mutation-keys.ts was generated */
|
|
@@ -44,6 +46,10 @@ export declare function generateRootBarrel(options?: RootBarrelOptions): string;
|
|
|
44
46
|
* export * as public_ from './public';
|
|
45
47
|
*/
|
|
46
48
|
export declare function generateMultiTargetBarrel(targetNames: string[]): string;
|
|
49
|
+
/**
|
|
50
|
+
* Generate the subscriptions/index.ts barrel file
|
|
51
|
+
*/
|
|
52
|
+
export declare function generateSubscriptionsBarrel(tables: Table[]): string;
|
|
47
53
|
/**
|
|
48
54
|
* Generate queries barrel including custom query operations
|
|
49
55
|
*/
|
package/core/codegen/barrel.js
CHANGED
|
@@ -38,6 +38,7 @@ exports.generateMutationsBarrel = generateMutationsBarrel;
|
|
|
38
38
|
exports.generateMainBarrel = generateMainBarrel;
|
|
39
39
|
exports.generateRootBarrel = generateRootBarrel;
|
|
40
40
|
exports.generateMultiTargetBarrel = generateMultiTargetBarrel;
|
|
41
|
+
exports.generateSubscriptionsBarrel = generateSubscriptionsBarrel;
|
|
41
42
|
exports.generateCustomQueriesBarrel = generateCustomQueriesBarrel;
|
|
42
43
|
exports.generateCustomMutationsBarrel = generateCustomMutationsBarrel;
|
|
43
44
|
/**
|
|
@@ -111,7 +112,7 @@ function generateMutationsBarrel(tables) {
|
|
|
111
112
|
}
|
|
112
113
|
function generateMainBarrel(tables, options = {}) {
|
|
113
114
|
const opts = options;
|
|
114
|
-
const { hasMutations = true, hasQueryKeys = false, hasMutationKeys = false, hasInvalidation = false, } = opts;
|
|
115
|
+
const { hasMutations = true, hasSubscriptions = false, hasQueryKeys = false, hasMutationKeys = false, hasInvalidation = false, } = opts;
|
|
115
116
|
const tableNames = tables.map((tbl) => tbl.name).join(', ');
|
|
116
117
|
const statements = [];
|
|
117
118
|
// Client configuration (ORM wrapper with configure/getClient)
|
|
@@ -134,6 +135,10 @@ function generateMainBarrel(tables, options = {}) {
|
|
|
134
135
|
if (hasMutations) {
|
|
135
136
|
statements.push(exportAllFrom('./mutations'));
|
|
136
137
|
}
|
|
138
|
+
// Subscription hooks
|
|
139
|
+
if (hasSubscriptions) {
|
|
140
|
+
statements.push(exportAllFrom('./subscriptions'));
|
|
141
|
+
}
|
|
137
142
|
// Add file header as leading comment on first statement
|
|
138
143
|
if (statements.length > 0) {
|
|
139
144
|
(0, babel_ast_1.addJSDocComment)(statements[0], [
|
|
@@ -243,6 +248,26 @@ function generateMultiTargetBarrel(targetNames) {
|
|
|
243
248
|
}
|
|
244
249
|
return (0, babel_ast_1.generateCode)(statements);
|
|
245
250
|
}
|
|
251
|
+
/**
|
|
252
|
+
* Generate the subscriptions/index.ts barrel file
|
|
253
|
+
*/
|
|
254
|
+
function generateSubscriptionsBarrel(tables) {
|
|
255
|
+
const statements = [];
|
|
256
|
+
for (const table of tables) {
|
|
257
|
+
const hookName = (0, utils_1.getSubscriptionHookName)(table);
|
|
258
|
+
statements.push(exportAllFrom(`./${hookName}`));
|
|
259
|
+
}
|
|
260
|
+
// Connection state hook
|
|
261
|
+
statements.push(exportAllFrom('./useConnectionState'));
|
|
262
|
+
if (statements.length > 0) {
|
|
263
|
+
(0, babel_ast_1.addJSDocComment)(statements[0], [
|
|
264
|
+
'Subscription hooks barrel export',
|
|
265
|
+
'@generated by @constructive-io/graphql-codegen',
|
|
266
|
+
'DO NOT EDIT - changes will be overwritten',
|
|
267
|
+
]);
|
|
268
|
+
}
|
|
269
|
+
return (0, babel_ast_1.generateCode)(statements);
|
|
270
|
+
}
|
|
246
271
|
// ============================================================================
|
|
247
272
|
// Custom operation barrels (includes both table and custom hooks)
|
|
248
273
|
// ============================================================================
|
package/core/codegen/index.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ export interface GenerateResult {
|
|
|
36
36
|
tables: number;
|
|
37
37
|
queryHooks: number;
|
|
38
38
|
mutationHooks: number;
|
|
39
|
+
subscriptionHooks: number;
|
|
39
40
|
customQueryHooks: number;
|
|
40
41
|
customMutationHooks: number;
|
|
41
42
|
totalFiles: number;
|
|
@@ -71,7 +72,7 @@ export declare function generateAllFiles(tables: Table[], config: GraphQLSDKConf
|
|
|
71
72
|
* (they're expected to exist in the shared types directory).
|
|
72
73
|
*/
|
|
73
74
|
export declare function generate(options: GenerateOptions): GenerateResult;
|
|
74
|
-
export { generateCustomMutationsBarrel, generateCustomQueriesBarrel, generateMainBarrel, generateMutationsBarrel, generateQueriesBarrel, } from './barrel';
|
|
75
|
+
export { generateCustomMutationsBarrel, generateCustomQueriesBarrel, generateMainBarrel, generateMutationsBarrel, generateQueriesBarrel, generateSubscriptionsBarrel, } from './barrel';
|
|
75
76
|
export { generateClientFile } from './client';
|
|
76
77
|
export { generateAllCustomMutationHooks, generateCustomMutationHook, } from './custom-mutations';
|
|
77
78
|
export { generateAllCustomQueryHooks, generateCustomQueryHook, } from './custom-queries';
|
|
@@ -80,3 +81,4 @@ export { generateMutationKeysFile } from './mutation-keys';
|
|
|
80
81
|
export { generateAllMutationHooks, generateCreateMutationHook, generateDeleteMutationHook, generateUpdateMutationHook, } from './mutations';
|
|
81
82
|
export { generateAllQueryHooks, generateListQueryHook, generateSingleQueryHook, } from './queries';
|
|
82
83
|
export { generateQueryKeysFile } from './query-keys';
|
|
84
|
+
export { generateAllSubscriptionHooks, generateConnectionStateHook, generateSubscriptionHook, } from './subscriptions';
|
package/core/codegen/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateQueryKeysFile = exports.generateSingleQueryHook = exports.generateListQueryHook = exports.generateAllQueryHooks = exports.generateUpdateMutationHook = exports.generateDeleteMutationHook = exports.generateCreateMutationHook = exports.generateAllMutationHooks = exports.generateMutationKeysFile = exports.generateInvalidationFile = exports.generateCustomQueryHook = exports.generateAllCustomQueryHooks = exports.generateCustomMutationHook = exports.generateAllCustomMutationHooks = exports.generateClientFile = exports.generateQueriesBarrel = exports.generateMutationsBarrel = exports.generateMainBarrel = exports.generateCustomQueriesBarrel = exports.generateCustomMutationsBarrel = void 0;
|
|
3
|
+
exports.generateSubscriptionHook = exports.generateConnectionStateHook = exports.generateAllSubscriptionHooks = exports.generateQueryKeysFile = exports.generateSingleQueryHook = exports.generateListQueryHook = exports.generateAllQueryHooks = exports.generateUpdateMutationHook = exports.generateDeleteMutationHook = exports.generateCreateMutationHook = exports.generateAllMutationHooks = exports.generateMutationKeysFile = exports.generateInvalidationFile = exports.generateCustomQueryHook = exports.generateAllCustomQueryHooks = exports.generateCustomMutationHook = exports.generateAllCustomMutationHooks = exports.generateClientFile = exports.generateSubscriptionsBarrel = exports.generateQueriesBarrel = exports.generateMutationsBarrel = exports.generateMainBarrel = exports.generateCustomQueriesBarrel = exports.generateCustomMutationsBarrel = void 0;
|
|
4
4
|
exports.generateAllFiles = generateAllFiles;
|
|
5
5
|
exports.generate = generate;
|
|
6
6
|
const config_1 = require("../../types/config");
|
|
@@ -13,6 +13,7 @@ const mutation_keys_1 = require("./mutation-keys");
|
|
|
13
13
|
const mutations_1 = require("./mutations");
|
|
14
14
|
const queries_1 = require("./queries");
|
|
15
15
|
const query_keys_1 = require("./query-keys");
|
|
16
|
+
const subscriptions_1 = require("./subscriptions");
|
|
16
17
|
const selection_1 = require("./selection");
|
|
17
18
|
const utils_1 = require("./utils");
|
|
18
19
|
// ============================================================================
|
|
@@ -173,12 +174,37 @@ function generate(options) {
|
|
|
173
174
|
: (0, barrel_1.generateMutationsBarrel)(tables),
|
|
174
175
|
});
|
|
175
176
|
}
|
|
177
|
+
// 8b. Generate subscription hooks (subscriptions/*.ts)
|
|
178
|
+
// Only generate for tables with the @realtime smart tag
|
|
179
|
+
const realtimeTables = tables.filter((t) => t.smartTags?.['@realtime'] !== undefined);
|
|
180
|
+
const subscriptionHooks = (0, subscriptions_1.generateAllSubscriptionHooks)(realtimeTables);
|
|
181
|
+
for (const hook of subscriptionHooks) {
|
|
182
|
+
files.push({
|
|
183
|
+
path: `subscriptions/${hook.fileName}`,
|
|
184
|
+
content: hook.content,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
// 8c. Generate connection state hook + barrel only if any table has @realtime
|
|
188
|
+
const hasSubscriptions = subscriptionHooks.length > 0;
|
|
189
|
+
if (hasSubscriptions) {
|
|
190
|
+
const connectionStateHook = (0, subscriptions_1.generateConnectionStateHook)();
|
|
191
|
+
files.push({
|
|
192
|
+
path: `subscriptions/${connectionStateHook.fileName}`,
|
|
193
|
+
content: connectionStateHook.content,
|
|
194
|
+
});
|
|
195
|
+
// 8d. Generate subscriptions/index.ts barrel
|
|
196
|
+
files.push({
|
|
197
|
+
path: 'subscriptions/index.ts',
|
|
198
|
+
content: (0, barrel_1.generateSubscriptionsBarrel)(realtimeTables),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
176
201
|
// 9. Generate main index.ts barrel
|
|
177
202
|
// No longer includes types.ts or schema-types.ts - hooks import from ORM directly
|
|
178
203
|
files.push({
|
|
179
204
|
path: 'index.ts',
|
|
180
205
|
content: (0, barrel_1.generateMainBarrel)(tables, {
|
|
181
206
|
hasMutations,
|
|
207
|
+
hasSubscriptions,
|
|
182
208
|
hasQueryKeys,
|
|
183
209
|
hasMutationKeys,
|
|
184
210
|
hasInvalidation,
|
|
@@ -190,6 +216,7 @@ function generate(options) {
|
|
|
190
216
|
tables: tables.length,
|
|
191
217
|
queryHooks: queryHooks.length,
|
|
192
218
|
mutationHooks: mutationHooks.length,
|
|
219
|
+
subscriptionHooks: subscriptionHooks.length,
|
|
193
220
|
customQueryHooks: customQueryHooks.length,
|
|
194
221
|
customMutationHooks: customMutationHooks.length,
|
|
195
222
|
totalFiles: files.length,
|
|
@@ -205,6 +232,7 @@ Object.defineProperty(exports, "generateCustomQueriesBarrel", { enumerable: true
|
|
|
205
232
|
Object.defineProperty(exports, "generateMainBarrel", { enumerable: true, get: function () { return barrel_2.generateMainBarrel; } });
|
|
206
233
|
Object.defineProperty(exports, "generateMutationsBarrel", { enumerable: true, get: function () { return barrel_2.generateMutationsBarrel; } });
|
|
207
234
|
Object.defineProperty(exports, "generateQueriesBarrel", { enumerable: true, get: function () { return barrel_2.generateQueriesBarrel; } });
|
|
235
|
+
Object.defineProperty(exports, "generateSubscriptionsBarrel", { enumerable: true, get: function () { return barrel_2.generateSubscriptionsBarrel; } });
|
|
208
236
|
var client_2 = require("./client");
|
|
209
237
|
Object.defineProperty(exports, "generateClientFile", { enumerable: true, get: function () { return client_2.generateClientFile; } });
|
|
210
238
|
var custom_mutations_2 = require("./custom-mutations");
|
|
@@ -228,3 +256,7 @@ Object.defineProperty(exports, "generateListQueryHook", { enumerable: true, get:
|
|
|
228
256
|
Object.defineProperty(exports, "generateSingleQueryHook", { enumerable: true, get: function () { return queries_2.generateSingleQueryHook; } });
|
|
229
257
|
var query_keys_2 = require("./query-keys");
|
|
230
258
|
Object.defineProperty(exports, "generateQueryKeysFile", { enumerable: true, get: function () { return query_keys_2.generateQueryKeysFile; } });
|
|
259
|
+
var subscriptions_2 = require("./subscriptions");
|
|
260
|
+
Object.defineProperty(exports, "generateAllSubscriptionHooks", { enumerable: true, get: function () { return subscriptions_2.generateAllSubscriptionHooks; } });
|
|
261
|
+
Object.defineProperty(exports, "generateConnectionStateHook", { enumerable: true, get: function () { return subscriptions_2.generateConnectionStateHook; } });
|
|
262
|
+
Object.defineProperty(exports, "generateSubscriptionHook", { enumerable: true, get: function () { return subscriptions_2.generateSubscriptionHook; } });
|
|
@@ -10,6 +10,12 @@ export interface GeneratedClientFile {
|
|
|
10
10
|
* Reads from the templates directory for proper type checking.
|
|
11
11
|
*/
|
|
12
12
|
export declare function generateOrmClientFile(): GeneratedClientFile;
|
|
13
|
+
/**
|
|
14
|
+
* Generate the realtime.ts file (RealtimeManager + subscription types)
|
|
15
|
+
*
|
|
16
|
+
* Reads from the templates directory for proper type checking.
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateRealtimeFile(): GeneratedClientFile;
|
|
13
19
|
/**
|
|
14
20
|
* Generate the query-builder.ts file (runtime query builder)
|
|
15
21
|
*
|
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.generateOrmClientFile = generateOrmClientFile;
|
|
37
|
+
exports.generateRealtimeFile = generateRealtimeFile;
|
|
37
38
|
exports.generateQueryBuilderFile = generateQueryBuilderFile;
|
|
38
39
|
exports.generateSelectTypesFile = generateSelectTypesFile;
|
|
39
40
|
exports.generateCreateClientFile = generateCreateClientFile;
|
|
@@ -83,6 +84,17 @@ function generateOrmClientFile() {
|
|
|
83
84
|
content: readTemplateFile('orm-client.ts', 'ORM Client - Runtime GraphQL executor'),
|
|
84
85
|
};
|
|
85
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Generate the realtime.ts file (RealtimeManager + subscription types)
|
|
89
|
+
*
|
|
90
|
+
* Reads from the templates directory for proper type checking.
|
|
91
|
+
*/
|
|
92
|
+
function generateRealtimeFile() {
|
|
93
|
+
return {
|
|
94
|
+
fileName: 'realtime.ts',
|
|
95
|
+
content: readTemplateFile('orm-realtime.ts', 'Realtime Manager - WebSocket subscription support'),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
86
98
|
/**
|
|
87
99
|
* Generate the query-builder.ts file (runtime query builder)
|
|
88
100
|
*
|
|
@@ -45,6 +45,37 @@ export declare class FetchAdapter implements GraphQLAdapter {
|
|
|
45
45
|
setHeaders(headers: Record<string, string>): void;
|
|
46
46
|
getEndpoint(): string;
|
|
47
47
|
}
|
|
48
|
+
export type SubscriptionOperation = 'INSERT' | 'UPDATE' | 'DELETE';
|
|
49
|
+
export type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
|
|
50
|
+
export type ConnectionStateListener = (state: ConnectionState) => void;
|
|
51
|
+
export type Unsubscribe = () => void;
|
|
52
|
+
export interface SubscriptionEvent<T> {
|
|
53
|
+
operation: SubscriptionOperation;
|
|
54
|
+
data: T | null;
|
|
55
|
+
previousValues?: Partial<T>;
|
|
56
|
+
timestamp: string;
|
|
57
|
+
}
|
|
58
|
+
export interface SubscriptionFieldMeta {
|
|
59
|
+
fieldName: string;
|
|
60
|
+
tableName: string;
|
|
61
|
+
dataFieldName: string;
|
|
62
|
+
}
|
|
63
|
+
export interface SubscribeOptions<T, TFilter = Record<string, unknown>> {
|
|
64
|
+
filter?: TFilter;
|
|
65
|
+
onEvent: (event: SubscriptionEvent<T>) => void;
|
|
66
|
+
onError?: (error: Error) => void;
|
|
67
|
+
onComplete?: () => void;
|
|
68
|
+
}
|
|
69
|
+
export interface RealtimeConfig {
|
|
70
|
+
url: string;
|
|
71
|
+
getToken?: () => string | Promise<string>;
|
|
72
|
+
connectionParams?: Record<string, unknown>;
|
|
73
|
+
lazy?: boolean;
|
|
74
|
+
retryAttempts?: number;
|
|
75
|
+
retryWait?: number | ((retryCount: number) => number | Promise<number>);
|
|
76
|
+
onConnected?: () => void;
|
|
77
|
+
onDisconnected?: (reason?: unknown) => void;
|
|
78
|
+
}
|
|
48
79
|
/**
|
|
49
80
|
* Configuration for creating an ORM client.
|
|
50
81
|
*/
|
|
@@ -55,6 +86,8 @@ export interface OrmClientConfig {
|
|
|
55
86
|
headers?: Record<string, string>;
|
|
56
87
|
/** Custom adapter for GraphQL execution (overrides endpoint/headers) */
|
|
57
88
|
adapter?: GraphQLAdapter;
|
|
89
|
+
/** Optional realtime (WebSocket) configuration */
|
|
90
|
+
realtime?: RealtimeConfig;
|
|
58
91
|
}
|
|
59
92
|
export declare class GraphQLRequestError extends Error {
|
|
60
93
|
readonly errors: GraphQLError[];
|
|
@@ -65,6 +98,16 @@ export declare class OrmClient {
|
|
|
65
98
|
private adapter;
|
|
66
99
|
constructor(config: OrmClientConfig);
|
|
67
100
|
execute<T>(document: string, variables?: Record<string, unknown>): Promise<QueryResult<T>>;
|
|
101
|
+
subscribe<T>(meta: SubscriptionFieldMeta, document: string, variables: Record<string, unknown>, options: {
|
|
102
|
+
onEvent: (event: SubscriptionEvent<T>) => void;
|
|
103
|
+
onError?: (error: Error) => void;
|
|
104
|
+
onComplete?: () => void;
|
|
105
|
+
}): Unsubscribe;
|
|
68
106
|
setHeaders(headers: Record<string, string>): void;
|
|
69
107
|
getEndpoint(): string;
|
|
108
|
+
getConnectionState(): ConnectionState;
|
|
109
|
+
onConnectionStateChange(listener: ConnectionStateListener): Unsubscribe;
|
|
110
|
+
getActiveSubscriptionCount(): number;
|
|
111
|
+
get isRealtimeEnabled(): boolean;
|
|
112
|
+
dispose(): void;
|
|
70
113
|
}
|
|
@@ -92,6 +92,9 @@ class OrmClient {
|
|
|
92
92
|
async execute(document, variables) {
|
|
93
93
|
return this.adapter.execute(document, variables);
|
|
94
94
|
}
|
|
95
|
+
subscribe(meta, document, variables, options) {
|
|
96
|
+
throw new Error('Realtime not configured');
|
|
97
|
+
}
|
|
95
98
|
setHeaders(headers) {
|
|
96
99
|
if (this.adapter.setHeaders) {
|
|
97
100
|
this.adapter.setHeaders(headers);
|
|
@@ -100,5 +103,18 @@ class OrmClient {
|
|
|
100
103
|
getEndpoint() {
|
|
101
104
|
return this.adapter.getEndpoint?.() ?? '';
|
|
102
105
|
}
|
|
106
|
+
getConnectionState() {
|
|
107
|
+
return 'disconnected';
|
|
108
|
+
}
|
|
109
|
+
onConnectionStateChange(listener) {
|
|
110
|
+
return () => { };
|
|
111
|
+
}
|
|
112
|
+
getActiveSubscriptionCount() {
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
get isRealtimeEnabled() {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
dispose() { }
|
|
103
119
|
}
|
|
104
120
|
exports.OrmClient = OrmClient;
|
|
@@ -40,6 +40,6 @@ export interface GenerateOrmResult {
|
|
|
40
40
|
*/
|
|
41
41
|
export declare function generateOrm(options: GenerateOrmOptions): GenerateOrmResult;
|
|
42
42
|
export { generateModelsBarrel, generateTypesBarrel } from './barrel';
|
|
43
|
-
export { generateOrmClientFile, generateQueryBuilderFile, generateSelectTypesFile, } from './client-generator';
|
|
43
|
+
export { generateOrmClientFile, generateQueryBuilderFile, generateRealtimeFile, generateSelectTypesFile, } from './client-generator';
|
|
44
44
|
export { generateCustomMutationOpsFile, generateCustomQueryOpsFile, } from './custom-ops-generator';
|
|
45
45
|
export { generateAllModelFiles, generateModelFile } from './model-generator';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateModelFile = exports.generateAllModelFiles = exports.generateCustomQueryOpsFile = exports.generateCustomMutationOpsFile = exports.generateSelectTypesFile = exports.generateQueryBuilderFile = exports.generateOrmClientFile = exports.generateTypesBarrel = exports.generateModelsBarrel = void 0;
|
|
3
|
+
exports.generateModelFile = exports.generateAllModelFiles = exports.generateCustomQueryOpsFile = exports.generateCustomMutationOpsFile = exports.generateSelectTypesFile = exports.generateRealtimeFile = exports.generateQueryBuilderFile = exports.generateOrmClientFile = exports.generateTypesBarrel = exports.generateModelsBarrel = void 0;
|
|
4
4
|
exports.generateOrm = generateOrm;
|
|
5
5
|
const barrel_1 = require("./barrel");
|
|
6
6
|
const client_generator_1 = require("./client-generator");
|
|
@@ -19,9 +19,11 @@ function generateOrm(options) {
|
|
|
19
19
|
const hasCustomQueries = (customOperations?.queries.length ?? 0) > 0;
|
|
20
20
|
const hasCustomMutations = (customOperations?.mutations.length ?? 0) > 0;
|
|
21
21
|
const typeRegistry = customOperations?.typeRegistry;
|
|
22
|
-
// 1. Generate runtime files (client, query-builder, select-types)
|
|
22
|
+
// 1. Generate runtime files (client, query-builder, select-types, realtime)
|
|
23
23
|
const clientFile = (0, client_generator_1.generateOrmClientFile)();
|
|
24
24
|
files.push({ path: clientFile.fileName, content: clientFile.content });
|
|
25
|
+
const realtimeFile = (0, client_generator_1.generateRealtimeFile)();
|
|
26
|
+
files.push({ path: realtimeFile.fileName, content: realtimeFile.content });
|
|
25
27
|
const queryBuilderFile = (0, client_generator_1.generateQueryBuilderFile)();
|
|
26
28
|
files.push({
|
|
27
29
|
path: queryBuilderFile.fileName,
|
|
@@ -111,6 +113,7 @@ Object.defineProperty(exports, "generateTypesBarrel", { enumerable: true, get: f
|
|
|
111
113
|
var client_generator_2 = require("./client-generator");
|
|
112
114
|
Object.defineProperty(exports, "generateOrmClientFile", { enumerable: true, get: function () { return client_generator_2.generateOrmClientFile; } });
|
|
113
115
|
Object.defineProperty(exports, "generateQueryBuilderFile", { enumerable: true, get: function () { return client_generator_2.generateQueryBuilderFile; } });
|
|
116
|
+
Object.defineProperty(exports, "generateRealtimeFile", { enumerable: true, get: function () { return client_generator_2.generateRealtimeFile; } });
|
|
114
117
|
Object.defineProperty(exports, "generateSelectTypesFile", { enumerable: true, get: function () { return client_generator_2.generateSelectTypesFile; } });
|
|
115
118
|
var custom_ops_generator_2 = require("./custom-ops-generator");
|
|
116
119
|
Object.defineProperty(exports, "generateCustomMutationOpsFile", { enumerable: true, get: function () { return custom_ops_generator_2.generateCustomMutationOpsFile; } });
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Table } from '../../types/schema';
|
|
2
|
+
export interface GeneratedSubscriptionFile {
|
|
3
|
+
fileName: string;
|
|
4
|
+
content: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Generate a subscription hook for a table.
|
|
8
|
+
*
|
|
9
|
+
* Produces a React hook that calls `getClient().subscribe()` with the
|
|
10
|
+
* correct subscription document, field metadata, and typed callbacks.
|
|
11
|
+
*
|
|
12
|
+
* Example generated output:
|
|
13
|
+
* ```ts
|
|
14
|
+
* export function useContactSubscription(options: ContactSubscriptionOptions): Unsubscribe {
|
|
15
|
+
* ...
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateSubscriptionHook(table: Table): GeneratedSubscriptionFile;
|
|
20
|
+
/**
|
|
21
|
+
* Generate the useConnectionState hook file.
|
|
22
|
+
*
|
|
23
|
+
* This hook exposes the WebSocket connection state from the ORM client
|
|
24
|
+
* so UI components can show connection indicators.
|
|
25
|
+
*/
|
|
26
|
+
export declare function generateConnectionStateHook(): GeneratedSubscriptionFile;
|
|
27
|
+
/**
|
|
28
|
+
* Generate subscription hooks for all tables
|
|
29
|
+
*/
|
|
30
|
+
export declare function generateAllSubscriptionHooks(tables: Table[]): GeneratedSubscriptionFile[];
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.generateSubscriptionHook = generateSubscriptionHook;
|
|
37
|
+
exports.generateConnectionStateHook = generateConnectionStateHook;
|
|
38
|
+
exports.generateAllSubscriptionHooks = generateAllSubscriptionHooks;
|
|
39
|
+
/**
|
|
40
|
+
* Subscription hook generators - delegates to ORM client subscribe (Babel AST-based)
|
|
41
|
+
*
|
|
42
|
+
* Output structure:
|
|
43
|
+
* subscriptions/
|
|
44
|
+
* useContactSubscription.ts - Subscription hook -> ORM client.subscribe()
|
|
45
|
+
* useConnectionState.ts - Connection state hook
|
|
46
|
+
*/
|
|
47
|
+
const t = __importStar(require("@babel/types"));
|
|
48
|
+
const hooks_ast_1 = require("./hooks-ast");
|
|
49
|
+
const utils_1 = require("./utils");
|
|
50
|
+
/**
|
|
51
|
+
* Generate a subscription hook for a table.
|
|
52
|
+
*
|
|
53
|
+
* Produces a React hook that calls `getClient().subscribe()` with the
|
|
54
|
+
* correct subscription document, field metadata, and typed callbacks.
|
|
55
|
+
*
|
|
56
|
+
* Example generated output:
|
|
57
|
+
* ```ts
|
|
58
|
+
* export function useContactSubscription(options: ContactSubscriptionOptions): Unsubscribe {
|
|
59
|
+
* ...
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
function generateSubscriptionHook(table) {
|
|
64
|
+
const { typeName, singularName } = (0, utils_1.getTableNames)(table);
|
|
65
|
+
const hookName = (0, utils_1.getSubscriptionHookName)(table);
|
|
66
|
+
const subscriptionFieldName = (0, utils_1.getSubscriptionFieldName)(table);
|
|
67
|
+
const keysName = `${(0, utils_1.lcFirst)(typeName)}Keys`;
|
|
68
|
+
const statements = [];
|
|
69
|
+
// Imports
|
|
70
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('react', ['useEffect', 'useRef', 'useCallback']));
|
|
71
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('@tanstack/react-query', ['useQueryClient']));
|
|
72
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('@tanstack/react-query', ['QueryClient'], true));
|
|
73
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('../client', ['getClient']));
|
|
74
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/client', [
|
|
75
|
+
'SubscriptionEvent',
|
|
76
|
+
'SubscriptionFieldMeta',
|
|
77
|
+
'Unsubscribe',
|
|
78
|
+
], true));
|
|
79
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/input-types', [typeName], true));
|
|
80
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('../query-keys', [keysName]));
|
|
81
|
+
// Re-export SubscriptionEvent for consumer convenience
|
|
82
|
+
statements.push((0, hooks_ast_1.createTypeReExport)(['SubscriptionEvent', 'Unsubscribe'], '../../orm/client'));
|
|
83
|
+
// Subscription document constant
|
|
84
|
+
const subscriptionDoc = `subscription On${typeName}Changed {
|
|
85
|
+
${subscriptionFieldName} {
|
|
86
|
+
event
|
|
87
|
+
${singularName} { __typename }
|
|
88
|
+
timestamp
|
|
89
|
+
}
|
|
90
|
+
}`;
|
|
91
|
+
const docDecl = (0, hooks_ast_1.constDecl)('SUBSCRIPTION_DOCUMENT', t.stringLiteral(subscriptionDoc));
|
|
92
|
+
statements.push(docDecl);
|
|
93
|
+
// Field metadata constant
|
|
94
|
+
const metaDecl = t.variableDeclaration('const', [
|
|
95
|
+
t.variableDeclarator(t.identifier('FIELD_META'), t.objectExpression([
|
|
96
|
+
(0, hooks_ast_1.objectProp)('fieldName', t.stringLiteral(subscriptionFieldName)),
|
|
97
|
+
(0, hooks_ast_1.objectProp)('tableName', t.stringLiteral(singularName)),
|
|
98
|
+
(0, hooks_ast_1.objectProp)('dataFieldName', t.stringLiteral(singularName)),
|
|
99
|
+
])),
|
|
100
|
+
]);
|
|
101
|
+
// Add type annotation: SubscriptionFieldMeta
|
|
102
|
+
const metaId = metaDecl.declarations[0].id;
|
|
103
|
+
metaId.typeAnnotation = t.tsTypeAnnotation((0, hooks_ast_1.typeRef)('SubscriptionFieldMeta'));
|
|
104
|
+
statements.push(metaDecl);
|
|
105
|
+
// Options interface
|
|
106
|
+
const optionsTypeName = `${typeName}SubscriptionOptions`;
|
|
107
|
+
const optionsInterface = t.tsInterfaceDeclaration(t.identifier(optionsTypeName), null, null, t.tsInterfaceBody([
|
|
108
|
+
(() => {
|
|
109
|
+
const p = t.tsPropertySignature(t.identifier('onEvent'), t.tsTypeAnnotation(t.tsFunctionType(null, [
|
|
110
|
+
(0, hooks_ast_1.createFunctionParam)('event', (0, hooks_ast_1.typeRef)('SubscriptionEvent', [(0, hooks_ast_1.typeRef)(typeName)])),
|
|
111
|
+
], t.tsTypeAnnotation(t.tsVoidKeyword()))));
|
|
112
|
+
return p;
|
|
113
|
+
})(),
|
|
114
|
+
(() => {
|
|
115
|
+
const p = t.tsPropertySignature(t.identifier('onError'), t.tsTypeAnnotation(t.tsFunctionType(null, [(0, hooks_ast_1.createFunctionParam)('error', (0, hooks_ast_1.typeRef)('Error'))], t.tsTypeAnnotation(t.tsVoidKeyword()))));
|
|
116
|
+
p.optional = true;
|
|
117
|
+
return p;
|
|
118
|
+
})(),
|
|
119
|
+
(() => {
|
|
120
|
+
const p = t.tsPropertySignature(t.identifier('enabled'), t.tsTypeAnnotation(t.tsBooleanKeyword()));
|
|
121
|
+
p.optional = true;
|
|
122
|
+
return p;
|
|
123
|
+
})(),
|
|
124
|
+
(() => {
|
|
125
|
+
const p = t.tsPropertySignature(t.identifier('invalidateQueries'), t.tsTypeAnnotation(t.tsBooleanKeyword()));
|
|
126
|
+
p.optional = true;
|
|
127
|
+
return p;
|
|
128
|
+
})(),
|
|
129
|
+
]));
|
|
130
|
+
statements.push(t.exportNamedDeclaration(optionsInterface));
|
|
131
|
+
// Hook implementation
|
|
132
|
+
const hookBody = [];
|
|
133
|
+
// const queryClient = useQueryClient();
|
|
134
|
+
hookBody.push((0, hooks_ast_1.constDecl)('queryClient', (0, hooks_ast_1.callExpr)('useQueryClient', [])));
|
|
135
|
+
// const optionsRef = useRef(options);
|
|
136
|
+
hookBody.push((0, hooks_ast_1.constDecl)('optionsRef', (0, hooks_ast_1.callExpr)('useRef', [t.identifier('options')])));
|
|
137
|
+
// optionsRef.current = options;
|
|
138
|
+
hookBody.push(t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier('optionsRef'), t.identifier('current')), t.identifier('options'))));
|
|
139
|
+
// useEffect with subscribe
|
|
140
|
+
const effectBody = [];
|
|
141
|
+
// if (options.enabled === false) return;
|
|
142
|
+
effectBody.push(t.ifStatement(t.binaryExpression('===', t.memberExpression(t.identifier('options'), t.identifier('enabled')), t.booleanLiteral(false)), t.returnStatement(null)));
|
|
143
|
+
// const client = getClient();
|
|
144
|
+
effectBody.push((0, hooks_ast_1.constDecl)('client', (0, hooks_ast_1.callExpr)('getClient', [])));
|
|
145
|
+
// if (!client.isRealtimeEnabled) return;
|
|
146
|
+
effectBody.push(t.ifStatement(t.unaryExpression('!', t.memberExpression(t.identifier('client'), t.identifier('isRealtimeEnabled'))), t.returnStatement(null)));
|
|
147
|
+
// const unsubscribe = client.subscribe(FIELD_META, SUBSCRIPTION_DOCUMENT, {}, { onEvent, onError, onComplete });
|
|
148
|
+
const subscribeCall = t.callExpression(t.memberExpression(t.identifier('client'), t.identifier('subscribe')), [
|
|
149
|
+
t.identifier('FIELD_META'),
|
|
150
|
+
t.identifier('SUBSCRIPTION_DOCUMENT'),
|
|
151
|
+
t.objectExpression([]),
|
|
152
|
+
t.objectExpression([
|
|
153
|
+
(0, hooks_ast_1.objectProp)('onEvent', t.arrowFunctionExpression([t.identifier('event')], t.blockStatement([
|
|
154
|
+
// optionsRef.current.onEvent(event);
|
|
155
|
+
t.expressionStatement((0, hooks_ast_1.callExpr)(t.memberExpression(t.memberExpression(t.identifier('optionsRef'), t.identifier('current')), t.identifier('onEvent')), [t.identifier('event')])),
|
|
156
|
+
// if (optionsRef.current.invalidateQueries !== false) { queryClient.invalidateQueries({ queryKey: keysName.all }); }
|
|
157
|
+
t.ifStatement(t.binaryExpression('!==', t.memberExpression(t.memberExpression(t.identifier('optionsRef'), t.identifier('current')), t.identifier('invalidateQueries')), t.booleanLiteral(false)), t.expressionStatement((0, hooks_ast_1.callExpr)(t.memberExpression(t.identifier('queryClient'), t.identifier('invalidateQueries')), [
|
|
158
|
+
t.objectExpression([
|
|
159
|
+
(0, hooks_ast_1.objectProp)('queryKey', t.memberExpression(t.identifier(keysName), t.identifier('all'))),
|
|
160
|
+
]),
|
|
161
|
+
]))),
|
|
162
|
+
]))),
|
|
163
|
+
(0, hooks_ast_1.objectProp)('onError', t.arrowFunctionExpression([t.identifier('err')], t.blockStatement([
|
|
164
|
+
t.expressionStatement(t.optionalCallExpression(t.optionalMemberExpression(t.memberExpression(t.identifier('optionsRef'), t.identifier('current')), t.identifier('onError'), false, true), [t.identifier('err')], false)),
|
|
165
|
+
]))),
|
|
166
|
+
]),
|
|
167
|
+
]);
|
|
168
|
+
effectBody.push((0, hooks_ast_1.constDecl)('unsubscribe', subscribeCall));
|
|
169
|
+
// return () => unsubscribe();
|
|
170
|
+
effectBody.push(t.returnStatement(t.arrowFunctionExpression([], t.callExpression(t.identifier('unsubscribe'), []))));
|
|
171
|
+
// useEffect(() => { ... }, [options.enabled]);
|
|
172
|
+
const effectFn = t.arrowFunctionExpression([], t.blockStatement(effectBody));
|
|
173
|
+
hookBody.push(t.expressionStatement((0, hooks_ast_1.callExpr)('useEffect', [
|
|
174
|
+
effectFn,
|
|
175
|
+
t.arrayExpression([
|
|
176
|
+
t.memberExpression(t.identifier('options'), t.identifier('enabled')),
|
|
177
|
+
t.identifier('queryClient'),
|
|
178
|
+
]),
|
|
179
|
+
])));
|
|
180
|
+
// Hook declaration
|
|
181
|
+
const hookParam = (0, hooks_ast_1.createFunctionParam)('options', (0, hooks_ast_1.typeRef)(optionsTypeName));
|
|
182
|
+
const hookDecl = (0, hooks_ast_1.exportFunction)(hookName, null, [hookParam], hookBody, t.tsVoidKeyword());
|
|
183
|
+
(0, hooks_ast_1.addJSDocComment)(hookDecl, [
|
|
184
|
+
`Subscription hook for ${typeName} realtime events`,
|
|
185
|
+
'',
|
|
186
|
+
'Subscribes to realtime changes on the server and automatically',
|
|
187
|
+
'invalidates React Query cache when events are received.',
|
|
188
|
+
'',
|
|
189
|
+
'@example',
|
|
190
|
+
'```tsx',
|
|
191
|
+
`${hookName}({`,
|
|
192
|
+
' onEvent: (event) => {',
|
|
193
|
+
` console.log(event.operation, event.data);`,
|
|
194
|
+
' },',
|
|
195
|
+
'});',
|
|
196
|
+
'```',
|
|
197
|
+
]);
|
|
198
|
+
statements.push(hookDecl);
|
|
199
|
+
return {
|
|
200
|
+
fileName: (0, utils_1.getSubscriptionFileName)(table),
|
|
201
|
+
content: (0, hooks_ast_1.generateHookFileCode)(`Subscription hook for ${typeName}`, statements),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Generate the useConnectionState hook file.
|
|
206
|
+
*
|
|
207
|
+
* This hook exposes the WebSocket connection state from the ORM client
|
|
208
|
+
* so UI components can show connection indicators.
|
|
209
|
+
*/
|
|
210
|
+
function generateConnectionStateHook() {
|
|
211
|
+
const statements = [];
|
|
212
|
+
// Imports
|
|
213
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('react', ['useState', 'useEffect']));
|
|
214
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('../client', ['getClient']));
|
|
215
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/client', ['ConnectionState'], true));
|
|
216
|
+
// Re-export ConnectionState
|
|
217
|
+
statements.push((0, hooks_ast_1.createTypeReExport)(['ConnectionState'], '../../orm/client'));
|
|
218
|
+
// Hook body
|
|
219
|
+
const hookBody = [];
|
|
220
|
+
// const [state, setState] = useState<ConnectionState>(() => getClient().getConnectionState());
|
|
221
|
+
const initFn = t.arrowFunctionExpression([], (0, hooks_ast_1.callExpr)(t.memberExpression((0, hooks_ast_1.callExpr)('getClient', []), t.identifier('getConnectionState')), []));
|
|
222
|
+
const useStateCall = (0, hooks_ast_1.callExpr)('useState', [initFn]);
|
|
223
|
+
// @ts-ignore - typeParameters on CallExpression for TS
|
|
224
|
+
useStateCall.typeParameters = t.tsTypeParameterInstantiation([
|
|
225
|
+
(0, hooks_ast_1.typeRef)('ConnectionState'),
|
|
226
|
+
]);
|
|
227
|
+
hookBody.push(t.variableDeclaration('const', [
|
|
228
|
+
t.variableDeclarator(t.arrayPattern([t.identifier('state'), t.identifier('setState')]), useStateCall),
|
|
229
|
+
]));
|
|
230
|
+
// useEffect
|
|
231
|
+
const effectBody = [];
|
|
232
|
+
effectBody.push((0, hooks_ast_1.constDecl)('client', (0, hooks_ast_1.callExpr)('getClient', [])));
|
|
233
|
+
// if (!client.isRealtimeEnabled) return;
|
|
234
|
+
effectBody.push(t.ifStatement(t.unaryExpression('!', t.memberExpression(t.identifier('client'), t.identifier('isRealtimeEnabled'))), t.returnStatement(null)));
|
|
235
|
+
// const unsubscribe = client.onConnectionStateChange(setState);
|
|
236
|
+
effectBody.push((0, hooks_ast_1.constDecl)('unsubscribe', (0, hooks_ast_1.callExpr)(t.memberExpression(t.identifier('client'), t.identifier('onConnectionStateChange')), [t.identifier('setState')])));
|
|
237
|
+
// return () => unsubscribe();
|
|
238
|
+
effectBody.push(t.returnStatement(t.arrowFunctionExpression([], t.callExpression(t.identifier('unsubscribe'), []))));
|
|
239
|
+
hookBody.push(t.expressionStatement((0, hooks_ast_1.callExpr)('useEffect', [
|
|
240
|
+
t.arrowFunctionExpression([], t.blockStatement(effectBody)),
|
|
241
|
+
t.arrayExpression([]),
|
|
242
|
+
])));
|
|
243
|
+
// return state;
|
|
244
|
+
hookBody.push(t.returnStatement(t.identifier('state')));
|
|
245
|
+
// Hook declaration
|
|
246
|
+
const hookDecl = (0, hooks_ast_1.exportFunction)('useConnectionState', null, [], hookBody, (0, hooks_ast_1.typeRef)('ConnectionState'));
|
|
247
|
+
(0, hooks_ast_1.addJSDocComment)(hookDecl, [
|
|
248
|
+
'Hook to observe the WebSocket connection state.',
|
|
249
|
+
'',
|
|
250
|
+
'Returns the current connection state of the realtime WebSocket.',
|
|
251
|
+
"Returns 'disconnected' if realtime is not configured.",
|
|
252
|
+
'',
|
|
253
|
+
'@example',
|
|
254
|
+
'```tsx',
|
|
255
|
+
'const state = useConnectionState();',
|
|
256
|
+
"// state: 'disconnected' | 'connecting' | 'connected' | 'reconnecting'",
|
|
257
|
+
'```',
|
|
258
|
+
]);
|
|
259
|
+
statements.push(hookDecl);
|
|
260
|
+
return {
|
|
261
|
+
fileName: 'useConnectionState.ts',
|
|
262
|
+
content: (0, hooks_ast_1.generateHookFileCode)('WebSocket connection state hook', statements),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Generate subscription hooks for all tables
|
|
267
|
+
*/
|
|
268
|
+
function generateAllSubscriptionHooks(tables) {
|
|
269
|
+
return tables.map((table) => generateSubscriptionHook(table));
|
|
270
|
+
}
|