@fitzzero/quickdraw-core 0.1.0 → 1.1.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/README.md +122 -28
- package/dist/client/index.d.ts +30 -37
- package/dist/client/index.js +103 -58
- package/dist/client/index.js.map +1 -1
- package/dist/client/testing.d.ts +1 -1
- package/dist/client/testing.js +32 -0
- package/dist/client/testing.js.map +1 -1
- package/dist/server/index.d.ts +577 -9
- package/dist/server/index.js +985 -47
- package/dist/server/index.js.map +1 -1
- package/dist/server/testing.d.ts +2 -2
- package/dist/server/testing.js +124 -36
- package/dist/server/testing.js.map +1 -1
- package/dist/shared/index.d.ts +111 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/{types-CUExGF7F.d.ts → types-BADirRXn.d.ts} +50 -8
- package/dist/{types-OhRxDBID.d.ts → types-D7oHWh4O.d.ts} +60 -2
- package/package.json +12 -13
|
@@ -2,14 +2,6 @@ import { Socket } from 'socket.io-client';
|
|
|
2
2
|
import { QueryClient } from '@tanstack/react-query';
|
|
3
3
|
import { AccessLevel } from './shared/index.js';
|
|
4
4
|
|
|
5
|
-
interface QuickdrawSocketContextValue {
|
|
6
|
-
socket: Socket | null;
|
|
7
|
-
isConnected: boolean;
|
|
8
|
-
userId: string | null;
|
|
9
|
-
serviceAccess: Record<string, AccessLevel>;
|
|
10
|
-
connect: (token?: string) => void;
|
|
11
|
-
disconnect: () => void;
|
|
12
|
-
}
|
|
13
5
|
interface QuickdrawProviderProps {
|
|
14
6
|
children: React.ReactNode;
|
|
15
7
|
/**
|
|
@@ -37,6 +29,10 @@ interface QuickdrawProviderProps {
|
|
|
37
29
|
interface UseServiceOptions<TResponse> {
|
|
38
30
|
onSuccess?: (data: TResponse) => void;
|
|
39
31
|
onError?: (error: string) => void;
|
|
32
|
+
/**
|
|
33
|
+
* Request timeout in milliseconds (default: 10000)
|
|
34
|
+
*/
|
|
35
|
+
timeout?: number;
|
|
40
36
|
/**
|
|
41
37
|
* TanStack Query mutation options
|
|
42
38
|
*/
|
|
@@ -105,5 +101,51 @@ type ClientServiceMethodMap<T extends Record<string, {
|
|
|
105
101
|
* Maps service names to their entity types.
|
|
106
102
|
*/
|
|
107
103
|
type SubscriptionDataMap<T extends Record<string, unknown>> = T;
|
|
104
|
+
/**
|
|
105
|
+
* Tracks an active subscription with reference counting for deduplication.
|
|
106
|
+
*/
|
|
107
|
+
interface SubscriptionEntry {
|
|
108
|
+
refCount: number;
|
|
109
|
+
cleanup?: () => void;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Registry for tracking active subscriptions per socket instance.
|
|
113
|
+
* This prevents memory leaks and race conditions with HMR/reconnects.
|
|
114
|
+
*/
|
|
115
|
+
interface SubscriptionRegistry {
|
|
116
|
+
/**
|
|
117
|
+
* Get or create a subscription entry, incrementing ref count.
|
|
118
|
+
* Returns true if this is a new subscription, false if joining existing.
|
|
119
|
+
*/
|
|
120
|
+
acquire: (key: string) => {
|
|
121
|
+
isNew: boolean;
|
|
122
|
+
entry: SubscriptionEntry;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Release a subscription, decrementing ref count.
|
|
126
|
+
* Returns true if subscription was fully released (ref count reached 0).
|
|
127
|
+
*/
|
|
128
|
+
release: (key: string) => boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Set the cleanup function for a subscription.
|
|
131
|
+
*/
|
|
132
|
+
setCleanup: (key: string, cleanup: () => void) => void;
|
|
133
|
+
/**
|
|
134
|
+
* Clear all subscriptions (called on disconnect/socket change).
|
|
135
|
+
*/
|
|
136
|
+
clear: () => void;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Extended socket context value with subscription registry.
|
|
140
|
+
*/
|
|
141
|
+
interface QuickdrawSocketContextValue {
|
|
142
|
+
socket: Socket | null;
|
|
143
|
+
isConnected: boolean;
|
|
144
|
+
userId: string | null;
|
|
145
|
+
serviceAccess: Record<string, AccessLevel>;
|
|
146
|
+
connect: (token?: string) => void;
|
|
147
|
+
disconnect: () => void;
|
|
148
|
+
subscriptionRegistry: SubscriptionRegistry;
|
|
149
|
+
}
|
|
108
150
|
|
|
109
151
|
export type { ClientServiceMethodMap as C, QuickdrawSocketContextValue as Q, SubscriptionDataMap as S, UseServiceOptions as U, QuickdrawProviderProps as a, UseServiceResult as b, UseSubscriptionOptions as c, UseSubscriptionResult as d };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Socket, Server } from 'socket.io';
|
|
2
2
|
import { Server as Server$1 } from 'http';
|
|
3
|
-
import {
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { AccessLevel, ServiceMethodDefinition, Logger, AdminFieldConfig } from './shared/index.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Extended Socket type with authentication properties
|
|
@@ -25,6 +26,19 @@ interface QuickdrawServerOptions {
|
|
|
25
26
|
authenticate?: (socket: QuickdrawSocket, auth: Record<string, unknown>) => Promise<string | undefined>;
|
|
26
27
|
};
|
|
27
28
|
logger?: Logger;
|
|
29
|
+
/**
|
|
30
|
+
* Automatic method logging configuration.
|
|
31
|
+
* Logs all service method calls, success/failure, timing, and errors.
|
|
32
|
+
* @default { enabled: true, logPayloads: false }
|
|
33
|
+
*/
|
|
34
|
+
methodLogging?: {
|
|
35
|
+
/** Enable automatic method logging. Default: true */
|
|
36
|
+
enabled?: boolean;
|
|
37
|
+
/** Log request payloads (may contain sensitive data). Default: false */
|
|
38
|
+
logPayloads?: boolean;
|
|
39
|
+
/** Log response data (may contain sensitive data). Default: false */
|
|
40
|
+
logResponses?: boolean;
|
|
41
|
+
};
|
|
28
42
|
}
|
|
29
43
|
interface QuickdrawServerResult {
|
|
30
44
|
io: Server;
|
|
@@ -41,6 +55,8 @@ interface BaseServiceInstance {
|
|
|
41
55
|
unsubscribeSocket: (socket: QuickdrawSocket) => void;
|
|
42
56
|
ensureAccessForMethod: (requiredLevel: AccessLevel, socket: QuickdrawSocket, entryId?: string) => Promise<void>;
|
|
43
57
|
getPublicMethods: () => ServiceMethodDefinition<unknown, unknown>[];
|
|
58
|
+
/** Set Socket.io server instance for room-based broadcasts */
|
|
59
|
+
setIo?: (io: Server) => void;
|
|
44
60
|
}
|
|
45
61
|
/**
|
|
46
62
|
* Interface for ServiceRegistry instances
|
|
@@ -70,6 +86,8 @@ interface InstallAdminMethodsOptions {
|
|
|
70
86
|
getSubscribers?: boolean;
|
|
71
87
|
reemit?: boolean;
|
|
72
88
|
unsubscribeAll?: boolean;
|
|
89
|
+
/** Enable adminMeta method for UI generation. Default: true if any other admin method is exposed */
|
|
90
|
+
meta?: boolean;
|
|
73
91
|
};
|
|
74
92
|
access: {
|
|
75
93
|
list: AccessLevel;
|
|
@@ -81,7 +99,47 @@ interface InstallAdminMethodsOptions {
|
|
|
81
99
|
getSubscribers: AccessLevel;
|
|
82
100
|
reemit: AccessLevel;
|
|
83
101
|
unsubscribeAll: AccessLevel;
|
|
102
|
+
/** Access level for adminMeta. Default: same as list */
|
|
103
|
+
meta?: AccessLevel;
|
|
84
104
|
};
|
|
105
|
+
/** Zod schema for deriving field metadata (typically the create schema) */
|
|
106
|
+
schema?: z.ZodTypeAny;
|
|
107
|
+
/** Human-readable display name for the service (e.g., "Chats") */
|
|
108
|
+
displayName?: string;
|
|
109
|
+
/** Override which fields appear in table (by default all non-json fields) */
|
|
110
|
+
tableColumns?: string[];
|
|
111
|
+
/** Fields to hide from admin UI entirely */
|
|
112
|
+
hiddenFields?: string[];
|
|
113
|
+
/** Override specific field configurations */
|
|
114
|
+
fieldOverrides?: Partial<Record<string, Partial<AdminFieldConfig>>>;
|
|
115
|
+
}
|
|
116
|
+
interface AdminListPayload {
|
|
117
|
+
page?: number;
|
|
118
|
+
pageSize?: number;
|
|
119
|
+
where?: Record<string, unknown>;
|
|
120
|
+
orderBy?: Record<string, "asc" | "desc">;
|
|
121
|
+
}
|
|
122
|
+
interface AdminListResponse<TEntity> {
|
|
123
|
+
items: TEntity[];
|
|
124
|
+
total: number;
|
|
125
|
+
page: number;
|
|
126
|
+
pageSize: number;
|
|
127
|
+
totalPages: number;
|
|
128
|
+
}
|
|
129
|
+
interface AdminSetACLPayload {
|
|
130
|
+
entryId: string;
|
|
131
|
+
acl: Array<{
|
|
132
|
+
userId: string;
|
|
133
|
+
level: AccessLevel;
|
|
134
|
+
}>;
|
|
135
|
+
}
|
|
136
|
+
interface AdminSubscribersResponse {
|
|
137
|
+
entryId: string;
|
|
138
|
+
subscribers: Array<{
|
|
139
|
+
socketId: string;
|
|
140
|
+
userId: string | null;
|
|
141
|
+
}>;
|
|
142
|
+
count: number;
|
|
85
143
|
}
|
|
86
144
|
/**
|
|
87
145
|
* Generic Prisma delegate type for CRUD operations.
|
|
@@ -115,4 +173,4 @@ interface PrismaDelegate<TEntity, TCreateInput, TUpdateInput, TWhereUniqueInput
|
|
|
115
173
|
}) => Promise<number>;
|
|
116
174
|
}
|
|
117
175
|
|
|
118
|
-
export type { BaseServiceInstance as B, InstallAdminMethodsOptions as I, PrismaDelegate as P, QuickdrawServerResult as Q, ServiceRegistryInstance as S, QuickdrawSocket as a, BaseServiceOptions as b,
|
|
176
|
+
export type { AdminListPayload as A, BaseServiceInstance as B, InstallAdminMethodsOptions as I, PrismaDelegate as P, QuickdrawServerResult as Q, ServiceRegistryInstance as S, QuickdrawSocket as a, BaseServiceOptions as b, AdminListResponse as c, AdminSetACLPayload as d, AdminSubscribersResponse as e, QuickdrawServerOptions as f };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fitzzero/quickdraw-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Fast fullstack patterns for real-time applications with Socket.io and TanStack Query",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/shared/index.js",
|
|
@@ -31,17 +31,6 @@
|
|
|
31
31
|
"files": [
|
|
32
32
|
"dist"
|
|
33
33
|
],
|
|
34
|
-
"scripts": {
|
|
35
|
-
"build": "tsup",
|
|
36
|
-
"dev": "tsup --watch",
|
|
37
|
-
"typecheck": "tsc --noEmit",
|
|
38
|
-
"lint": "eslint src --ext .ts,.tsx",
|
|
39
|
-
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
40
|
-
"test": "vitest run",
|
|
41
|
-
"test:watch": "vitest",
|
|
42
|
-
"test:coverage": "vitest run --coverage",
|
|
43
|
-
"prepublishOnly": "pnpm build"
|
|
44
|
-
},
|
|
45
34
|
"keywords": [
|
|
46
35
|
"socket.io",
|
|
47
36
|
"tanstack-query",
|
|
@@ -107,5 +96,15 @@
|
|
|
107
96
|
},
|
|
108
97
|
"engines": {
|
|
109
98
|
"node": ">=20"
|
|
99
|
+
},
|
|
100
|
+
"scripts": {
|
|
101
|
+
"build": "tsup",
|
|
102
|
+
"dev": "tsup --watch",
|
|
103
|
+
"typecheck": "tsc --noEmit",
|
|
104
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
105
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
106
|
+
"test": "vitest run",
|
|
107
|
+
"test:watch": "vitest",
|
|
108
|
+
"test:coverage": "vitest run --coverage"
|
|
110
109
|
}
|
|
111
|
-
}
|
|
110
|
+
}
|