@fitzzero/quickdraw-core 3.8.0 → 3.9.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 CHANGED
@@ -352,18 +352,52 @@ import {
352
352
  import { createMockSocket, createTestWrapper } from "@fitzzero/quickdraw-core/client/testing";
353
353
  ```
354
354
 
355
+ ## Linting
356
+
357
+ The package ships a shared oxlint base config, `oxlint.base.jsonc` — the
358
+ framework's lint best practices (strict type-safety, complexity budgets, and
359
+ the `quickdraw` plugin rules pre-wired for `services/**` and client code).
360
+ Extend it from your root `.oxlintrc.json` so best practices update with the
361
+ package:
362
+
363
+ ```jsonc
364
+ {
365
+ "extends": ["./node_modules/@fitzzero/quickdraw-core/oxlint.base.jsonc"],
366
+ // plugins are NOT purely inherited: omitting this array unions oxlint's
367
+ // default plugin set into the merge — mirror the base's list.
368
+ "plugins": ["typescript", "import", "react", "nextjs", "jsx_a11y"],
369
+ // ignorePatterns, env, globals, and settings are not inherited — declare here.
370
+ "ignorePatterns": ["**/dist/**", "**/node_modules/**"],
371
+ "overrides": [
372
+ // Project-specific relaxations win over the base (overrides concatenate,
373
+ // consumer last), e.g. allow specific cross-service mutations:
374
+ {
375
+ "files": ["**/services/**/*.ts"],
376
+ "rules": {
377
+ "quickdraw/no-cross-service-mutations": [
378
+ "error",
379
+ { "allowedModels": { "chat": ["chatMember"] } },
380
+ ],
381
+ },
382
+ },
383
+ ],
384
+ }
385
+ ```
386
+
387
+ The base config also loads `./eslint-plugin` (the `quickdraw` rules) via
388
+ `jsPlugins` — no separate wiring needed. The `./eslint-config` export (ESLint
389
+ flat config) is legacy; prefer the oxlint base.
390
+
355
391
  ## Local Development
356
392
 
357
393
  This package is developed alongside [quickdraw-chat](https://github.com/fitzzero/quickdraw-chat), a reference implementation.
358
394
 
359
- ### Using pnpm link
395
+ quickdraw-chat consumes the published npm package. For local iteration
396
+ against a checkout, use `bun link` (or point lint `extends` at the sibling
397
+ path), and always re-verify against a published version before releasing:
360
398
 
361
399
  ```bash
362
- # In quickdraw-chat, the package is linked:
363
- "@fitzzero/quickdraw-core": "link:../../../quickdraw"
364
-
365
- # Changes to quickdraw-core are instantly available after rebuild
366
- pnpm build # or pnpm dev for watch mode
400
+ bun run build # or bun run dev for watch mode
367
401
  ```
368
402
 
369
403
  ## Type Definitions
@@ -0,0 +1,123 @@
1
+ // Shared oxlint base config for quickdraw apps.
2
+ //
3
+ // Consume from a project by extending it in your root .oxlintrc.json:
4
+ //
5
+ // {
6
+ // "extends": ["./node_modules/@fitzzero/quickdraw-core/oxlint.base.jsonc"],
7
+ // ...project-specific config
8
+ // }
9
+ //
10
+ // oxlint merge semantics (v1.x): `rules` and `categories` merge per-key with
11
+ // the extending config winning; `overrides` concatenate (base first, so a
12
+ // consumer override on the same glob wins); `jsPlugins` concatenate.
13
+ // NOT inherited — declare these in the consumer config:
14
+ // - `ignorePatterns`, `env`, `globals`, `settings`
15
+ // - `plugins`: if the consumer omits its `plugins` array, oxlint unions the
16
+ // DEFAULT plugin set into the merge — mirror the list below to avoid
17
+ // surprise diagnostics from plugins you didn't opt into.
18
+ {
19
+ "plugins": ["typescript", "import", "react", "nextjs", "jsx_a11y"],
20
+ "categories": {
21
+ "correctness": "deny",
22
+ "suspicious": "deny",
23
+ "pedantic": "deny",
24
+ },
25
+ // The quickdraw framework rules, shipped alongside this file.
26
+ // The relative specifier resolves against this file's location, i.e. inside
27
+ // the installed package — consumers don't need their own jsPlugins entry.
28
+ "jsPlugins": [
29
+ {
30
+ "name": "quickdraw",
31
+ "specifier": "./eslint-plugin-quickdraw/index.mjs",
32
+ },
33
+ ],
34
+ "rules": {
35
+ "react/rules-of-hooks": "error",
36
+ "no-console": "error",
37
+ "no-var": "error",
38
+ "typescript/no-explicit-any": "error",
39
+ "typescript/no-non-null-assertion": "error",
40
+ "typescript/no-import-type-side-effects": "error",
41
+
42
+ "typescript/no-unsafe-assignment": "error",
43
+ "typescript/no-unsafe-call": "error",
44
+ "typescript/no-unsafe-member-access": "error",
45
+ "typescript/no-unsafe-return": "error",
46
+ "typescript/no-unsafe-argument": "error",
47
+ "typescript/restrict-template-expressions": "off",
48
+ "typescript/no-redundant-type-constituents": "off",
49
+
50
+ "require-await": "error",
51
+ "no-inline-comments": "error",
52
+ "no-unmodified-loop-condition": "error",
53
+ "no-promise-executor-return": "error",
54
+ "eqeqeq": "error",
55
+ "import/max-dependencies": ["error", { "max": 10 }],
56
+
57
+ // Complexity budgets: keep units small enough to reason about (and small
58
+ // enough for focused AI edits).
59
+ "complexity": ["error", { "max": 15 }],
60
+ "max-depth": ["error", { "max": 4 }],
61
+ "max-lines": ["error", { "max": 500, "skipBlankLines": true, "skipComments": true }],
62
+ "max-lines-per-function": [
63
+ "error",
64
+ { "max": 80, "skipBlankLines": true, "skipComments": true },
65
+ ],
66
+ },
67
+ "overrides": [
68
+ // Service layer: enforce the quickdraw service contract.
69
+ // `no-cross-service-mutations` ships with an EMPTY allowlist (strictest).
70
+ // Projects relax it with their own services override, e.g.:
71
+ // { "files": ["**/services/**/*.ts"], "rules": { "quickdraw/no-cross-service-mutations": ["error", { "allowedModels": { "chat": ["chatMember"] } }] } }
72
+ {
73
+ "files": ["**/services/**/*.ts"],
74
+ "rules": {
75
+ "quickdraw/no-raw-service-room-string": "error",
76
+ "quickdraw/no-cross-service-mutations": "error",
77
+ "quickdraw/require-zod-schema": "error",
78
+ "quickdraw/no-service-method-record": "error",
79
+ "quickdraw/no-unsafe-payload-cast": "error",
80
+ },
81
+ },
82
+ // Client/React code: relax server-oriented strictness, enforce the
83
+ // typed-socket and design-system rules instead.
84
+ {
85
+ "files": ["apps/web/**", "**/*.tsx"],
86
+ "rules": {
87
+ "typescript/explicit-function-return-type": "off",
88
+ "jsx_a11y/no-autofocus": "off",
89
+ "react/react-in-jsx-scope": "off",
90
+ "import/no-unassigned-import": "off",
91
+ "import/max-dependencies": "off",
92
+ "max-lines-per-function": "off",
93
+ "max-lines": "off",
94
+ "no-warning-comments": "off",
95
+ "quickdraw/no-raw-tooltip-strings": "error",
96
+ "quickdraw/no-raw-typography-strings": "error",
97
+ "quickdraw/no-raw-button-strings": "error",
98
+ "quickdraw/no-raw-socket-on": "error",
99
+ "quickdraw/no-raw-socket-emit": "error",
100
+ },
101
+ },
102
+ // Shared/db packages: public surface — explicit types required.
103
+ {
104
+ "files": ["packages/shared/**", "packages/db/**"],
105
+ "rules": {
106
+ "typescript/explicit-function-return-type": "error",
107
+ "typescript/explicit-module-boundary-types": "error",
108
+ "no-console": "error",
109
+ },
110
+ },
111
+ // Tests: size and style budgets don't apply.
112
+ {
113
+ "files": ["**/__tests__/**", "**/*.test.ts", "**/*.test.tsx"],
114
+ "rules": {
115
+ "max-lines-per-function": "off",
116
+ "max-lines": "off",
117
+ "no-inline-comments": "off",
118
+ "require-await": "off",
119
+ "import/max-dependencies": "off",
120
+ },
121
+ },
122
+ ],
123
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fitzzero/quickdraw-core",
3
- "version": "3.8.0",
3
+ "version": "3.9.0",
4
4
  "description": "Fast fullstack patterns for real-time applications with Socket.io and TanStack Query",
5
5
  "keywords": [
6
6
  "fullstack",
@@ -15,7 +15,8 @@
15
15
  "files": [
16
16
  "dist",
17
17
  "eslint-plugin-quickdraw",
18
- "eslint-config"
18
+ "eslint-config",
19
+ "oxlint.base.jsonc"
19
20
  ],
20
21
  "type": "module",
21
22
  "main": "./dist/shared/index.js",