@spoosh/plugin-optimistic 0.7.0 → 0.7.2

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/dist/index.d.mts CHANGED
@@ -1,4 +1,5 @@
1
- import { ReadPaths, FindMatchingKey, HasParams, ExtractParamNames, Simplify, ExtractData, SpooshPlugin } from '@spoosh/core';
1
+ import * as _spoosh_core from '@spoosh/core';
2
+ import { ReadPaths, FindMatchingKey, HasParams, ExtractParamNames, Simplify, ExtractData } from '@spoosh/core';
2
3
 
3
4
  /**
4
5
  * Check if query exists in the method config.
@@ -54,7 +55,7 @@ declare const COMPLETED_BRAND: unique symbol;
54
55
  * @typeParam TUsed - Tracks which methods have been called to prevent duplicate calls
55
56
  * @typeParam TCompleted - Tracks whether UPDATE_CACHE was called (required for valid builder)
56
57
  */
57
- type OptimisticBuilder<TData = unknown, TMethodConfig = unknown, TUserPath extends string = string, TResponse = unknown, TTiming extends "immediate" | "onSuccess" = "immediate", TUsed extends string = never, TCompleted extends boolean = false> = (TCompleted extends true ? {
58
+ type OptimisticBuilder<TData = unknown, TMethodConfig = unknown, TUserPath extends string = string, TResponse = unknown, TError = unknown, TTiming extends "immediate" | "onSuccess" = "immediate", TUsed extends string = never, TCompleted extends boolean = false> = (TCompleted extends true ? {
58
59
  readonly [COMPLETED_BRAND]: true;
59
60
  } : unknown) & {
60
61
  /**
@@ -67,7 +68,7 @@ type OptimisticBuilder<TData = unknown, TMethodConfig = unknown, TUserPath exten
67
68
  * .WHERE(entry => entry.query.page === 1)
68
69
  * ```
69
70
  */
70
- WHERE: IfNotUsed<"WHERE", TUsed, WhereOptions<TMethodConfig, TUserPath> extends never ? never : (predicate: (entry: Simplify<WhereOptions<TMethodConfig, TUserPath>>) => boolean) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "WHERE", TCompleted>>;
71
+ WHERE: IfNotUsed<"WHERE", TUsed, WhereOptions<TMethodConfig, TUserPath> extends never ? never : (predicate: (entry: Simplify<WhereOptions<TMethodConfig, TUserPath>>) => boolean) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, TTiming, TUsed | "WHERE", TCompleted>>;
71
72
  /**
72
73
  * Specify how to update the cached data optimistically.
73
74
  * This method is required - an optimistic update must have an updater function.
@@ -77,37 +78,37 @@ type OptimisticBuilder<TData = unknown, TMethodConfig = unknown, TUserPath exten
77
78
  *
78
79
  * @param updater - Function that receives current data (and response if ON_SUCCESS), returns updated data
79
80
  */
80
- UPDATE_CACHE: IfNotUsed<"UPDATE_CACHE", TUsed, TTiming extends "onSuccess" ? (updater: (data: TData, response: TResponse) => TData) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "UPDATE_CACHE", true> : (updater: (data: TData) => TData) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "UPDATE_CACHE", true>>;
81
+ UPDATE_CACHE: IfNotUsed<"UPDATE_CACHE", TUsed, TTiming extends "onSuccess" ? (updater: (data: TData, response: TResponse) => TData) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, TTiming, TUsed | "UPDATE_CACHE", true> : (updater: (data: TData) => TData) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, TTiming, TUsed | "UPDATE_CACHE", true>>;
81
82
  /**
82
83
  * Apply optimistic update only after mutation succeeds.
83
84
  * By default, updates are applied immediately before mutation completes.
84
85
  * When using ON_SUCCESS, UPDATE_CACHE receives the mutation response as second argument.
85
86
  */
86
- ON_SUCCESS: IfNotUsed<"ON_SUCCESS", TUsed, () => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, "onSuccess", TUsed | "ON_SUCCESS", TCompleted>>;
87
+ ON_SUCCESS: IfNotUsed<"ON_SUCCESS", TUsed, () => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, "onSuccess", TUsed | "ON_SUCCESS", TCompleted>>;
87
88
  /**
88
89
  * Disable automatic rollback when mutation fails.
89
90
  * By default, optimistic updates are rolled back on error.
90
91
  */
91
- NO_ROLLBACK: IfNotUsed<"NO_ROLLBACK", TUsed, () => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "NO_ROLLBACK", TCompleted>>;
92
+ NO_ROLLBACK: IfNotUsed<"NO_ROLLBACK", TUsed, () => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, TTiming, TUsed | "NO_ROLLBACK", TCompleted>>;
92
93
  /**
93
94
  * Callback when mutation fails.
94
95
  */
95
- ON_ERROR: IfNotUsed<"ON_ERROR", TUsed, (callback: (error: unknown) => void) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "ON_ERROR", TCompleted>>;
96
+ ON_ERROR: IfNotUsed<"ON_ERROR", TUsed, (callback: (error: TError) => void) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, TTiming, TUsed | "ON_ERROR", TCompleted>>;
96
97
  };
97
98
  /**
98
99
  * Path methods proxy for optimistic API - only GET.
99
100
  * Resolves literal paths (e.g., "posts/1") to schema keys (e.g., "posts/:id") using FindMatchingKey.
100
101
  * Uses TPath for param extraction to preserve user's param names.
101
102
  */
102
- type OptimisticPathMethods<TSchema, TPath extends string, TResponse> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? TSchema[TKey] extends infer TRoute ? "GET" extends keyof TRoute ? TRoute["GET"] extends infer TGetConfig ? {
103
- GET: () => OptimisticBuilder<ExtractData<TGetConfig>, TGetConfig, TPath, TResponse, "immediate", never, false>;
103
+ type OptimisticPathMethods<TSchema, TPath extends string, TResponse, TError> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? TSchema[TKey] extends infer TRoute ? "GET" extends keyof TRoute ? TRoute["GET"] extends infer TGetConfig ? {
104
+ GET: () => OptimisticBuilder<ExtractData<TGetConfig>, TGetConfig, TPath, TResponse, TError, "immediate", never, false>;
104
105
  } : never : never : never : never : never;
105
106
  /**
106
107
  * Helper type for creating the optimistic API proxy.
107
108
  * Accepts both schema-defined paths (e.g., "posts/:id") and literal paths (e.g., "posts/1").
108
109
  * Uses union with (string & {}) to allow any string while preserving autocomplete.
109
110
  */
110
- type OptimisticApiHelper<TSchema, TResponse = unknown> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) => OptimisticPathMethods<TSchema, TPath, TResponse>;
111
+ type OptimisticApiHelper<TSchema, TResponse = unknown, TError = unknown> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) => OptimisticPathMethods<TSchema, TPath, TResponse, TError>;
111
112
  /**
112
113
  * A generic OptimisticTarget that accepts any data/response types.
113
114
  * Used for the return type of the callback.
@@ -160,10 +161,10 @@ type CompletedOptimisticBuilder = {
160
161
  * ]
161
162
  * ```
162
163
  */
163
- type OptimisticCallbackFn<TSchema = unknown, TResponse = unknown> = (api: OptimisticApiHelper<TSchema, TResponse>) => CompletedOptimisticBuilder | CompletedOptimisticBuilder[];
164
+ type OptimisticCallbackFn<TSchema = unknown, TResponse = unknown, TError = unknown> = (api: OptimisticApiHelper<TSchema, TResponse, TError>) => CompletedOptimisticBuilder | CompletedOptimisticBuilder[];
164
165
  type OptimisticPluginConfig = object;
165
166
  type OptimisticWriteOptions = object;
166
- interface OptimisticWriteTriggerOptions<TSchema = unknown, TResponse = unknown> {
167
+ interface OptimisticWriteTriggerOptions<TSchema = unknown, TResponse = unknown, TError = unknown> {
167
168
  /**
168
169
  * Configure optimistic updates for this mutation.
169
170
  *
@@ -200,7 +201,7 @@ interface OptimisticWriteTriggerOptions<TSchema = unknown, TResponse = unknown>
200
201
  * });
201
202
  * ```
202
203
  */
203
- optimistic?: OptimisticCallbackFn<TSchema, TResponse>;
204
+ optimistic?: OptimisticCallbackFn<TSchema, TResponse, TError>;
204
205
  }
205
206
  type OptimisticReadOptions = object;
206
207
  type OptimisticPagesOptions = object;
@@ -210,11 +211,11 @@ interface OptimisticReadResult {
210
211
  type OptimisticWriteResult = object;
211
212
  declare module "@spoosh/core" {
212
213
  interface PluginResolvers<TContext> {
213
- optimistic: OptimisticCallbackFn<TContext["schema"], TContext["data"]> | undefined;
214
+ optimistic: OptimisticCallbackFn<TContext["schema"], TContext["data"], TContext["error"]> | undefined;
214
215
  }
215
216
  }
216
217
 
217
- declare function optimisticPlugin(): SpooshPlugin<{
218
+ declare function optimisticPlugin(): _spoosh_core.SpooshPlugin<{
218
219
  readOptions: OptimisticReadOptions;
219
220
  writeOptions: OptimisticWriteOptions;
220
221
  writeTriggerOptions: OptimisticWriteTriggerOptions;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { ReadPaths, FindMatchingKey, HasParams, ExtractParamNames, Simplify, ExtractData, SpooshPlugin } from '@spoosh/core';
1
+ import * as _spoosh_core from '@spoosh/core';
2
+ import { ReadPaths, FindMatchingKey, HasParams, ExtractParamNames, Simplify, ExtractData } from '@spoosh/core';
2
3
 
3
4
  /**
4
5
  * Check if query exists in the method config.
@@ -54,7 +55,7 @@ declare const COMPLETED_BRAND: unique symbol;
54
55
  * @typeParam TUsed - Tracks which methods have been called to prevent duplicate calls
55
56
  * @typeParam TCompleted - Tracks whether UPDATE_CACHE was called (required for valid builder)
56
57
  */
57
- type OptimisticBuilder<TData = unknown, TMethodConfig = unknown, TUserPath extends string = string, TResponse = unknown, TTiming extends "immediate" | "onSuccess" = "immediate", TUsed extends string = never, TCompleted extends boolean = false> = (TCompleted extends true ? {
58
+ type OptimisticBuilder<TData = unknown, TMethodConfig = unknown, TUserPath extends string = string, TResponse = unknown, TError = unknown, TTiming extends "immediate" | "onSuccess" = "immediate", TUsed extends string = never, TCompleted extends boolean = false> = (TCompleted extends true ? {
58
59
  readonly [COMPLETED_BRAND]: true;
59
60
  } : unknown) & {
60
61
  /**
@@ -67,7 +68,7 @@ type OptimisticBuilder<TData = unknown, TMethodConfig = unknown, TUserPath exten
67
68
  * .WHERE(entry => entry.query.page === 1)
68
69
  * ```
69
70
  */
70
- WHERE: IfNotUsed<"WHERE", TUsed, WhereOptions<TMethodConfig, TUserPath> extends never ? never : (predicate: (entry: Simplify<WhereOptions<TMethodConfig, TUserPath>>) => boolean) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "WHERE", TCompleted>>;
71
+ WHERE: IfNotUsed<"WHERE", TUsed, WhereOptions<TMethodConfig, TUserPath> extends never ? never : (predicate: (entry: Simplify<WhereOptions<TMethodConfig, TUserPath>>) => boolean) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, TTiming, TUsed | "WHERE", TCompleted>>;
71
72
  /**
72
73
  * Specify how to update the cached data optimistically.
73
74
  * This method is required - an optimistic update must have an updater function.
@@ -77,37 +78,37 @@ type OptimisticBuilder<TData = unknown, TMethodConfig = unknown, TUserPath exten
77
78
  *
78
79
  * @param updater - Function that receives current data (and response if ON_SUCCESS), returns updated data
79
80
  */
80
- UPDATE_CACHE: IfNotUsed<"UPDATE_CACHE", TUsed, TTiming extends "onSuccess" ? (updater: (data: TData, response: TResponse) => TData) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "UPDATE_CACHE", true> : (updater: (data: TData) => TData) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "UPDATE_CACHE", true>>;
81
+ UPDATE_CACHE: IfNotUsed<"UPDATE_CACHE", TUsed, TTiming extends "onSuccess" ? (updater: (data: TData, response: TResponse) => TData) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, TTiming, TUsed | "UPDATE_CACHE", true> : (updater: (data: TData) => TData) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, TTiming, TUsed | "UPDATE_CACHE", true>>;
81
82
  /**
82
83
  * Apply optimistic update only after mutation succeeds.
83
84
  * By default, updates are applied immediately before mutation completes.
84
85
  * When using ON_SUCCESS, UPDATE_CACHE receives the mutation response as second argument.
85
86
  */
86
- ON_SUCCESS: IfNotUsed<"ON_SUCCESS", TUsed, () => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, "onSuccess", TUsed | "ON_SUCCESS", TCompleted>>;
87
+ ON_SUCCESS: IfNotUsed<"ON_SUCCESS", TUsed, () => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, "onSuccess", TUsed | "ON_SUCCESS", TCompleted>>;
87
88
  /**
88
89
  * Disable automatic rollback when mutation fails.
89
90
  * By default, optimistic updates are rolled back on error.
90
91
  */
91
- NO_ROLLBACK: IfNotUsed<"NO_ROLLBACK", TUsed, () => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "NO_ROLLBACK", TCompleted>>;
92
+ NO_ROLLBACK: IfNotUsed<"NO_ROLLBACK", TUsed, () => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, TTiming, TUsed | "NO_ROLLBACK", TCompleted>>;
92
93
  /**
93
94
  * Callback when mutation fails.
94
95
  */
95
- ON_ERROR: IfNotUsed<"ON_ERROR", TUsed, (callback: (error: unknown) => void) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "ON_ERROR", TCompleted>>;
96
+ ON_ERROR: IfNotUsed<"ON_ERROR", TUsed, (callback: (error: TError) => void) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TError, TTiming, TUsed | "ON_ERROR", TCompleted>>;
96
97
  };
97
98
  /**
98
99
  * Path methods proxy for optimistic API - only GET.
99
100
  * Resolves literal paths (e.g., "posts/1") to schema keys (e.g., "posts/:id") using FindMatchingKey.
100
101
  * Uses TPath for param extraction to preserve user's param names.
101
102
  */
102
- type OptimisticPathMethods<TSchema, TPath extends string, TResponse> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? TSchema[TKey] extends infer TRoute ? "GET" extends keyof TRoute ? TRoute["GET"] extends infer TGetConfig ? {
103
- GET: () => OptimisticBuilder<ExtractData<TGetConfig>, TGetConfig, TPath, TResponse, "immediate", never, false>;
103
+ type OptimisticPathMethods<TSchema, TPath extends string, TResponse, TError> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? TSchema[TKey] extends infer TRoute ? "GET" extends keyof TRoute ? TRoute["GET"] extends infer TGetConfig ? {
104
+ GET: () => OptimisticBuilder<ExtractData<TGetConfig>, TGetConfig, TPath, TResponse, TError, "immediate", never, false>;
104
105
  } : never : never : never : never : never;
105
106
  /**
106
107
  * Helper type for creating the optimistic API proxy.
107
108
  * Accepts both schema-defined paths (e.g., "posts/:id") and literal paths (e.g., "posts/1").
108
109
  * Uses union with (string & {}) to allow any string while preserving autocomplete.
109
110
  */
110
- type OptimisticApiHelper<TSchema, TResponse = unknown> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) => OptimisticPathMethods<TSchema, TPath, TResponse>;
111
+ type OptimisticApiHelper<TSchema, TResponse = unknown, TError = unknown> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) => OptimisticPathMethods<TSchema, TPath, TResponse, TError>;
111
112
  /**
112
113
  * A generic OptimisticTarget that accepts any data/response types.
113
114
  * Used for the return type of the callback.
@@ -160,10 +161,10 @@ type CompletedOptimisticBuilder = {
160
161
  * ]
161
162
  * ```
162
163
  */
163
- type OptimisticCallbackFn<TSchema = unknown, TResponse = unknown> = (api: OptimisticApiHelper<TSchema, TResponse>) => CompletedOptimisticBuilder | CompletedOptimisticBuilder[];
164
+ type OptimisticCallbackFn<TSchema = unknown, TResponse = unknown, TError = unknown> = (api: OptimisticApiHelper<TSchema, TResponse, TError>) => CompletedOptimisticBuilder | CompletedOptimisticBuilder[];
164
165
  type OptimisticPluginConfig = object;
165
166
  type OptimisticWriteOptions = object;
166
- interface OptimisticWriteTriggerOptions<TSchema = unknown, TResponse = unknown> {
167
+ interface OptimisticWriteTriggerOptions<TSchema = unknown, TResponse = unknown, TError = unknown> {
167
168
  /**
168
169
  * Configure optimistic updates for this mutation.
169
170
  *
@@ -200,7 +201,7 @@ interface OptimisticWriteTriggerOptions<TSchema = unknown, TResponse = unknown>
200
201
  * });
201
202
  * ```
202
203
  */
203
- optimistic?: OptimisticCallbackFn<TSchema, TResponse>;
204
+ optimistic?: OptimisticCallbackFn<TSchema, TResponse, TError>;
204
205
  }
205
206
  type OptimisticReadOptions = object;
206
207
  type OptimisticPagesOptions = object;
@@ -210,11 +211,11 @@ interface OptimisticReadResult {
210
211
  type OptimisticWriteResult = object;
211
212
  declare module "@spoosh/core" {
212
213
  interface PluginResolvers<TContext> {
213
- optimistic: OptimisticCallbackFn<TContext["schema"], TContext["data"]> | undefined;
214
+ optimistic: OptimisticCallbackFn<TContext["schema"], TContext["data"], TContext["error"]> | undefined;
214
215
  }
215
216
  }
216
217
 
217
- declare function optimisticPlugin(): SpooshPlugin<{
218
+ declare function optimisticPlugin(): _spoosh_core.SpooshPlugin<{
218
219
  readOptions: OptimisticReadOptions;
219
220
  writeOptions: OptimisticWriteOptions;
220
221
  writeTriggerOptions: OptimisticWriteTriggerOptions;
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ __export(src_exports, {
25
25
  module.exports = __toCommonJS(src_exports);
26
26
 
27
27
  // src/plugin.ts
28
+ var import_core = require("@spoosh/core");
28
29
  var import_plugin_invalidation = require("@spoosh/plugin-invalidation");
29
30
  function createBuilder(state) {
30
31
  return {
@@ -277,7 +278,7 @@ function buildSnapshotDiff(snapshots, mode = "apply") {
277
278
  }
278
279
  var PLUGIN_NAME = "spoosh:optimistic";
279
280
  function optimisticPlugin() {
280
- return {
281
+ return (0, import_core.createSpooshPlugin)({
281
282
  name: PLUGIN_NAME,
282
283
  operations: ["write"],
283
284
  dependencies: ["spoosh:invalidation"],
@@ -382,5 +383,5 @@ function optimisticPlugin() {
382
383
  }
383
384
  return response;
384
385
  }
385
- };
386
+ });
386
387
  }
package/dist/index.mjs CHANGED
@@ -1,4 +1,7 @@
1
1
  // src/plugin.ts
2
+ import {
3
+ createSpooshPlugin
4
+ } from "@spoosh/core";
2
5
  import "@spoosh/plugin-invalidation";
3
6
  function createBuilder(state) {
4
7
  return {
@@ -251,7 +254,7 @@ function buildSnapshotDiff(snapshots, mode = "apply") {
251
254
  }
252
255
  var PLUGIN_NAME = "spoosh:optimistic";
253
256
  function optimisticPlugin() {
254
- return {
257
+ return createSpooshPlugin({
255
258
  name: PLUGIN_NAME,
256
259
  operations: ["write"],
257
260
  dependencies: ["spoosh:invalidation"],
@@ -356,7 +359,7 @@ function optimisticPlugin() {
356
359
  }
357
360
  return response;
358
361
  }
359
- };
362
+ });
360
363
  }
361
364
  export {
362
365
  optimisticPlugin
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spoosh/plugin-optimistic",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "Optimistic updates plugin for Spoosh - instant UI updates with automatic rollback",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -37,8 +37,8 @@
37
37
  "@spoosh/plugin-invalidation": ">=0.7.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@spoosh/core": "0.15.0",
41
- "@spoosh/plugin-invalidation": "0.9.0",
40
+ "@spoosh/core": "0.16.0",
41
+ "@spoosh/plugin-invalidation": "0.9.1",
42
42
  "@spoosh/test-utils": "0.3.0"
43
43
  },
44
44
  "scripts": {
@@ -46,6 +46,6 @@
46
46
  "build": "tsup",
47
47
  "typecheck": "tsc --noEmit",
48
48
  "lint": "eslint src --max-warnings 0",
49
- "format": "prettier --write 'src/**/*.ts'"
49
+ "format": "prettier --write 'src/**/*.ts' '*.md'"
50
50
  }
51
51
  }