@conduit-client/command-fetch-network 3.19.0 → 3.19.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.
@@ -16,6 +16,10 @@ export declare abstract class FetchNetworkCommand<Data, ExtraServices extends ob
16
16
  };
17
17
  constructor(services: NamedFetchService & ExtraServices);
18
18
  fetch(): PromiseLike<Result<Data, Error>>;
19
+ protected readonly additionalNullResponses: ReadonlyArray<number>;
20
+ protected isSemanticNullResponse(response: Response): boolean;
21
+ protected isProtocolNoBodyStatus(status: number): boolean;
22
+ private isUndeclaredNoBodyResponse;
19
23
  protected coerceError(errorResponse: Response): Promise<Error>;
20
24
  private convertFetchResponseToData;
21
25
  protected abstract readonly fetchParams: Parameters<FetchService>;
package/dist/v1/index.js CHANGED
@@ -131,6 +131,7 @@ const _FetchNetworkCommand = class _FetchNetworkCommand extends NetworkCommand {
131
131
  constructor(services) {
132
132
  super(services);
133
133
  this.services = services;
134
+ this.additionalNullResponses = [];
134
135
  }
135
136
  fetch() {
136
137
  try {
@@ -139,6 +140,15 @@ const _FetchNetworkCommand = class _FetchNetworkCommand extends NetworkCommand {
139
140
  return resolvedPromiseLike(err(toError(reason)));
140
141
  }
141
142
  }
143
+ isSemanticNullResponse(response) {
144
+ return this.additionalNullResponses.includes(response.status);
145
+ }
146
+ isProtocolNoBodyStatus(status) {
147
+ return status === 204 || status === 205;
148
+ }
149
+ isUndeclaredNoBodyResponse(response) {
150
+ return this.isProtocolNoBodyStatus(response.status) && !this.isSemanticNullResponse(response);
151
+ }
142
152
  async coerceError(errorResponse) {
143
153
  return toError(errorResponse.statusText);
144
154
  }
@@ -146,10 +156,24 @@ const _FetchNetworkCommand = class _FetchNetworkCommand extends NetworkCommand {
146
156
  return response.then(
147
157
  (response2) => {
148
158
  if (response2.ok) {
149
- return response2.json().then(
150
- (json) => ok(json),
151
- (reason) => err(toError(reason))
152
- ).finally(() => {
159
+ let resultPromise;
160
+ if (this.isSemanticNullResponse(response2)) {
161
+ resultPromise = Promise.resolve(ok(null));
162
+ } else if (this.isUndeclaredNoBodyResponse(response2)) {
163
+ resultPromise = Promise.resolve(
164
+ err(
165
+ toError(
166
+ `Unexpected ${response2.status} response: no-content status was not declared in the API specification. Declare this response in your OAS without a content property.`
167
+ )
168
+ )
169
+ );
170
+ } else {
171
+ resultPromise = response2.json().then(
172
+ (json) => ok(json),
173
+ (reason) => err(toError(reason))
174
+ );
175
+ }
176
+ return resultPromise.finally(() => {
153
177
  try {
154
178
  this.afterRequestHooks({ statusCode: response2.status });
155
179
  } catch {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../network/dist/v1/index.js","../../src/v1/abortable-request-decorator.ts","../../src/v1/fetch-command.ts","../../src/v1/index.ts"],"sourcesContent":["/*!\n * Copyright (c) 2022, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport { buildSubscribableResult, isSubscribableResult, ok, err } from \"@conduit-client/utils\";\nimport { BaseCommand } from \"@conduit-client/command-base/v1\";\nclass NetworkCommand extends BaseCommand {\n constructor(services) {\n super();\n this.services = services;\n this.subscriptions = [];\n this.exposeSubscribeAndRefresh = false;\n }\n execute() {\n const result = this.fetch();\n if (this.exposeSubscribeAndRefresh) {\n return this.fetchSubscribableResult(result);\n }\n return result;\n }\n fetchSubscribableResult(res) {\n return res.then((networkResult) => {\n return buildSubscribableResult(\n networkResult,\n (cb) => {\n this.subscriptions.push(cb);\n return () => {\n this.subscriptions = this.subscriptions.filter((cb2) => cb2 !== cb);\n };\n },\n () => this.refresh()\n );\n });\n }\n refresh() {\n return this.execute().then((newResult) => {\n if (isSubscribableResult(newResult)) {\n const value = newResult.isOk() ? ok(newResult.value.data) : err(newResult.error.failure);\n this.subscriptions.forEach((cb) => {\n cb(value);\n });\n }\n return ok(void 0);\n });\n }\n async afterRequestHooks(_options) {\n }\n}\nfunction buildServiceDescriptor() {\n return {\n type: \"networkCommandBaseClass\",\n version: \"1.0\",\n service: NetworkCommand\n };\n}\nexport {\n NetworkCommand,\n buildServiceDescriptor\n};\n//# sourceMappingURL=index.js.map\n","import type { Command } from '@conduit-client/command-base/v1';\n\n/**\n * Options interface for commands that support abortion\n */\nexport interface AbortableCommandOptions {\n /**\n * Optional AbortSignal for request cancellation.\n * Follows standard web platform patterns (fetch API).\n */\n signal?: AbortSignal;\n}\n\n/**\n * Enhanced Command interface that indicates abortion capability\n */\nexport interface AbortableCommand<T, Params extends Array<any> = []> extends Command<T, Params> {\n readonly isAbortableCommand: true;\n readonly signal: AbortSignal;\n}\n\n/**\n * Type guard to check if a command is abortable\n */\nfunction isAbortableCommand<T>(command: Command<T>): command is AbortableCommand<T> {\n return 'isAbortableCommand' in command && (command as any).isAbortableCommand === true;\n}\n\n/**\n * Interface for commands that support fetch operations (can be aborted)\n */\ninterface FetchCapable {\n fetchParams?: unknown;\n}\n\n/**\n * Type guard to check if a command supports fetch operations\n */\nfunction hasFetchParams(command: any): command is FetchCapable {\n return command && typeof command === 'object' && 'fetchParams' in command;\n}\n\n/**\n * Factory function for creating abortable command proxies\n *\n * Provides a clean API for decorator creation with proper error handling\n * and graceful degradation for non-fetch commands.\n *\n * @param command - The command to make abortable\n * @param signal - The AbortSignal for request cancellation\n * @returns Proxied command if possible, original command with warning if not\n */\nexport function createAbortableDecorator<T>(command: Command<T>, options: any): Command<T> {\n if (!options?.signal || !(options?.signal instanceof AbortSignal)) {\n return command;\n }\n const { signal } = options;\n\n // Return original command if already decorated\n if (isAbortableCommand(command)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Command is already abortable. Returning original command to avoid double-wrapping.'\n );\n }\n return command;\n }\n\n // Only decorate commands that support fetch operations\n if (!hasFetchParams(command)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n `Command ${command.constructor.name} does not support fetch operations. ` +\n 'AbortSignal will be ignored.'\n );\n }\n\n return command;\n }\n\n try {\n return new Proxy(command, {\n get(target: any, prop: string | symbol, receiver: any): any {\n // Add the abortable marker property\n if (prop === 'isAbortableCommand') {\n return true;\n }\n\n // Add signal property for access to the original AbortSignal\n if (prop === 'signal') {\n return signal;\n }\n\n // Intercept fetchParams getter/method access\n if (prop === 'fetchParams') {\n const originalFetchParams = target[prop];\n\n // Check if this is an internal execution (cache control system)\n const isInternal = target.isInternalExecution === true;\n\n // Handle both getter (property) and method patterns\n if (typeof originalFetchParams === 'function') {\n // fetchParams is a method\n return function (this: any, ...args: any[]) {\n const originalReturnValue = originalFetchParams.apply(this, args);\n\n // Only inject signal for user executions\n if (!isInternal) {\n const [url, init = {}] = originalReturnValue;\n return [url, { signal, ...init }];\n }\n\n return originalReturnValue;\n };\n } else {\n // fetchParams is a getter property\n if (\n !isInternal &&\n originalFetchParams &&\n Array.isArray(originalFetchParams)\n ) {\n const [url, init = {}] = originalFetchParams;\n return [url, { signal, ...init }];\n }\n\n return originalFetchParams;\n }\n }\n\n // Forward all other property/method access to the original command\n return Reflect.get(target, prop, receiver);\n },\n has(target: any, prop: string | symbol): boolean {\n // Ensure 'in' operator works for our synthetic properties\n if (prop === 'isAbortableCommand' || prop === 'signal') {\n return true;\n }\n return Reflect.has(target, prop);\n },\n });\n } catch (error) {\n if (process.env.NODE_ENV !== 'production') {\n console.error(\n 'Failed to create abortable command proxy, returning original command unchanged.',\n error\n );\n }\n\n return command;\n }\n}\n","import { err, ok, resolvedPromiseLike, toError, type Result } from '@conduit-client/utils';\nimport { NetworkCommand } from '@conduit-client/command-network/v1';\nimport { createAbortableDecorator } from './abortable-request-decorator';\nimport type { NamedFetchService, FetchService } from '@conduit-client/service-fetch-network/v1';\n\n/**\n * An implementation of NetworkCommand that uses HTTP/fetch as the transport mechanism.\n */\nexport abstract class FetchNetworkCommand<\n Data,\n ExtraServices extends object = object,\n> extends NetworkCommand<Data, NamedFetchService & ExtraServices> {\n /**\n * Available decorators for FetchNetworkCommand instances.\n * These decorators can be applied to enhance command functionality.\n */\n static readonly availableDecorators = {\n abortable: createAbortableDecorator,\n };\n\n constructor(protected services: NamedFetchService & ExtraServices) {\n super(services);\n }\n\n fetch(): PromiseLike<Result<Data, Error>> {\n try {\n return this.convertFetchResponseToData(this.services.fetch(...this.fetchParams));\n } catch (reason) {\n return resolvedPromiseLike(err(toError(reason)));\n }\n }\n\n protected async coerceError(errorResponse: Response): Promise<Error> {\n return toError(errorResponse.statusText); // Default Behavior\n }\n\n private convertFetchResponseToData<Data = unknown>(\n response: PromiseLike<Response>\n ): PromiseLike<Result<Data, Error>> {\n return response.then(\n (response) => {\n if (response.ok) {\n return response\n .json()\n .then(\n (json: Data) => ok(json),\n (reason: any) => err(toError(reason))\n )\n .finally(() => {\n try {\n this.afterRequestHooks({ statusCode: response.status });\n } catch {\n // intentionally do nothing\n }\n });\n } else {\n return this.coerceError(response)\n .then((coercedError) => {\n return err(coercedError);\n })\n .finally(() => {\n try {\n this.afterRequestHooks({ statusCode: response.status });\n } catch {\n // intentionally do nothing\n }\n });\n }\n },\n (reason) => err(toError(reason))\n );\n }\n\n protected abstract readonly fetchParams: Parameters<FetchService>;\n}\n","import { type NamedService, type ServiceDescriptor } from '@conduit-client/utils';\nimport { FetchNetworkCommand } from './fetch-command';\n\nexport { FetchNetworkCommand } from './fetch-command';\n\n// Export AbortableCommandDecorator types and utilities\nexport { createAbortableDecorator } from './abortable-request-decorator';\nexport type { AbortableCommand, AbortableCommandOptions } from './abortable-request-decorator';\n\nexport type FetchNetworkCommandServiceDescriptor = ServiceDescriptor<\n typeof FetchNetworkCommand,\n 'fetchNetworkCommandBaseClass',\n '1.0'\n>;\n\nexport function buildServiceDescriptor(): FetchNetworkCommandServiceDescriptor {\n return {\n type: 'fetchNetworkCommandBaseClass',\n version: '1.0',\n service: FetchNetworkCommand,\n };\n}\n\nexport type NamedFetchNetworkCommandService = NamedService<\n 'fetchNetworkCommandBaseClass',\n typeof FetchNetworkCommand\n>;\n\nexport type { GeneratedFetchNetworkCommand } from './generated-command';\n"],"names":["response"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../network/dist/v1/index.js","../../src/v1/abortable-request-decorator.ts","../../src/v1/fetch-command.ts","../../src/v1/index.ts"],"sourcesContent":["/*!\n * Copyright (c) 2022, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport { buildSubscribableResult, isSubscribableResult, ok, err } from \"@conduit-client/utils\";\nimport { BaseCommand } from \"@conduit-client/command-base/v1\";\nclass NetworkCommand extends BaseCommand {\n constructor(services) {\n super();\n this.services = services;\n this.subscriptions = [];\n this.exposeSubscribeAndRefresh = false;\n }\n execute() {\n const result = this.fetch();\n if (this.exposeSubscribeAndRefresh) {\n return this.fetchSubscribableResult(result);\n }\n return result;\n }\n fetchSubscribableResult(res) {\n return res.then((networkResult) => {\n return buildSubscribableResult(\n networkResult,\n (cb) => {\n this.subscriptions.push(cb);\n return () => {\n this.subscriptions = this.subscriptions.filter((cb2) => cb2 !== cb);\n };\n },\n () => this.refresh()\n );\n });\n }\n refresh() {\n return this.execute().then((newResult) => {\n if (isSubscribableResult(newResult)) {\n const value = newResult.isOk() ? ok(newResult.value.data) : err(newResult.error.failure);\n this.subscriptions.forEach((cb) => {\n cb(value);\n });\n }\n return ok(void 0);\n });\n }\n async afterRequestHooks(_options) {\n }\n}\nfunction buildServiceDescriptor() {\n return {\n type: \"networkCommandBaseClass\",\n version: \"1.0\",\n service: NetworkCommand\n };\n}\nexport {\n NetworkCommand,\n buildServiceDescriptor\n};\n//# sourceMappingURL=index.js.map\n","import type { Command } from '@conduit-client/command-base/v1';\n\n/**\n * Options interface for commands that support abortion\n */\nexport interface AbortableCommandOptions {\n /**\n * Optional AbortSignal for request cancellation.\n * Follows standard web platform patterns (fetch API).\n */\n signal?: AbortSignal;\n}\n\n/**\n * Enhanced Command interface that indicates abortion capability\n */\nexport interface AbortableCommand<T, Params extends Array<any> = []> extends Command<T, Params> {\n readonly isAbortableCommand: true;\n readonly signal: AbortSignal;\n}\n\n/**\n * Type guard to check if a command is abortable\n */\nfunction isAbortableCommand<T>(command: Command<T>): command is AbortableCommand<T> {\n return 'isAbortableCommand' in command && (command as any).isAbortableCommand === true;\n}\n\n/**\n * Interface for commands that support fetch operations (can be aborted)\n */\ninterface FetchCapable {\n fetchParams?: unknown;\n}\n\n/**\n * Type guard to check if a command supports fetch operations\n */\nfunction hasFetchParams(command: any): command is FetchCapable {\n return command && typeof command === 'object' && 'fetchParams' in command;\n}\n\n/**\n * Factory function for creating abortable command proxies\n *\n * Provides a clean API for decorator creation with proper error handling\n * and graceful degradation for non-fetch commands.\n *\n * @param command - The command to make abortable\n * @param signal - The AbortSignal for request cancellation\n * @returns Proxied command if possible, original command with warning if not\n */\nexport function createAbortableDecorator<T>(command: Command<T>, options: any): Command<T> {\n if (!options?.signal || !(options?.signal instanceof AbortSignal)) {\n return command;\n }\n const { signal } = options;\n\n // Return original command if already decorated\n if (isAbortableCommand(command)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Command is already abortable. Returning original command to avoid double-wrapping.'\n );\n }\n return command;\n }\n\n // Only decorate commands that support fetch operations\n if (!hasFetchParams(command)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n `Command ${command.constructor.name} does not support fetch operations. ` +\n 'AbortSignal will be ignored.'\n );\n }\n\n return command;\n }\n\n try {\n return new Proxy(command, {\n get(target: any, prop: string | symbol, receiver: any): any {\n // Add the abortable marker property\n if (prop === 'isAbortableCommand') {\n return true;\n }\n\n // Add signal property for access to the original AbortSignal\n if (prop === 'signal') {\n return signal;\n }\n\n // Intercept fetchParams getter/method access\n if (prop === 'fetchParams') {\n const originalFetchParams = target[prop];\n\n // Check if this is an internal execution (cache control system)\n const isInternal = target.isInternalExecution === true;\n\n // Handle both getter (property) and method patterns\n if (typeof originalFetchParams === 'function') {\n // fetchParams is a method\n return function (this: any, ...args: any[]) {\n const originalReturnValue = originalFetchParams.apply(this, args);\n\n // Only inject signal for user executions\n if (!isInternal) {\n const [url, init = {}] = originalReturnValue;\n return [url, { signal, ...init }];\n }\n\n return originalReturnValue;\n };\n } else {\n // fetchParams is a getter property\n if (\n !isInternal &&\n originalFetchParams &&\n Array.isArray(originalFetchParams)\n ) {\n const [url, init = {}] = originalFetchParams;\n return [url, { signal, ...init }];\n }\n\n return originalFetchParams;\n }\n }\n\n // Forward all other property/method access to the original command\n return Reflect.get(target, prop, receiver);\n },\n has(target: any, prop: string | symbol): boolean {\n // Ensure 'in' operator works for our synthetic properties\n if (prop === 'isAbortableCommand' || prop === 'signal') {\n return true;\n }\n return Reflect.has(target, prop);\n },\n });\n } catch (error) {\n if (process.env.NODE_ENV !== 'production') {\n console.error(\n 'Failed to create abortable command proxy, returning original command unchanged.',\n error\n );\n }\n\n return command;\n }\n}\n","import { err, ok, resolvedPromiseLike, toError, type Result } from '@conduit-client/utils';\nimport { NetworkCommand } from '@conduit-client/command-network/v1';\nimport { createAbortableDecorator } from './abortable-request-decorator';\nimport type { NamedFetchService, FetchService } from '@conduit-client/service-fetch-network/v1';\n\n/**\n * An implementation of NetworkCommand that uses HTTP/fetch as the transport mechanism.\n */\nexport abstract class FetchNetworkCommand<\n Data,\n ExtraServices extends object = object,\n> extends NetworkCommand<Data, NamedFetchService & ExtraServices> {\n /**\n * Available decorators for FetchNetworkCommand instances.\n * These decorators can be applied to enhance command functionality.\n */\n static readonly availableDecorators = {\n abortable: createAbortableDecorator,\n };\n\n constructor(protected services: NamedFetchService & ExtraServices) {\n super(services);\n }\n\n fetch(): PromiseLike<Result<Data, Error>> {\n try {\n return this.convertFetchResponseToData(this.services.fetch(...this.fetchParams));\n } catch (reason) {\n return resolvedPromiseLike(err(toError(reason)));\n }\n }\n\n protected readonly additionalNullResponses: ReadonlyArray<number> = [];\n\n protected isSemanticNullResponse(response: Response): boolean {\n return this.additionalNullResponses.includes(response.status);\n }\n\n protected isProtocolNoBodyStatus(status: number): boolean {\n return status === 204 || status === 205;\n }\n\n private isUndeclaredNoBodyResponse(response: Response): boolean {\n return (\n this.isProtocolNoBodyStatus(response.status) && !this.isSemanticNullResponse(response)\n );\n }\n\n protected async coerceError(errorResponse: Response): Promise<Error> {\n return toError(errorResponse.statusText); // Default Behavior\n }\n\n private convertFetchResponseToData<Data = unknown>(\n response: PromiseLike<Response>\n ): PromiseLike<Result<Data, Error>> {\n return response.then(\n (response) => {\n if (response.ok) {\n let resultPromise: Promise<Result<Data, Error>>;\n if (this.isSemanticNullResponse(response)) {\n resultPromise = Promise.resolve(ok(null as Data));\n } else if (this.isUndeclaredNoBodyResponse(response)) {\n resultPromise = Promise.resolve(\n err(\n toError(\n `Unexpected ${response.status} response: no-content status was not declared in the API specification. Declare this response in your OAS without a content property.`\n )\n )\n );\n } else {\n resultPromise = response.json().then(\n (json: Data) => ok(json),\n (reason: any) => err(toError(reason))\n );\n }\n return resultPromise.finally(() => {\n try {\n this.afterRequestHooks({ statusCode: response.status });\n } catch {\n // intentionally do nothing\n }\n });\n } else {\n return this.coerceError(response)\n .then((coercedError) => {\n return err(coercedError);\n })\n .finally(() => {\n try {\n this.afterRequestHooks({ statusCode: response.status });\n } catch {\n // intentionally do nothing\n }\n });\n }\n },\n (reason) => err(toError(reason))\n );\n }\n\n protected abstract readonly fetchParams: Parameters<FetchService>;\n}\n","import { type NamedService, type ServiceDescriptor } from '@conduit-client/utils';\nimport { FetchNetworkCommand } from './fetch-command';\n\nexport { FetchNetworkCommand } from './fetch-command';\n\n// Export AbortableCommandDecorator types and utilities\nexport { createAbortableDecorator } from './abortable-request-decorator';\nexport type { AbortableCommand, AbortableCommandOptions } from './abortable-request-decorator';\n\nexport type FetchNetworkCommandServiceDescriptor = ServiceDescriptor<\n typeof FetchNetworkCommand,\n 'fetchNetworkCommandBaseClass',\n '1.0'\n>;\n\nexport function buildServiceDescriptor(): FetchNetworkCommandServiceDescriptor {\n return {\n type: 'fetchNetworkCommandBaseClass',\n version: '1.0',\n service: FetchNetworkCommand,\n };\n}\n\nexport type NamedFetchNetworkCommandService = NamedService<\n 'fetchNetworkCommandBaseClass',\n typeof FetchNetworkCommand\n>;\n\nexport type { GeneratedFetchNetworkCommand } from './generated-command';\n"],"names":["response"],"mappings":";;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,MAAM,uBAAuB,YAAY;AAAA,EACvC,YAAY,UAAU;AACpB,UAAK;AACL,SAAK,WAAW;AAChB,SAAK,gBAAgB,CAAA;AACrB,SAAK,4BAA4B;AAAA,EACnC;AAAA,EACA,UAAU;AACR,UAAM,SAAS,KAAK,MAAK;AACzB,QAAI,KAAK,2BAA2B;AAClC,aAAO,KAAK,wBAAwB,MAAM;AAAA,IAC5C;AACA,WAAO;AAAA,EACT;AAAA,EACA,wBAAwB,KAAK;AAC3B,WAAO,IAAI,KAAK,CAAC,kBAAkB;AACjC,aAAO;AAAA,QACL;AAAA,QACA,CAAC,OAAO;AACN,eAAK,cAAc,KAAK,EAAE;AAC1B,iBAAO,MAAM;AACX,iBAAK,gBAAgB,KAAK,cAAc,OAAO,CAAC,QAAQ,QAAQ,EAAE;AAAA,UACpE;AAAA,QACF;AAAA,QACA,MAAM,KAAK,QAAO;AAAA,MAC1B;AAAA,IACI,CAAC;AAAA,EACH;AAAA,EACA,UAAU;AACR,WAAO,KAAK,QAAO,EAAG,KAAK,CAAC,cAAc;AACxC,UAAI,qBAAqB,SAAS,GAAG;AACnC,cAAM,QAAQ,UAAU,KAAI,IAAK,GAAG,UAAU,MAAM,IAAI,IAAI,IAAI,UAAU,MAAM,OAAO;AACvF,aAAK,cAAc,QAAQ,CAAC,OAAO;AACjC,aAAG,KAAK;AAAA,QACV,CAAC;AAAA,MACH;AACA,aAAO,GAAG,MAAM;AAAA,IAClB,CAAC;AAAA,EACH;AAAA,EACA,MAAM,kBAAkB,UAAU;AAAA,EAClC;AACF;ACxBA,SAAS,mBAAsB,SAAqD;AAChF,SAAO,wBAAwB,WAAY,QAAgB,uBAAuB;AACtF;AAYA,SAAS,eAAe,SAAuC;AAC3D,SAAO,WAAW,OAAO,YAAY,YAAY,iBAAiB;AACtE;AAYO,SAAS,yBAA4B,SAAqB,SAA0B;AACvF,MAAI,EAAC,mCAAS,WAAU,GAAE,mCAAS,mBAAkB,cAAc;AAC/D,WAAO;AAAA,EACX;AACA,QAAM,EAAE,WAAW;AAGnB,MAAI,mBAAmB,OAAO,GAAG;AAC7B,QAAI,QAAQ,IAAI,aAAa,cAAc;AACvC,cAAQ;AAAA,QACJ;AAAA,MAAA;AAAA,IAER;AACA,WAAO;AAAA,EACX;AAGA,MAAI,CAAC,eAAe,OAAO,GAAG;AAC1B,QAAI,QAAQ,IAAI,aAAa,cAAc;AACvC,cAAQ;AAAA,QACJ,WAAW,QAAQ,YAAY,IAAI;AAAA,MAAA;AAAA,IAG3C;AAEA,WAAO;AAAA,EACX;AAEA,MAAI;AACA,WAAO,IAAI,MAAM,SAAS;AAAA,MACtB,IAAI,QAAa,MAAuB,UAAoB;AAExD,YAAI,SAAS,sBAAsB;AAC/B,iBAAO;AAAA,QACX;AAGA,YAAI,SAAS,UAAU;AACnB,iBAAO;AAAA,QACX;AAGA,YAAI,SAAS,eAAe;AACxB,gBAAM,sBAAsB,OAAO,IAAI;AAGvC,gBAAM,aAAa,OAAO,wBAAwB;AAGlD,cAAI,OAAO,wBAAwB,YAAY;AAE3C,mBAAO,YAAwB,MAAa;AACxC,oBAAM,sBAAsB,oBAAoB,MAAM,MAAM,IAAI;AAGhE,kBAAI,CAAC,YAAY;AACb,sBAAM,CAAC,KAAK,OAAO,CAAA,CAAE,IAAI;AACzB,uBAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM;AAAA,cACpC;AAEA,qBAAO;AAAA,YACX;AAAA,UACJ,OAAO;AAEH,gBACI,CAAC,cACD,uBACA,MAAM,QAAQ,mBAAmB,GACnC;AACE,oBAAM,CAAC,KAAK,OAAO,CAAA,CAAE,IAAI;AACzB,qBAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM;AAAA,YACpC;AAEA,mBAAO;AAAA,UACX;AAAA,QACJ;AAGA,eAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAAA,MAC7C;AAAA,MACA,IAAI,QAAa,MAAgC;AAE7C,YAAI,SAAS,wBAAwB,SAAS,UAAU;AACpD,iBAAO;AAAA,QACX;AACA,eAAO,QAAQ,IAAI,QAAQ,IAAI;AAAA,MACnC;AAAA,IAAA,CACH;AAAA,EACL,SAAS,OAAO;AACZ,QAAI,QAAQ,IAAI,aAAa,cAAc;AACvC,cAAQ;AAAA,QACJ;AAAA,QACA;AAAA,MAAA;AAAA,IAER;AAEA,WAAO;AAAA,EACX;AACJ;AC9IO,MAAe,uBAAf,MAAe,6BAGZ,eAAwD;AAAA,EAS9D,YAAsB,UAA6C;AAC/D,UAAM,QAAQ;AADI,SAAA,WAAA;AAYtB,SAAmB,0BAAiD,CAAA;AAAA,EAVpE;AAAA,EAEA,QAA0C;AACtC,QAAI;AACA,aAAO,KAAK,2BAA2B,KAAK,SAAS,MAAM,GAAG,KAAK,WAAW,CAAC;AAAA,IACnF,SAAS,QAAQ;AACb,aAAO,oBAAoB,IAAI,QAAQ,MAAM,CAAC,CAAC;AAAA,IACnD;AAAA,EACJ;AAAA,EAIU,uBAAuB,UAA6B;AAC1D,WAAO,KAAK,wBAAwB,SAAS,SAAS,MAAM;AAAA,EAChE;AAAA,EAEU,uBAAuB,QAAyB;AACtD,WAAO,WAAW,OAAO,WAAW;AAAA,EACxC;AAAA,EAEQ,2BAA2B,UAA6B;AAC5D,WACI,KAAK,uBAAuB,SAAS,MAAM,KAAK,CAAC,KAAK,uBAAuB,QAAQ;AAAA,EAE7F;AAAA,EAEA,MAAgB,YAAY,eAAyC;AACjE,WAAO,QAAQ,cAAc,UAAU;AAAA,EAC3C;AAAA,EAEQ,2BACJ,UACgC;AAChC,WAAO,SAAS;AAAA,MACZ,CAACA,cAAa;AACV,YAAIA,UAAS,IAAI;AACb,cAAI;AACJ,cAAI,KAAK,uBAAuBA,SAAQ,GAAG;AACvC,4BAAgB,QAAQ,QAAQ,GAAG,IAAY,CAAC;AAAA,UACpD,WAAW,KAAK,2BAA2BA,SAAQ,GAAG;AAClD,4BAAgB,QAAQ;AAAA,cACpB;AAAA,gBACI;AAAA,kBACI,cAAcA,UAAS,MAAM;AAAA,gBAAA;AAAA,cACjC;AAAA,YACJ;AAAA,UAER,OAAO;AACH,4BAAgBA,UAAS,OAAO;AAAA,cAC5B,CAAC,SAAe,GAAG,IAAI;AAAA,cACvB,CAAC,WAAgB,IAAI,QAAQ,MAAM,CAAC;AAAA,YAAA;AAAA,UAE5C;AACA,iBAAO,cAAc,QAAQ,MAAM;AAC/B,gBAAI;AACA,mBAAK,kBAAkB,EAAE,YAAYA,UAAS,QAAQ;AAAA,YAC1D,QAAQ;AAAA,YAER;AAAA,UACJ,CAAC;AAAA,QACL,OAAO;AACH,iBAAO,KAAK,YAAYA,SAAQ,EAC3B,KAAK,CAAC,iBAAiB;AACpB,mBAAO,IAAI,YAAY;AAAA,UAC3B,CAAC,EACA,QAAQ,MAAM;AACX,gBAAI;AACA,mBAAK,kBAAkB,EAAE,YAAYA,UAAS,QAAQ;AAAA,YAC1D,QAAQ;AAAA,YAER;AAAA,UACJ,CAAC;AAAA,QACT;AAAA,MACJ;AAAA,MACA,CAAC,WAAW,IAAI,QAAQ,MAAM,CAAC;AAAA,IAAA;AAAA,EAEvC;AAGJ;AArFI,qBAAgB,sBAAsB;AAAA,EAClC,WAAW;AAAA;AATZ,IAAe,sBAAf;ACOA,SAAS,yBAA+D;AAC3E,SAAO;AAAA,IACH,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,EAAA;AAEjB;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conduit-client/command-fetch-network",
3
- "version": "3.19.0",
3
+ "version": "3.19.2",
4
4
  "private": false,
5
5
  "description": "Luvio Fetch Network Command",
6
6
  "type": "module",
@@ -31,10 +31,10 @@
31
31
  "watch": "npm run build --watch"
32
32
  },
33
33
  "dependencies": {
34
- "@conduit-client/command-base": "3.19.0",
35
- "@conduit-client/command-network": "3.19.0",
36
- "@conduit-client/service-fetch-network": "3.19.0",
37
- "@conduit-client/utils": "3.19.0"
34
+ "@conduit-client/command-base": "3.19.2",
35
+ "@conduit-client/command-network": "3.19.2",
36
+ "@conduit-client/service-fetch-network": "3.19.2",
37
+ "@conduit-client/utils": "3.19.2"
38
38
  },
39
39
  "volta": {
40
40
  "extends": "../../../../package.json"