@fitzzero/quickdraw-core 3.9.1 → 4.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.
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Flags emitToRoom calls whose event name is row-list compensation —
3
+ * `*:created` / `*:deleted` / `*:updated` / `*:reordered` — the hand-wired
4
+ * stack that collection subscriptions (defineCollection + useCollection)
5
+ * replace with automatic, multi-node-safe deltas.
6
+ *
7
+ * Ship at "warn" while migrating; flip to "error" once collections cover
8
+ * the events. emitToRoomVolatile is deliberately not flagged — volatile
9
+ * emits are for ephemeral state, which is correctly not a collection.
10
+ */
11
+
12
+ const COMPENSATION_EVENT = /:(created|deleted|updated|reordered)$/;
13
+
14
+ /**
15
+ * Extract the static tail of an event-name argument: the whole string for
16
+ * a literal, the last quasi for a template literal (`${service}:created`).
17
+ */
18
+ function staticEventTail(node) {
19
+ if (node.type === "Literal" && typeof node.value === "string") {
20
+ return node.value;
21
+ }
22
+ if (node.type === "TemplateLiteral" && node.quasis.length > 0) {
23
+ return node.quasis[node.quasis.length - 1].value.cooked ?? "";
24
+ }
25
+ return null;
26
+ }
27
+
28
+ /** @type {import('eslint').Rule.RuleModule} */
29
+ export default {
30
+ meta: {
31
+ type: "suggestion",
32
+ docs: {
33
+ description:
34
+ "Disallow hand-emitted row add/remove/update events via emitToRoom. Declare a collection instead — defineCollection emits added/updated/removed deltas automatically (multi-node-safe, with reconnect re-snapshot).",
35
+ },
36
+ messages: {
37
+ declareCollection:
38
+ 'Hand-emitted "{{ eventName }}" is row-list compensation. Declare a collection instead: defineCollection() emits added/updated/removed deltas automatically, and useCollection() replaces the client-side merge.',
39
+ },
40
+ schema: [],
41
+ },
42
+ create(context) {
43
+ return {
44
+ CallExpression(node) {
45
+ const callee = node.callee;
46
+ if (
47
+ callee.type !== "MemberExpression" ||
48
+ callee.property.type !== "Identifier" ||
49
+ callee.property.name !== "emitToRoom"
50
+ ) {
51
+ return;
52
+ }
53
+
54
+ const eventArg = node.arguments[1];
55
+ if (!eventArg) return;
56
+
57
+ const tail = staticEventTail(eventArg);
58
+ if (tail !== null && COMPENSATION_EVENT.test(tail)) {
59
+ context.report({
60
+ node: eventArg,
61
+ messageId: "declareCollection",
62
+ data: { eventName: tail },
63
+ });
64
+ }
65
+ },
66
+ };
67
+ },
68
+ };
package/oxlint.base.jsonc CHANGED
@@ -77,6 +77,9 @@
77
77
  "quickdraw/require-zod-schema": "error",
78
78
  "quickdraw/no-service-method-record": "error",
79
79
  "quickdraw/no-unsafe-payload-cast": "error",
80
+ // Warn while migrating hand-emitted *:created/deleted/updated/
81
+ // reordered events to defineCollection; flip to error afterwards.
82
+ "quickdraw/no-manual-collection-events": "warn",
80
83
  },
81
84
  },
82
85
  // Client/React code: relax server-oriented strictness, enforce the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fitzzero/quickdraw-core",
3
- "version": "3.9.1",
3
+ "version": "4.1.0",
4
4
  "description": "Fast fullstack patterns for real-time applications with Socket.io and TanStack Query",
5
5
  "keywords": [
6
6
  "fullstack",