@fitzzero/quickdraw-core 3.9.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -25
- package/dist/client/index.d.ts +132 -6
- package/dist/client/index.js +492 -22
- package/dist/client/index.js.map +1 -1
- package/dist/client/testing.d.ts +1 -1
- package/dist/client/testing.js +3 -0
- package/dist/client/testing.js.map +1 -1
- package/dist/server/index.d.ts +402 -34
- package/dist/server/index.js +610 -89
- package/dist/server/index.js.map +1 -1
- package/dist/server/testing.d.ts +1 -1
- package/dist/server/testing.js +98 -3
- package/dist/server/testing.js.map +1 -1
- package/dist/shared/index.d.ts +154 -31
- package/dist/shared/index.js +16 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/{types-ClgSr90l.d.ts → types-87lWXyNP.d.ts} +36 -32
- package/dist/{types-DUHPIy_5.d.ts → types-CX5LuC_8.d.ts} +94 -2
- package/eslint-plugin-quickdraw/index.mjs +4 -0
- package/eslint-plugin-quickdraw/rules/no-manual-collection-events.mjs +68 -0
- package/oxlint.base.jsonc +3 -0
- package/package.json +1 -1
package/dist/client/testing.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { QueryClient } from '@tanstack/react-query';
|
|
3
3
|
import { ServiceResponse } from '../shared/index.js';
|
|
4
|
-
import { Q as QuickdrawSocketContextValue } from '../types-
|
|
4
|
+
import { Q as QuickdrawSocketContextValue } from '../types-CX5LuC_8.js';
|
|
5
5
|
import 'zod';
|
|
6
6
|
import 'socket.io-client';
|
|
7
7
|
|
package/dist/client/testing.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/testing.tsx"],"names":[],"mappings":"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","file":"testing.js","sourcesContent":["import * as React from \"react\";\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport type { Socket } from \"socket.io-client\";\nimport type { ServiceResponse } from \"../shared/types\";\nimport type { QuickdrawSocketContextValue } from \"./types\";\n\n// Generic mock function type that works with both Jest and Vitest\ntype MockFn = (...args: unknown[]) => unknown;\n\n/**\n * Mock socket for testing client components.\n */\nexport interface MockSocket {\n id: string;\n connected: boolean;\n emit: MockFn;\n on: MockFn;\n off: MockFn;\n disconnect: MockFn;\n}\n\n/**\n * Create a mock socket for testing.\n */\nexport function createMockSocket(): MockSocket {\n // Simple mock function that can be enhanced by the test framework\n const createMock = (): MockFn => {\n const fn: MockFn = () => undefined;\n return fn;\n };\n\n return {\n id: \"mock-socket-id\",\n connected: true,\n emit: createMock(),\n on: createMock(),\n off: createMock(),\n disconnect: createMock(),\n };\n}\n\n/**\n * Create a mock subscription registry for testing.\n */\nfunction createMockSubscriptionRegistry() {\n const subscriptions = new Map<string, { refCount: number; cleanup?: () => void }>();\n\n return {\n acquire: (key: string) => {\n const existing = subscriptions.get(key);\n if (existing) {\n existing.refCount++;\n return { isNew: false, entry: existing };\n }\n const entry = { refCount: 1 };\n subscriptions.set(key, entry);\n return { isNew: true, entry };\n },\n release: (key: string) => {\n const entry = subscriptions.get(key);\n if (!entry) return false;\n entry.refCount--;\n if (entry.refCount <= 0) {\n entry.cleanup?.();\n subscriptions.delete(key);\n return true;\n }\n return false;\n },\n setCleanup: (key: string, cleanup: () => void) => {\n const entry = subscriptions.get(key);\n if (entry) entry.cleanup = cleanup;\n },\n clear: () => subscriptions.clear(),\n };\n}\n\n/**\n * Create a mock QuickdrawSocketContextValue for testing.\n */\nexport function createMockSocketContext(\n overrides: Partial<QuickdrawSocketContextValue> = {},\n): QuickdrawSocketContextValue {\n const mockSocket = createMockSocket();\n\n return {\n socket: mockSocket as unknown as Socket,\n isConnected: true,\n userId: \"test-user-id\",\n serviceAccess: {},\n connect: () => {},\n disconnect: () => {},\n subscriptionRegistry: createMockSubscriptionRegistry(),\n subscriptionBatcher: { enqueue: () => {} },\n ...overrides,\n };\n}\n\n/**\n * Mock socket emit that resolves with a successful response.\n */\nexport function mockSuccessEmit<T>(\n data: T,\n): (_event: string, _payload: unknown, callback?: (response: ServiceResponse<T>) => void) => void {\n return (_event, _payload, callback) => {\n callback?.({ success: true, data });\n };\n}\n\n/**\n * Mock socket emit that resolves with an error response.\n */\nexport function mockErrorEmit(\n error: string,\n code?: number,\n): (\n _event: string,\n _payload: unknown,\n callback?: (response: ServiceResponse<unknown>) => void,\n) => void {\n return (_event, _payload, callback) => {\n const response: ServiceResponse<unknown> = { success: false, error };\n if (code !== undefined) {\n (response as { success: false; error: string; code: number }).code = code;\n }\n callback?.(response);\n };\n}\n\n/**\n * Create a mock QueryClient for testing.\n */\nexport function createMockQueryClient(): QueryClient {\n // Dynamic import to avoid bundling issues\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { QueryClient } = require(\"@tanstack/react-query\") as {\n QueryClient: new (options?: unknown) => QueryClient;\n };\n\n return new QueryClient({\n defaultOptions: {\n queries: {\n retry: false,\n gcTime: 0,\n },\n mutations: {\n retry: false,\n },\n },\n });\n}\n\n/**\n * Test wrapper component that provides the necessary context.\n */\nexport interface TestWrapperProps {\n children: React.ReactNode;\n socketContext?: Partial<QuickdrawSocketContextValue>;\n queryClient?: QueryClient;\n}\n\n/**\n * Create a test wrapper for rendering components with quickdraw context.\n *\n * @example\n * ```tsx\n * import { render } from '@testing-library/react';\n * import { createTestWrapper, createMockSocketContext, mockSuccessEmit } from '@quickdraw/core/client/testing';\n *\n * test('creates chat', async () => {\n * const mockSocket = createMockSocket();\n * mockSocket.emit.mockImplementation(mockSuccessEmit({ id: 'chat-123' }));\n *\n * const wrapper = createTestWrapper({\n * socketContext: { socket: mockSocket },\n * });\n *\n * const { getByText } = render(<CreateChatButton />, { wrapper });\n * // ...\n * });\n * ```\n */\nexport function createTestWrapper(\n options: Omit<TestWrapperProps, \"children\"> = {},\n): ({ children }: { children: React.ReactNode }) => React.ReactElement {\n const socketContext = createMockSocketContext(options.socketContext);\n const queryClient = options.queryClient ?? createMockQueryClient();\n\n // Create context for testing\n const QuickdrawSocketContext = React.createContext<QuickdrawSocketContextValue | null>(null);\n\n return function TestWrapper({ children }: { children: React.ReactNode }): React.ReactElement {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { QueryClientProvider } = require(\"@tanstack/react-query\") as {\n QueryClientProvider: React.ComponentType<{ client: QueryClient; children: React.ReactNode }>;\n };\n\n return (\n <QueryClientProvider client={queryClient}>\n <QuickdrawSocketContext.Provider value={socketContext}>\n {children}\n </QuickdrawSocketContext.Provider>\n </QueryClientProvider>\n );\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/client/testing.tsx"],"names":[],"mappings":"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","file":"testing.js","sourcesContent":["import * as React from \"react\";\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport type { Socket } from \"socket.io-client\";\nimport type { ServiceResponse } from \"../shared/types\";\nimport type { QuickdrawSocketContextValue } from \"./types\";\n\n// Generic mock function type that works with both Jest and Vitest\ntype MockFn = (...args: unknown[]) => unknown;\n\n/**\n * Mock socket for testing client components.\n */\nexport interface MockSocket {\n id: string;\n connected: boolean;\n emit: MockFn;\n on: MockFn;\n off: MockFn;\n disconnect: MockFn;\n}\n\n/**\n * Create a mock socket for testing.\n */\nexport function createMockSocket(): MockSocket {\n // Simple mock function that can be enhanced by the test framework\n const createMock = (): MockFn => {\n const fn: MockFn = () => undefined;\n return fn;\n };\n\n return {\n id: \"mock-socket-id\",\n connected: true,\n emit: createMock(),\n on: createMock(),\n off: createMock(),\n disconnect: createMock(),\n };\n}\n\n/**\n * Create a mock subscription registry for testing.\n */\nfunction createMockSubscriptionRegistry() {\n const subscriptions = new Map<string, { refCount: number; cleanup?: () => void }>();\n\n return {\n acquire: (key: string) => {\n const existing = subscriptions.get(key);\n if (existing) {\n existing.refCount++;\n return { isNew: false, entry: existing };\n }\n const entry = { refCount: 1 };\n subscriptions.set(key, entry);\n return { isNew: true, entry };\n },\n release: (key: string) => {\n const entry = subscriptions.get(key);\n if (!entry) return false;\n entry.refCount--;\n if (entry.refCount <= 0) {\n entry.cleanup?.();\n subscriptions.delete(key);\n return true;\n }\n return false;\n },\n setCleanup: (key: string, cleanup: () => void) => {\n const entry = subscriptions.get(key);\n if (entry) entry.cleanup = cleanup;\n },\n clear: () => subscriptions.clear(),\n };\n}\n\n/**\n * Create a mock QuickdrawSocketContextValue for testing.\n */\nexport function createMockSocketContext(\n overrides: Partial<QuickdrawSocketContextValue> = {},\n): QuickdrawSocketContextValue {\n const mockSocket = createMockSocket();\n\n return {\n socket: mockSocket as unknown as Socket,\n isConnected: true,\n userId: \"test-user-id\",\n serviceAccess: {},\n connect: () => {},\n disconnect: () => {},\n subscriptionRegistry: createMockSubscriptionRegistry(),\n subscriptionBatcher: { enqueue: () => {} },\n isRateLimited: false,\n reportRateLimited: () => {},\n ...overrides,\n };\n}\n\n/**\n * Mock socket emit that resolves with a successful response.\n */\nexport function mockSuccessEmit<T>(\n data: T,\n): (_event: string, _payload: unknown, callback?: (response: ServiceResponse<T>) => void) => void {\n return (_event, _payload, callback) => {\n callback?.({ success: true, data });\n };\n}\n\n/**\n * Mock socket emit that resolves with an error response.\n */\nexport function mockErrorEmit(\n error: string,\n code?: number,\n): (\n _event: string,\n _payload: unknown,\n callback?: (response: ServiceResponse<unknown>) => void,\n) => void {\n return (_event, _payload, callback) => {\n const response: ServiceResponse<unknown> = { success: false, error };\n if (code !== undefined) {\n (response as { success: false; error: string; code: number }).code = code;\n }\n callback?.(response);\n };\n}\n\n/**\n * Create a mock QueryClient for testing.\n */\nexport function createMockQueryClient(): QueryClient {\n // Dynamic import to avoid bundling issues\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { QueryClient } = require(\"@tanstack/react-query\") as {\n QueryClient: new (options?: unknown) => QueryClient;\n };\n\n return new QueryClient({\n defaultOptions: {\n queries: {\n retry: false,\n gcTime: 0,\n },\n mutations: {\n retry: false,\n },\n },\n });\n}\n\n/**\n * Test wrapper component that provides the necessary context.\n */\nexport interface TestWrapperProps {\n children: React.ReactNode;\n socketContext?: Partial<QuickdrawSocketContextValue>;\n queryClient?: QueryClient;\n}\n\n/**\n * Create a test wrapper for rendering components with quickdraw context.\n *\n * @example\n * ```tsx\n * import { render } from '@testing-library/react';\n * import { createTestWrapper, createMockSocketContext, mockSuccessEmit } from '@quickdraw/core/client/testing';\n *\n * test('creates chat', async () => {\n * const mockSocket = createMockSocket();\n * mockSocket.emit.mockImplementation(mockSuccessEmit({ id: 'chat-123' }));\n *\n * const wrapper = createTestWrapper({\n * socketContext: { socket: mockSocket },\n * });\n *\n * const { getByText } = render(<CreateChatButton />, { wrapper });\n * // ...\n * });\n * ```\n */\nexport function createTestWrapper(\n options: Omit<TestWrapperProps, \"children\"> = {},\n): ({ children }: { children: React.ReactNode }) => React.ReactElement {\n const socketContext = createMockSocketContext(options.socketContext);\n const queryClient = options.queryClient ?? createMockQueryClient();\n\n // Create context for testing\n const QuickdrawSocketContext = React.createContext<QuickdrawSocketContextValue | null>(null);\n\n return function TestWrapper({ children }: { children: React.ReactNode }): React.ReactElement {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { QueryClientProvider } = require(\"@tanstack/react-query\") as {\n QueryClientProvider: React.ComponentType<{ client: QueryClient; children: React.ReactNode }>;\n };\n\n return (\n <QueryClientProvider client={queryClient}>\n <QuickdrawSocketContext.Provider value={socketContext}>\n {children}\n </QuickdrawSocketContext.Provider>\n </QueryClientProvider>\n );\n };\n}\n"]}
|