@qlover/fe-corekit 3.1.0 → 3.2.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/dist/index.cjs CHANGED
@@ -51,15 +51,20 @@ __export(index_exports, {
51
51
  ResponsePlugin: () => ResponsePlugin,
52
52
  RetryPlugin: () => RetryPlugin,
53
53
  SimpleUrlBuilder: () => SimpleUrlBuilder,
54
- SyncStorage: () => SyncStorage,
54
+ StorageExecutor: () => StorageExecutor,
55
55
  appendHeaders: () => appendHeaders,
56
56
  createAbortPromise: () => createAbortPromise,
57
+ createStoragePlugin: () => createStoragePlugin,
58
+ createStoragePluginWithStorage: () => createStoragePluginWithStorage,
57
59
  hasObjectKey: () => hasObjectKey,
58
60
  hasObjectKeyWithValue: () => hasObjectKeyWithValue,
59
61
  isAbortError: () => isAbortError,
60
62
  isAbsoluteUrl: () => isAbsoluteUrl,
61
63
  isAsString: () => isAsString,
64
+ isEncryptor: () => isEncryptor,
62
65
  isRequestAdapterResponse: () => isRequestAdapterResponse,
66
+ isSerializer: () => isSerializer,
67
+ isStorage: () => isStorage,
63
68
  normalizeHookNames: () => normalizeHookNames,
64
69
  raceWithAbort: () => raceWithAbort,
65
70
  runPluginHook: () => runPluginHook,
@@ -2881,6 +2886,9 @@ var RequestAdapterFetch = class {
2881
2886
  if (!baseURL) {
2882
2887
  return url;
2883
2888
  }
2889
+ if (url.startsWith(baseURL)) {
2890
+ return url;
2891
+ }
2884
2892
  if (baseURL.endsWith("/") && url.startsWith("/")) {
2885
2893
  return baseURL.slice(0, -1) + url;
2886
2894
  }
@@ -3827,12 +3835,18 @@ var SimpleUrlBuilder = class {
3827
3835
  basePath = "/" + basePath;
3828
3836
  }
3829
3837
  let combinedPath = basePath;
3830
- if (!combinedPath.endsWith("/") && !url.startsWith("/")) {
3831
- combinedPath += "/";
3838
+ if (!combinedPath.endsWith("/") || !url.startsWith("/")) {
3839
+ if (!combinedPath.endsWith("/")) {
3840
+ combinedPath += "/";
3841
+ }
3832
3842
  }
3833
3843
  combinedPath += url.replace(/^\//, "");
3834
3844
  urlObject = new URL(combinedPath, "http://temp");
3835
3845
  shouldReturnPathOnly = true;
3846
+ } else if (base && base === "api") {
3847
+ const combinedPath = "/api/" + url.replace(/^\//, "");
3848
+ urlObject = new URL(combinedPath, "http://temp");
3849
+ shouldReturnPathOnly = true;
3836
3850
  } else if (base) {
3837
3851
  urlObject = new URL(url, "http://temp");
3838
3852
  shouldReturnPathOnly = true;
@@ -3981,6 +3995,7 @@ var SimpleUrlBuilder = class {
3981
3995
  };
3982
3996
 
3983
3997
  // src/request/impl/RequestPlugin.ts
3998
+ var import_lodash_es4 = require("lodash-es");
3984
3999
  var RequestPlugin = class {
3985
4000
  pluginName = "RequestPlugin";
3986
4001
  config;
@@ -4035,13 +4050,29 @@ var RequestPlugin = class {
4035
4050
  * @override
4036
4051
  */
4037
4052
  onBefore(ctx) {
4038
- const mergedConfig = this.mergeConfig(ctx.parameters);
4053
+ ctx.setParameters(this.mergeConfig(ctx.parameters));
4054
+ }
4055
+ startsWith(url, baseUrl) {
4056
+ return url.startsWith(baseUrl);
4057
+ }
4058
+ /**
4059
+ * Main request handler
4060
+ *
4061
+ * This is the core of the plugin. It merges default plugin configuration with request context configuration,
4062
+ * processes request data, builds the URL, and injects headers.
4063
+ *
4064
+ * @param config - Request configuration
4065
+ * @returns Merged configuration with processed data, built URL, and injected headers
4066
+ */
4067
+ mergeConfig(config) {
4068
+ const mergedConfig = this.createConfig(config);
4039
4069
  const processedData = this.processRequestData(mergedConfig);
4040
4070
  const builtUrl = this.buildUrl(mergedConfig);
4071
+ if (builtUrl && mergedConfig.baseURL && this.startsWith(builtUrl, mergedConfig.baseURL)) {
4072
+ delete mergedConfig.baseURL;
4073
+ }
4041
4074
  const injectedHeaders = this.injectHeaders(mergedConfig);
4042
- ctx.setParameters({
4043
- ...ctx.parameters,
4044
- ...mergedConfig,
4075
+ return Object.assign(mergedConfig, {
4045
4076
  data: processedData,
4046
4077
  url: builtUrl,
4047
4078
  headers: injectedHeaders
@@ -4059,8 +4090,8 @@ var RequestPlugin = class {
4059
4090
  * @param contextConfig - Configuration from request context
4060
4091
  * @returns Merged configuration
4061
4092
  */
4062
- mergeConfig(contextConfig) {
4063
- const merged = { ...this.config, ...contextConfig };
4093
+ createConfig(contextConfig) {
4094
+ const merged = Object.assign((0, import_lodash_es4.clone)(this.config), contextConfig);
4064
4095
  if (!("data" in contextConfig) && "data" in this.config) {
4065
4096
  merged.data = this.config.data;
4066
4097
  }
@@ -4074,13 +4105,10 @@ var RequestPlugin = class {
4074
4105
  * @throws {Error} If the built URL is empty or invalid
4075
4106
  */
4076
4107
  buildUrl(config) {
4077
- const url = this.urlBuilder.buildUrl(config);
4078
- if (!url || url.trim() === "") {
4079
- throw new Error(
4080
- `RequestPlugin: Invalid URL. URL cannot be empty. baseURL: ${config.baseURL ?? "undefined"}, url: ${config.url ?? "undefined"}`
4081
- );
4108
+ if (config.allowEmptyUrl === false && !config.url && !config.baseURL) {
4109
+ throw new Error("Empty URL is not allowed");
4082
4110
  }
4083
- return url;
4111
+ return this.urlBuilder.buildUrl(config);
4084
4112
  }
4085
4113
  /**
4086
4114
  * Inject default headers into request configuration
@@ -4134,7 +4162,7 @@ var RequestPlugin = class {
4134
4162
  };
4135
4163
 
4136
4164
  // src/request/impl/ResponsePlugin.ts
4137
- var import_lodash_es4 = require("lodash-es");
4165
+ var import_lodash_es5 = require("lodash-es");
4138
4166
 
4139
4167
  // src/request/utils/isRequestAdapterResponse.ts
4140
4168
  function isRequestAdapterResponse(value) {
@@ -4215,18 +4243,17 @@ var ResponsePlugin = class {
4215
4243
  async onSuccess(context) {
4216
4244
  const returnValue = context.returnValue;
4217
4245
  const config = context.parameters;
4246
+ const result = await this.handleResponse(returnValue, config);
4247
+ if (result) {
4248
+ context.setReturnValue(result);
4249
+ }
4250
+ }
4251
+ handleResponse(returnValue, config) {
4218
4252
  if (returnValue instanceof Response) {
4219
- const processedResponse = await this.processResponse(returnValue, config);
4220
- context.setReturnValue(processedResponse);
4221
- return;
4253
+ return this.processResponse(returnValue, config);
4222
4254
  }
4223
4255
  if (isRequestAdapterResponse(returnValue)) {
4224
- const processedResponse = await this.processAdapterResponse(
4225
- returnValue,
4226
- config
4227
- );
4228
- context.setReturnValue(processedResponse);
4229
- return;
4256
+ return this.processAdapterResponse(returnValue, config);
4230
4257
  }
4231
4258
  }
4232
4259
  /**
@@ -4298,7 +4325,7 @@ var ResponsePlugin = class {
4298
4325
  * ```
4299
4326
  */
4300
4327
  async parseResponseData(response, responseType) {
4301
- if ((0, import_lodash_es4.isFunction)(this.config.responseDataParser)) {
4328
+ if ((0, import_lodash_es5.isFunction)(this.config.responseDataParser)) {
4302
4329
  return await this.config.responseDataParser(response, responseType);
4303
4330
  }
4304
4331
  return await this.defaultParseResponseData(response, responseType);
@@ -4322,7 +4349,7 @@ var ResponsePlugin = class {
4322
4349
  if (parser === false) {
4323
4350
  return response;
4324
4351
  }
4325
- if ((0, import_lodash_es4.isFunction)(parser)) {
4352
+ if ((0, import_lodash_es5.isFunction)(parser)) {
4326
4353
  return await parser(response);
4327
4354
  }
4328
4355
  return await this.fallbackParseByContentType(response, normalizedType);
@@ -4340,13 +4367,13 @@ var ResponsePlugin = class {
4340
4367
  const lowerContentType = contentType.toLowerCase();
4341
4368
  if (lowerContentType.includes("application/json")) {
4342
4369
  const jsonParser = this.parsers.json;
4343
- if ((0, import_lodash_es4.isFunction)(jsonParser)) {
4370
+ if ((0, import_lodash_es5.isFunction)(jsonParser)) {
4344
4371
  return jsonParser;
4345
4372
  }
4346
4373
  }
4347
4374
  if (lowerContentType.includes("text/") || lowerContentType.includes("application/xml") || lowerContentType.includes("application/xhtml")) {
4348
4375
  const textParser = this.parsers.text;
4349
- if ((0, import_lodash_es4.isFunction)(textParser)) {
4376
+ if ((0, import_lodash_es5.isFunction)(textParser)) {
4350
4377
  return textParser;
4351
4378
  }
4352
4379
  }
@@ -4363,11 +4390,11 @@ var ResponsePlugin = class {
4363
4390
  getFallbackParsers() {
4364
4391
  const fallbackParsers = [];
4365
4392
  const jsonParser = this.parsers.json;
4366
- if ((0, import_lodash_es4.isFunction)(jsonParser)) {
4393
+ if ((0, import_lodash_es5.isFunction)(jsonParser)) {
4367
4394
  fallbackParsers.push(jsonParser);
4368
4395
  }
4369
4396
  const textParser = this.parsers.text;
4370
- if ((0, import_lodash_es4.isFunction)(textParser)) {
4397
+ if ((0, import_lodash_es5.isFunction)(textParser)) {
4371
4398
  fallbackParsers.push(textParser);
4372
4399
  }
4373
4400
  return fallbackParsers;
@@ -4904,71 +4931,45 @@ var Base64Serializer = class {
4904
4931
 
4905
4932
  // src/storage/impl/KeyStorage.ts
4906
4933
  var KeyStorage = class {
4907
- constructor(key, options = {}) {
4934
+ constructor(key, storage) {
4908
4935
  this.key = key;
4909
- this.options = options;
4910
- try {
4911
- const localValue = options.storage?.getItem(key);
4912
- this.value = localValue ?? null;
4913
- } catch {
4914
- this.value = null;
4915
- }
4936
+ this.storage = storage;
4916
4937
  }
4917
4938
  value;
4918
- mergeOptions(options) {
4919
- return {
4920
- ...this.options,
4921
- ...options
4922
- };
4923
- }
4924
- /**
4925
- * @override
4926
- */
4927
- getKey() {
4928
- return this.key;
4929
- }
4930
- /**
4931
- * @override
4932
- */
4933
- getValue() {
4934
- return this.value;
4935
- }
4936
4939
  /**
4937
4940
  * @override
4938
4941
  */
4939
4942
  get(options) {
4940
- const { storage, ...reset } = this.mergeOptions(options);
4941
- if (this.value != null) {
4942
- return this.value;
4943
+ if (!this.storage) {
4944
+ return this.value ?? null;
4943
4945
  }
4944
- if (storage) {
4945
- const val = storage.getItem(this.key, void 0, reset);
4946
- if (val == null) {
4947
- this.remove();
4948
- return null;
4949
- }
4950
- this.value = val;
4951
- return val;
4946
+ const val = this.storage.getItem(this.key, options);
4947
+ if (val == null) {
4948
+ this.remove();
4949
+ return null;
4952
4950
  }
4953
- return this.value;
4951
+ this.value = val;
4952
+ return val;
4954
4953
  }
4955
4954
  /**
4956
4955
  * @override
4957
4956
  */
4958
- set(token, options) {
4959
- const { storage, ...reset } = this.mergeOptions(options);
4960
- this.value = token;
4961
- if (storage) {
4962
- storage.setItem(this.key, token, reset);
4957
+ set(value, options) {
4958
+ if (!this.storage) {
4959
+ this.value = value;
4960
+ return;
4963
4961
  }
4962
+ this.storage.setItem(this.key, value, options);
4964
4963
  }
4965
4964
  /**
4966
4965
  * @override
4967
4966
  */
4968
4967
  remove(options) {
4969
- const { storage, ...reset } = this.mergeOptions(options);
4970
- this.value = null;
4971
- storage?.removeItem(this.key, reset);
4968
+ if (!this.storage) {
4969
+ this.value = null;
4970
+ return;
4971
+ }
4972
+ this.storage.removeItem(this.key, options);
4972
4973
  }
4973
4974
  };
4974
4975
 
@@ -5003,7 +5004,6 @@ var ObjectStorage = class {
5003
5004
  /**
5004
5005
  * Gets the number of items stored in the memory cache
5005
5006
  *
5006
- * @override
5007
5007
  * @returns The number of stored items in memory
5008
5008
  *
5009
5009
  * @example
@@ -5081,12 +5081,9 @@ var ObjectStorage = class {
5081
5081
  if (!storeValue) {
5082
5082
  return _dv;
5083
5083
  }
5084
- const value = this.serializer ? this.serializer.deserialize(storeValue, _dv) : storeValue;
5084
+ const value = typeof storeValue === "string" && this.serializer ? this.serializer.deserialize(storeValue, _dv) : storeValue;
5085
5085
  return this.getRawValue(value, _dv);
5086
5086
  }
5087
- /**
5088
- * @override
5089
- */
5090
5087
  getRawValue(value, defaultValue) {
5091
5088
  if (this.isStorageValue(value)) {
5092
5089
  if (this.isExpired(value)) {
@@ -5180,268 +5177,146 @@ var ObjectStorage = class {
5180
5177
  isStorageValue(value) {
5181
5178
  return typeof value === "object" && value !== null && "key" in value && "value" in value;
5182
5179
  }
5183
- /**
5184
- * Gets the serializer instance
5185
- *
5186
- * Significance: Provides access to the serialization logic
5187
- * Core idea: Expose serializer for advanced use cases
5188
- * Main function: Return the serializer instance
5189
- * Main purpose: Enable direct access to serialization when needed
5190
- *
5191
- * @returns The serializer instance
5192
- *
5193
- * @example
5194
- * ```typescript
5195
- * const serializer = storage.getSerializer();
5196
- * if (serializer) {
5197
- * // Direct access to serializer
5198
- * }
5199
- * ```
5200
- */
5201
- getSerializer() {
5202
- return this.serializer;
5203
- }
5204
5180
  };
5205
5181
 
5206
- // src/storage/impl/SyncStorage.ts
5207
- function toPipeValue(pipe) {
5208
- if ("type" in pipe && "pipe" in pipe) {
5209
- return pipe;
5210
- }
5211
- if ("serialize" in pipe && "deserialize" in pipe) {
5212
- return { pipe, type: "serialize" };
5213
- }
5214
- if ("encrypt" in pipe && "decrypt" in pipe) {
5215
- return { pipe, type: "encrypt" };
5182
+ // src/storage/utils/isStorage.ts
5183
+ var storageMethods = ["setItem", "getItem", "removeItem", "clear"];
5184
+ function isStorage(storage) {
5185
+ if (storage == null || typeof storage !== "object") {
5186
+ return false;
5216
5187
  }
5217
- if ("setItem" in pipe && "getItem" in pipe && "removeItem" in pipe && "clear" in pipe) {
5218
- return { pipe, type: "storage" };
5188
+ for (const method of storageMethods) {
5189
+ if (storage[method] == null || typeof storage[method] !== "function") {
5190
+ return false;
5191
+ }
5219
5192
  }
5220
- return null;
5193
+ return true;
5221
5194
  }
5222
- var operationMaps = {
5223
- setItem: {
5224
- serialize: (pipe, args) => pipe.serialize(...args),
5225
- encrypt: (pipe, args) => pipe.encrypt(...args),
5226
- storage: (pipe, args) => pipe.setItem(...args)
5227
- },
5228
- getItem: {
5229
- serialize: (pipe, args) => pipe.deserialize(...args),
5230
- encrypt: (pipe, args) => pipe.decrypt(...args),
5231
- storage: (pipe, args) => pipe.getItem(...args)
5232
- }
5233
- };
5234
- var SyncStorage = class {
5235
- /**
5236
- * Creates a new SyncStorage instance with pipeline support
5237
- *
5238
- * @param storage - Primary storage backend (e.g., localStorage, sessionStorage)
5239
- * @param pipes - Optional pipe or array of pipes for data transformation
5240
- *
5241
- * @example Single pipe
5242
- * ```typescript
5243
- * const storage = new SyncStorage(
5244
- * localStorage,
5245
- * new JSONSerializer()
5246
- * );
5247
- * ```
5248
- *
5249
- * @example Multiple pipes
5250
- * ```typescript
5251
- * const storage = new SyncStorage(
5252
- * localStorage,
5253
- * [
5254
- * new JSONSerializer(),
5255
- * new AESEncryptor('secret-key')
5256
- * ]
5257
- * );
5258
- * ```
5259
- *
5260
- * @example No pipes (direct storage)
5261
- * ```typescript
5262
- * const storage = new SyncStorage(localStorage);
5263
- * // Data stored as-is without transformation
5264
- * ```
5265
- */
5266
- constructor(storage, pipes = []) {
5267
- this.storage = storage;
5268
- this.pipes = (Array.isArray(pipes) ? pipes : [pipes]).map((p) => toPipeValue(p)).filter((p) => p != null);
5195
+
5196
+ // src/storage/utils/createStoragePlugin.ts
5197
+ function createStoragePluginWithStorage(storage) {
5198
+ return {
5199
+ get: storage.getItem.bind(storage),
5200
+ set: storage.setItem.bind(storage),
5201
+ remove: storage.removeItem.bind(storage),
5202
+ clear: storage.clear.bind(storage),
5203
+ type: "storage"
5204
+ };
5205
+ }
5206
+ function isSerializer(plugin) {
5207
+ return typeof plugin === "object" && plugin !== null && "serialize" in plugin && "deserialize" in plugin;
5208
+ }
5209
+ function isEncryptor(plugin) {
5210
+ return typeof plugin === "object" && plugin !== null && "encrypt" in plugin && "decrypt" in plugin;
5211
+ }
5212
+ function createStoragePlugin(plugins) {
5213
+ if (Array.isArray(plugins)) {
5214
+ return plugins.map((plugin) => {
5215
+ if (isSerializer(plugin)) {
5216
+ return {
5217
+ get: (_key, value) => plugin.deserialize(
5218
+ value
5219
+ ),
5220
+ set: (_key, value) => plugin.serialize(value),
5221
+ type: "serializer"
5222
+ };
5223
+ } else if (isEncryptor(plugin)) {
5224
+ return {
5225
+ get: (_key, value) => plugin.decrypt(
5226
+ value
5227
+ ),
5228
+ set: (_key, value) => plugin.encrypt(value),
5229
+ type: "encryptor"
5230
+ };
5231
+ } else if (isStorage(plugin)) {
5232
+ return createStoragePluginWithStorage(plugin);
5233
+ }
5234
+ return plugin;
5235
+ });
5269
5236
  }
5237
+ return [createStoragePluginWithStorage(plugins)];
5238
+ }
5239
+
5240
+ // src/storage/impl/StorageExecutor.ts
5241
+ var StorageExecutor = class {
5242
+ plugins = [];
5270
5243
  /**
5271
- * Internal pipe value list with pre-determined types
5272
- *
5273
- * Stores the processed pipeline of transformations that will be
5274
- * applied to data during storage and retrieval operations.
5275
- *
5276
- * @protected
5277
- */
5278
- pipes;
5279
- /**
5280
- * Get the number of items in the primary storage
5281
- *
5282
- * Returns the count of items in the primary storage backend only.
5283
- * Does not include items in intermediate storage layers.
5284
- *
5285
- * @override
5286
- * @returns Number of items in primary storage
5244
+ * Builds the plugin list from either a single `StorageInterface` or an array whose last element
5245
+ * is the backing storage and preceding elements are transformers (e.g. serializer, encryptor).
5287
5246
  *
5288
- * @example
5289
- * ```typescript
5290
- * console.log(storage.length); // 5
5291
- * storage.setItem('newKey', 'value');
5292
- * console.log(storage.length); // 6
5293
- * ```
5247
+ * @param plugins - Single storage instance or tuple of `[ ...transformers, storage ]`
5294
5248
  */
5295
- get length() {
5296
- return this.storage.length;
5249
+ constructor(plugins) {
5250
+ this.plugins = createStoragePlugin(plugins);
5297
5251
  }
5298
5252
  /**
5299
- * Store a value with pipeline processing
5300
- *
5301
- * Processes the value through the configured pipeline (serialization,
5302
- * encryption, intermediate storage) before storing in the primary storage.
5303
- *
5304
- * Pipeline execution:
5305
- * 1. Apply serialization (if configured)
5306
- * 2. Apply encryption (if configured)
5307
- * 3. Store in intermediate storage layers (if configured)
5308
- * 4. Store in primary storage
5253
+ * Writes value through the plugin chain (forward). Each plugin may return a transformed value for the next.
5309
5254
  *
5310
5255
  * @override
5311
- * @template T - Type of value to store
5312
- * @param key - Storage key
5313
- * @param value - Value to store
5314
- * @param options - Optional storage options (e.g., expiration)
5315
- *
5316
- * @example Basic storage
5317
- * ```typescript
5318
- * storage.setItem('user', { id: 1, name: 'John' });
5319
- * ```
5320
- *
5321
- * @example With options
5322
- * ```typescript
5323
- * storage.setItem('session', { token: 'abc' }, { expire: 3600 });
5324
- * ```
5325
5256
  */
5326
5257
  setItem(key, value, options) {
5327
- let processedValue = value;
5328
- for (const currentPipe of this.pipes) {
5329
- const { type, pipe } = currentPipe;
5330
- if (type === "storage") {
5331
- pipe.setItem(
5332
- key,
5333
- processedValue,
5334
- options
5335
- );
5336
- } else {
5337
- const result = operationMaps.setItem[type](
5338
- // @ts-expect-error
5339
- pipe,
5340
- [processedValue]
5341
- );
5342
- if (result != null) {
5343
- processedValue = result;
5344
- }
5258
+ let finalValue = value;
5259
+ for (const plugin of this.plugins) {
5260
+ const result = plugin.set(key, finalValue, options);
5261
+ if (result !== void 0) {
5262
+ finalValue = result;
5345
5263
  }
5346
5264
  }
5347
- this.storage.setItem(key, processedValue, options);
5348
5265
  }
5349
5266
  /**
5350
- * Retrieve a value with pipeline processing
5267
+ * Reads value through the plugin chain in reverse order.
5351
5268
  *
5352
- * Retrieves the value from storage and processes it through the pipeline
5353
- * in reverse order (decryption, deserialization) to restore the original value.
5269
+ * **Multiple storage plugins:** When the pipeline contains more than one storage plugin (e.g.
5270
+ * `[sessionStorage, localStorage]`), getItem **only uses the value from the last storage** (the
5271
+ * plugin at the end of the array). The iteration runs from tail to head; the first storage plugin
5272
+ * encountered (which is the last in the array) is the only one whose `get` result is used. All
5273
+ * other storage plugins are skipped and their values are ignored. This ensures a single, well-defined
5274
+ * read source (e.g. prefer localStorage over sessionStorage when both are in the chain).
5354
5275
  *
5355
- * Retrieval strategy:
5356
- * 1. Try to retrieve from primary storage
5357
- * 2. If not found, try intermediate storage layers (in reverse order)
5358
- * 3. Apply decryption (if configured)
5359
- * 4. Apply deserialization (if configured)
5360
- * 5. Return processed value or default
5276
+ * Pipe plugins (serializer, encryptor, etc.) are always applied to transform the value read from
5277
+ * that single storage. If no value is found, returns `defaultValue` when provided, otherwise `null`.
5361
5278
  *
5362
5279
  * @override
5363
- * @template T - Type of value to retrieve
5364
- * @param key - Storage key
5365
- * @param defaultValue - Default value if key not found
5366
- * @param options - Optional retrieval options
5367
- * @returns Retrieved value or default, `null` if not found and no default
5368
- *
5369
- * @example Basic retrieval
5370
- * ```typescript
5371
- * const user = storage.getItem('user');
5372
- * if (user) {
5373
- * console.log(user.name);
5374
- * }
5375
- * ```
5376
- *
5377
- * @example With default value
5378
- * ```typescript
5379
- * const config = storage.getItem('config', { theme: 'light' });
5380
- * console.log(config.theme); // 'light' if not found
5381
- * ```
5382
5280
  */
5383
5281
  getItem(key, defaultValue, options) {
5384
- let processedValue = this.storage.getItem(key, defaultValue, options);
5385
- if (processedValue == null) {
5386
- const reversedPipes2 = [...this.pipes].reverse();
5387
- for (const currentPipe of reversedPipes2) {
5388
- const { type, pipe } = currentPipe;
5389
- if (type !== "storage") {
5390
- continue;
5391
- }
5392
- const res = operationMaps.getItem[type](pipe, [
5393
- key,
5394
- processedValue,
5395
- options
5396
- ]);
5397
- if (res != null) {
5398
- processedValue = res;
5399
- break;
5400
- }
5401
- }
5402
- }
5403
- if (processedValue == null) {
5404
- return defaultValue ?? null;
5405
- }
5406
- const reversedPipes = [...this.pipes].reverse();
5407
- for (const currentPipe of reversedPipes) {
5408
- const { type, pipe } = currentPipe;
5409
- if (type === "storage") {
5282
+ const lastIndex = this.plugins.length - 1;
5283
+ let finalValue;
5284
+ let storageHasValue = false;
5285
+ for (let i = lastIndex; i >= 0; i--) {
5286
+ const plugin = this.plugins[i];
5287
+ const isStoragePlugin = plugin.type === "storage";
5288
+ if (isStoragePlugin && storageHasValue) {
5410
5289
  continue;
5411
5290
  }
5412
- processedValue = operationMaps.getItem[type](
5413
- pipe,
5414
- [processedValue]
5415
- );
5416
- }
5417
- if (processedValue !== null && this.storage.getRawValue) {
5418
- processedValue = this.storage.getRawValue(processedValue, options);
5291
+ const result = plugin.get(key, finalValue, options);
5292
+ if (result !== void 0) {
5293
+ finalValue = result;
5294
+ if (isStoragePlugin) {
5295
+ storageHasValue = true;
5296
+ }
5297
+ }
5419
5298
  }
5420
- return processedValue ?? null;
5299
+ return finalValue ?? defaultValue ?? null;
5421
5300
  }
5422
5301
  /**
5423
- * Delete data items, delete from all storage layers
5302
+ * Removes item for the given key from all plugins that implement `remove`.
5424
5303
  *
5425
5304
  * @override
5426
- * @param key - Storage key
5427
- * @param options - Delete options
5428
5305
  */
5429
5306
  removeItem(key, options) {
5430
- this.storage.removeItem(key, options);
5431
- this.pipes.filter((p) => p.type === "storage").forEach((p) => {
5432
- p.pipe.removeItem(key, options);
5433
- });
5307
+ for (const plugin of this.plugins) {
5308
+ plugin.remove?.(key, options);
5309
+ }
5434
5310
  }
5435
5311
  /**
5436
- * Clear all data, including storage in the pipeline
5437
-
5438
- * @override
5439
- */
5312
+ * Clears data in all plugins that implement `clear`.
5313
+ *
5314
+ * @override
5315
+ */
5440
5316
  clear() {
5441
- this.storage.clear();
5442
- this.pipes.filter((p) => p.type === "storage").forEach((p) => {
5443
- p.pipe.clear();
5444
- });
5317
+ for (const plugin of this.plugins) {
5318
+ plugin.clear?.();
5319
+ }
5445
5320
  }
5446
5321
  };
5447
5322
  // Annotate the CommonJS export names for ESM import in node:
@@ -5477,15 +5352,20 @@ var SyncStorage = class {
5477
5352
  ResponsePlugin,
5478
5353
  RetryPlugin,
5479
5354
  SimpleUrlBuilder,
5480
- SyncStorage,
5355
+ StorageExecutor,
5481
5356
  appendHeaders,
5482
5357
  createAbortPromise,
5358
+ createStoragePlugin,
5359
+ createStoragePluginWithStorage,
5483
5360
  hasObjectKey,
5484
5361
  hasObjectKeyWithValue,
5485
5362
  isAbortError,
5486
5363
  isAbsoluteUrl,
5487
5364
  isAsString,
5365
+ isEncryptor,
5488
5366
  isRequestAdapterResponse,
5367
+ isSerializer,
5368
+ isStorage,
5489
5369
  normalizeHookNames,
5490
5370
  raceWithAbort,
5491
5371
  runPluginHook,