@bessemer/cornerstone 0.5.37 → 0.5.38

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/cache.js CHANGED
@@ -11,7 +11,7 @@ var CacheProps;
11
11
  };
12
12
  CacheProps2.buildCacheProps = (options) => {
13
13
  options = options ?? {};
14
- const props = Objects.merge(DefaultCacheProps, options);
14
+ const props = Objects.deepMerge(DefaultCacheProps, options);
15
15
  if (props.maxSize === null && props.timeToLive === null) {
16
16
  throw new Error("Invalid cache configuration, both maxSize and timeToLive are null");
17
17
  }
package/dist/cache.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cache.ts"],"sourcesContent":["import { AbstractLocalKeyValueStore, AbstractRemoteKeyValueStore, LocalKeyValueStore, RemoteKeyValueStore } from '@bessemer/cornerstone/store'\nimport { Arrays, Dates, Durations, Objects, Strings, Zod } from '@bessemer/cornerstone'\nimport { Duration } from '@bessemer/cornerstone/duration'\nimport { ResourceKey, ResourceNamespace } from '@bessemer/cornerstone/resource'\nimport { AbstractApplicationContext } from '@bessemer/cornerstone/context'\nimport { NominalType } from '@bessemer/cornerstone/types'\nimport { Entry } from '@bessemer/cornerstone/entry'\nimport { GlobPattern } from '@bessemer/cornerstone/glob'\nimport { Arrayable } from 'type-fest'\nimport { ZodType } from 'zod'\n\n// JOHN should this even be in cornerstone? especially consider the config types down at the bottom\n\nexport type CacheProps = {\n maxSize: number | null\n timeToLive: Duration\n timeToStale: Duration | null\n}\n\nexport type CacheOptions = Partial<CacheProps>\n\nexport namespace CacheProps {\n const DefaultCacheProps = {\n maxSize: 50000,\n timeToLive: Durations.OneDay,\n timeToStale: Durations.OneHour,\n }\n\n export const buildCacheProps = (options?: CacheOptions): CacheProps => {\n options = options ?? {}\n\n const props = Objects.merge(DefaultCacheProps, options)\n\n if (props.maxSize === null && props.timeToLive === null) {\n throw new Error('Invalid cache configuration, both maxSize and timeToLive are null')\n }\n\n return props\n }\n}\n\nexport namespace CacheKey {\n // We use a hardcoded UUID to represent a unique token value that serves as a flag to disable caching\n const DisableCacheToken = 'f6822c1a-d527-4c65-b9dd-ddc24620b684'\n\n export const disableCaching = (): ResourceNamespace => {\n return DisableCacheToken\n }\n\n export const isDisabled = (key: ResourceNamespace): boolean => {\n return Strings.contains(key, DisableCacheToken)\n }\n}\n\nexport type CacheSector = {\n globs: Array<GlobPattern>\n}\n\nexport namespace CacheSector {\n export const of = (globs: Arrayable<GlobPattern>) => {\n return { globs: Arrays.toArray(globs) }\n }\n\n export const namespace = (namespace: ResourceNamespace, sector: CacheSector): CacheSector => {\n return { globs: ResourceKey.namespaceAll(namespace, sector.globs) }\n }\n}\n\nexport type CacheName = NominalType<string, 'CacheName'>\nexport const CacheNameSchema: ZodType<CacheName> = Zod.string()\n\nexport interface AbstractCache<T> {\n name: CacheName\n}\n\nexport interface Cache<T> extends AbstractCache<T> {\n fetchValue(namespace: ResourceNamespace, key: ResourceKey, fetch: () => Promise<T>): Promise<T>\n\n fetchValues(\n namespace: ResourceNamespace,\n keys: Array<ResourceKey>,\n fetch: (keys: Array<ResourceKey>) => Promise<Array<Entry<T>>>\n ): Promise<Array<Entry<T>>>\n\n writeValue(namespace: ResourceNamespace, key: ResourceKey, value: T | undefined): Promise<void>\n\n writeValues(namespace: ResourceNamespace, entries: Array<Entry<T | undefined>>): Promise<void>\n\n evictAll(sector: CacheSector): Promise<void>\n}\n\nexport interface CacheProvider<T> extends RemoteKeyValueStore<CacheEntry<T>> {\n type: CacheProviderType\n\n evictAll(sector: CacheSector): Promise<void>\n}\n\nexport abstract class AbstractCacheProvider<T> extends AbstractRemoteKeyValueStore<CacheEntry<T>> implements CacheProvider<T> {\n abstract type: CacheProviderType\n\n abstract evictAll(sector: CacheSector): Promise<void>\n}\n\nexport interface LocalCache<T> extends AbstractCache<T> {\n getValue(namespace: ResourceNamespace, key: ResourceKey, fetch: () => T): T\n\n getValues(namespace: ResourceNamespace, keys: Array<ResourceKey>, fetch: (keys: Array<ResourceKey>) => Array<Entry<T>>): Array<Entry<T>>\n\n setValue(namespace: ResourceNamespace, key: ResourceKey, value: T | undefined): void\n\n setValues(namespace: ResourceNamespace, entries: Array<Entry<T | undefined>>): void\n\n removeAll(sector: CacheSector): void\n}\n\nexport interface LocalCacheProvider<T> extends LocalKeyValueStore<CacheEntry<T>>, CacheProvider<T> {\n removeAll(sector: CacheSector): void\n}\n\nexport abstract class AbstractLocalCacheProvider<T> extends AbstractLocalKeyValueStore<CacheEntry<T>> implements LocalCacheProvider<T> {\n abstract type: CacheProviderType\n\n abstract removeAll(sector: CacheSector): void\n\n async evictAll(sector: CacheSector): Promise<void> {\n this.removeAll(sector)\n }\n}\n\nexport type CacheEntry<T> = {\n value: T\n liveTimestamp: Date | null\n staleTimestamp: Date | null\n}\n\nexport namespace CacheEntry {\n export const isActive = <T>(entry: CacheEntry<T>): boolean => {\n if (isDead(entry) || isStale(entry)) {\n return false\n }\n\n return true\n }\n\n export const isDead = <T>(entry: CacheEntry<T> | undefined): boolean => {\n if (Objects.isNil(entry)) {\n return true\n }\n\n if (Objects.isNil(entry.liveTimestamp)) {\n return false\n }\n\n return Dates.isBefore(entry.liveTimestamp, Dates.now())\n }\n\n export const isAlive = <T>(entry: CacheEntry<T> | undefined): boolean => !isDead(entry)\n\n export const isStale = <T>(entry: CacheEntry<T>): boolean => {\n if (Objects.isNil(entry.staleTimestamp)) {\n return false\n }\n\n return Dates.isBefore(entry.staleTimestamp, Dates.now())\n }\n\n export const of = <T>(value: T) => {\n const entry: CacheEntry<T> = {\n value,\n liveTimestamp: null,\n staleTimestamp: null,\n }\n\n return entry\n }\n\n // JOHN do we want to enforce some kind of minimum liveness threshold?\n export const applyProps = <T>(originalEntry: CacheEntry<T>, props: CacheProps): CacheEntry<T> => {\n let liveTimestamp: Date | null = originalEntry.liveTimestamp\n if (!Objects.isNil(props.timeToLive)) {\n const limit = Dates.addMilliseconds(Dates.now(), Durations.inMilliseconds(props.timeToLive))\n if (Dates.isBefore(limit, liveTimestamp ?? limit)) {\n liveTimestamp = limit\n }\n }\n\n let staleTimestamp: Date | null = originalEntry.staleTimestamp\n if (!Objects.isNil(props.timeToStale)) {\n const limit = Dates.addMilliseconds(Dates.now(), Durations.inMilliseconds(props.timeToStale))\n if (Dates.isBefore(limit, staleTimestamp ?? limit)) {\n staleTimestamp = limit\n }\n }\n\n const limitedEntry: CacheEntry<T> = {\n value: originalEntry.value,\n liveTimestamp,\n staleTimestamp,\n }\n\n return limitedEntry\n }\n}\n\nexport type CacheConfigurationOptions = CacheConfigurationSection & {\n local: CacheConfigurationSection\n}\n\nexport type CacheConfigurationSection = {\n defaults: CacheDefinition\n\n /**\n * These options map from cache name key to configuration. They are a way for the tenant to override the configurations\n * for specific caches from the cache configuration here.\n */\n caches?: Record<string, Partial<CacheDefinition>>\n}\n\nexport type CacheDefinition = {\n options?: CacheOptions\n providers: Array<CacheProviderConfiguration>\n}\n\nexport type CacheProviderType = NominalType<string, 'CacheProviderType'>\nexport type CacheProviderConfiguration = CacheOptions & {\n type: CacheProviderType\n}\n\nexport type CacheConfiguration = CacheConfigurationSection & {\n local: CacheConfigurationSection\n}\n\nexport type CacheProviderRegistry<ContextType extends AbstractApplicationContext> = {\n type: CacheProviderType\n construct: <T>(props: CacheProps, context: ContextType) => CacheProvider<T>\n}\n"],"mappings":"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","names":["CacheProps","CacheKey","CacheSector","namespace","CacheEntry"]}
1
+ {"version":3,"sources":["../src/cache.ts"],"sourcesContent":["import { AbstractLocalKeyValueStore, AbstractRemoteKeyValueStore, LocalKeyValueStore, RemoteKeyValueStore } from '@bessemer/cornerstone/store'\nimport { Arrays, Dates, Durations, Objects, Strings, Zod } from '@bessemer/cornerstone'\nimport { Duration } from '@bessemer/cornerstone/duration'\nimport { ResourceKey, ResourceNamespace } from '@bessemer/cornerstone/resource'\nimport { AbstractApplicationContext } from '@bessemer/cornerstone/context'\nimport { NominalType } from '@bessemer/cornerstone/types'\nimport { Entry } from '@bessemer/cornerstone/entry'\nimport { GlobPattern } from '@bessemer/cornerstone/glob'\nimport { Arrayable } from 'type-fest'\nimport { ZodType } from 'zod'\n\n// JOHN should this even be in cornerstone? especially consider the config types down at the bottom\n\nexport type CacheProps = {\n maxSize: number | null\n timeToLive: Duration\n timeToStale: Duration | null\n}\n\nexport type CacheOptions = Partial<CacheProps>\n\nexport namespace CacheProps {\n const DefaultCacheProps = {\n maxSize: 50000,\n timeToLive: Durations.OneDay,\n timeToStale: Durations.OneHour,\n }\n\n export const buildCacheProps = (options?: CacheOptions): CacheProps => {\n options = options ?? {}\n\n const props = Objects.deepMerge(DefaultCacheProps, options)\n\n if (props.maxSize === null && props.timeToLive === null) {\n throw new Error('Invalid cache configuration, both maxSize and timeToLive are null')\n }\n\n return props\n }\n}\n\nexport namespace CacheKey {\n // We use a hardcoded UUID to represent a unique token value that serves as a flag to disable caching\n const DisableCacheToken = 'f6822c1a-d527-4c65-b9dd-ddc24620b684'\n\n export const disableCaching = (): ResourceNamespace => {\n return DisableCacheToken\n }\n\n export const isDisabled = (key: ResourceNamespace): boolean => {\n return Strings.contains(key, DisableCacheToken)\n }\n}\n\nexport type CacheSector = {\n globs: Array<GlobPattern>\n}\n\nexport namespace CacheSector {\n export const of = (globs: Arrayable<GlobPattern>) => {\n return { globs: Arrays.toArray(globs) }\n }\n\n export const namespace = (namespace: ResourceNamespace, sector: CacheSector): CacheSector => {\n return { globs: ResourceKey.namespaceAll(namespace, sector.globs) }\n }\n}\n\nexport type CacheName = NominalType<string, 'CacheName'>\nexport const CacheNameSchema: ZodType<CacheName> = Zod.string()\n\nexport interface AbstractCache<T> {\n name: CacheName\n}\n\nexport interface Cache<T> extends AbstractCache<T> {\n fetchValue(namespace: ResourceNamespace, key: ResourceKey, fetch: () => Promise<T>): Promise<T>\n\n fetchValues(\n namespace: ResourceNamespace,\n keys: Array<ResourceKey>,\n fetch: (keys: Array<ResourceKey>) => Promise<Array<Entry<T>>>\n ): Promise<Array<Entry<T>>>\n\n writeValue(namespace: ResourceNamespace, key: ResourceKey, value: T | undefined): Promise<void>\n\n writeValues(namespace: ResourceNamespace, entries: Array<Entry<T | undefined>>): Promise<void>\n\n evictAll(sector: CacheSector): Promise<void>\n}\n\nexport interface CacheProvider<T> extends RemoteKeyValueStore<CacheEntry<T>> {\n type: CacheProviderType\n\n evictAll(sector: CacheSector): Promise<void>\n}\n\nexport abstract class AbstractCacheProvider<T> extends AbstractRemoteKeyValueStore<CacheEntry<T>> implements CacheProvider<T> {\n abstract type: CacheProviderType\n\n abstract evictAll(sector: CacheSector): Promise<void>\n}\n\nexport interface LocalCache<T> extends AbstractCache<T> {\n getValue(namespace: ResourceNamespace, key: ResourceKey, fetch: () => T): T\n\n getValues(namespace: ResourceNamespace, keys: Array<ResourceKey>, fetch: (keys: Array<ResourceKey>) => Array<Entry<T>>): Array<Entry<T>>\n\n setValue(namespace: ResourceNamespace, key: ResourceKey, value: T | undefined): void\n\n setValues(namespace: ResourceNamespace, entries: Array<Entry<T | undefined>>): void\n\n removeAll(sector: CacheSector): void\n}\n\nexport interface LocalCacheProvider<T> extends LocalKeyValueStore<CacheEntry<T>>, CacheProvider<T> {\n removeAll(sector: CacheSector): void\n}\n\nexport abstract class AbstractLocalCacheProvider<T> extends AbstractLocalKeyValueStore<CacheEntry<T>> implements LocalCacheProvider<T> {\n abstract type: CacheProviderType\n\n abstract removeAll(sector: CacheSector): void\n\n async evictAll(sector: CacheSector): Promise<void> {\n this.removeAll(sector)\n }\n}\n\nexport type CacheEntry<T> = {\n value: T\n liveTimestamp: Date | null\n staleTimestamp: Date | null\n}\n\nexport namespace CacheEntry {\n export const isActive = <T>(entry: CacheEntry<T>): boolean => {\n if (isDead(entry) || isStale(entry)) {\n return false\n }\n\n return true\n }\n\n export const isDead = <T>(entry: CacheEntry<T> | undefined): boolean => {\n if (Objects.isNil(entry)) {\n return true\n }\n\n if (Objects.isNil(entry.liveTimestamp)) {\n return false\n }\n\n return Dates.isBefore(entry.liveTimestamp, Dates.now())\n }\n\n export const isAlive = <T>(entry: CacheEntry<T> | undefined): boolean => !isDead(entry)\n\n export const isStale = <T>(entry: CacheEntry<T>): boolean => {\n if (Objects.isNil(entry.staleTimestamp)) {\n return false\n }\n\n return Dates.isBefore(entry.staleTimestamp, Dates.now())\n }\n\n export const of = <T>(value: T) => {\n const entry: CacheEntry<T> = {\n value,\n liveTimestamp: null,\n staleTimestamp: null,\n }\n\n return entry\n }\n\n // JOHN do we want to enforce some kind of minimum liveness threshold?\n export const applyProps = <T>(originalEntry: CacheEntry<T>, props: CacheProps): CacheEntry<T> => {\n let liveTimestamp: Date | null = originalEntry.liveTimestamp\n if (!Objects.isNil(props.timeToLive)) {\n const limit = Dates.addMilliseconds(Dates.now(), Durations.inMilliseconds(props.timeToLive))\n if (Dates.isBefore(limit, liveTimestamp ?? limit)) {\n liveTimestamp = limit\n }\n }\n\n let staleTimestamp: Date | null = originalEntry.staleTimestamp\n if (!Objects.isNil(props.timeToStale)) {\n const limit = Dates.addMilliseconds(Dates.now(), Durations.inMilliseconds(props.timeToStale))\n if (Dates.isBefore(limit, staleTimestamp ?? limit)) {\n staleTimestamp = limit\n }\n }\n\n const limitedEntry: CacheEntry<T> = {\n value: originalEntry.value,\n liveTimestamp,\n staleTimestamp,\n }\n\n return limitedEntry\n }\n}\n\nexport type CacheConfigurationOptions = CacheConfigurationSection & {\n local: CacheConfigurationSection\n}\n\nexport type CacheConfigurationSection = {\n defaults: CacheDefinition\n\n /**\n * These options map from cache name key to configuration. They are a way for the tenant to override the configurations\n * for specific caches from the cache configuration here.\n */\n caches?: Record<string, Partial<CacheDefinition>>\n}\n\nexport type CacheDefinition = {\n options?: CacheOptions\n providers: Array<CacheProviderConfiguration>\n}\n\nexport type CacheProviderType = NominalType<string, 'CacheProviderType'>\nexport type CacheProviderConfiguration = CacheOptions & {\n type: CacheProviderType\n}\n\nexport type CacheConfiguration = CacheConfigurationSection & {\n local: CacheConfigurationSection\n}\n\nexport type CacheProviderRegistry<ContextType extends AbstractApplicationContext> = {\n type: CacheProviderType\n construct: <T>(props: CacheProps, context: ContextType) => CacheProvider<T>\n}\n"],"mappings":"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","names":["CacheProps","CacheKey","CacheSector","namespace","CacheEntry"]}
@@ -59,14 +59,14 @@ var NotFoundErrorCode = "error-event.not-found";
59
59
  var RequestCorrelationIdAttribute = "requestCorrelationId";
60
60
  var HttpStatusCodeAttribute = "httpStatusCode";
61
61
  var unhandled = (builder) => of(
62
- Objects.merge(builder, {
62
+ Objects.deepMerge(builder, {
63
63
  code: UnhandledErrorCode,
64
64
  message: "An Unhandled Error has occurred.",
65
65
  attributes: { [HttpStatusCodeAttribute]: 500 }
66
66
  })
67
67
  );
68
68
  var notFound = (builder) => of(
69
- Objects.merge(builder, {
69
+ Objects.deepMerge(builder, {
70
70
  code: NotFoundErrorCode,
71
71
  message: "The requested Resource could not be found.",
72
72
  attributes: { [HttpStatusCodeAttribute]: 404 }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/error-event.ts"],"sourcesContent":["import { Arrays, Errors, Objects } from '@bessemer/cornerstone'\nimport { NominalType, Throwable } from '@bessemer/cornerstone/types'\nimport { RecordAttribute } from '@bessemer/cornerstone/object'\n\n/*\n Represents a structured error event. The code can be mapped to a unique type of error while the\n message and attributes can provide contextual information about the error. Finally,\n an ErrorEvent could have multiple causes which get aggregated into a single parent error.\n */\nexport type ErrorCode = NominalType<string, 'ErrorCode'>\nexport type ErrorAttribute<Type = unknown> = RecordAttribute<Type, 'ErrorAttribute'>\n\nexport type ErrorEvent = {\n code: ErrorCode\n message: string\n attributes: Record<ErrorAttribute, unknown>\n causes: Array<ErrorEvent>\n}\n\n// Builder object that allows for 'partial' representation of ErrorEvents\nexport type ErrorEventBuilder = {\n code: ErrorCode\n message?: string | null\n attributes?: Record<ErrorAttribute, unknown>\n causes?: Array<ErrorEvent>\n}\n\n// An exception type that contains an ErrorEvent\nexport class ErrorEventException extends Error {\n readonly errorEvent: ErrorEvent\n\n constructor(errorEvent: ErrorEvent, cause?: unknown) {\n super(errorEvent.message ?? '', { cause })\n this.name = this.constructor.name\n this.errorEvent = errorEvent\n }\n}\n\nexport const isErrorEvent = (throwable: Throwable): throwable is ErrorEvent => {\n if (!Objects.isObject(throwable)) {\n return false\n }\n\n return 'code' in throwable && 'message' in throwable && 'attributes' in throwable && 'causes' in throwable\n}\n\nexport const isErrorEventException = (throwable: Throwable): throwable is ErrorEventException => {\n return throwable instanceof ErrorEventException\n}\n\nexport const of = (builder: ErrorEventBuilder): ErrorEvent => {\n const code = builder.code\n\n return {\n code,\n message: builder.message ?? code,\n attributes: builder.attributes ?? {},\n causes: builder.causes ?? [],\n }\n}\n\nexport const from = (throwable: Throwable): ErrorEvent => {\n if (isErrorEvent(throwable)) {\n return throwable\n }\n\n if (!Errors.isError(throwable)) {\n return unhandled()\n }\n\n const errorEventException = Errors.findInCausalChain(throwable, isErrorEventException) as ErrorEventException | undefined\n if (Objects.isNil(errorEventException)) {\n return unhandled()\n }\n\n return errorEventException.errorEvent\n}\n\nexport const findByCodeInCausalChain = (error: ErrorEvent, code: string): ErrorEvent | undefined => {\n return findInCausalChain(error, (it) => it.code === code)\n}\n\n/*\n Traverses the causal chain of the ErrorEvent, searching for a predicate that matches (including matching on the parent error event)\n This is useful if you want to find whether or not a given error was caused by a specific failure. The search executes depth-first and\n will return te first matching instance that satisfies the predicate, or undefined otherwise\n */\nexport const findInCausalChain = (error: ErrorEvent, predicate: (error: ErrorEvent) => boolean): ErrorEvent | undefined => {\n if (predicate(error)) {\n return error\n }\n\n return Arrays.first(error.causes.map((it) => findInCausalChain(it, predicate)).filter(Objects.isPresent))\n}\n\nexport const aggregate = (builder: ErrorEventBuilder, causes: Array<ErrorEvent>): ErrorEvent | undefined => {\n if (causes.length === 0) {\n return undefined\n }\n\n return of({ ...builder, causes })\n}\n\nexport const UnhandledErrorCode: ErrorCode = 'error-event.unhandled'\nexport const NotFoundErrorCode: ErrorCode = 'error-event.not-found'\n\nexport const RequestCorrelationIdAttribute: ErrorAttribute<string> = 'requestCorrelationId'\nexport const HttpStatusCodeAttribute: ErrorAttribute<number> = 'httpStatusCode'\n\nexport const unhandled = (builder?: ErrorEventBuilder) =>\n of(\n Objects.merge(builder, {\n code: UnhandledErrorCode,\n message: 'An Unhandled Error has occurred.',\n attributes: { [HttpStatusCodeAttribute]: 500 },\n })\n )\n\nexport const notFound = (builder?: ErrorEventBuilder) =>\n of(\n Objects.merge(builder, {\n code: NotFoundErrorCode,\n message: 'The requested Resource could not be found.',\n attributes: { [HttpStatusCodeAttribute]: 404 },\n })\n )\n"],"mappings":";AAAA,SAAS,QAAQ,QAAQ,eAAe;AA4BjC,IAAM,sBAAN,cAAkC,MAAM;AAAA,EACpC;AAAA,EAET,YAAY,YAAwB,OAAiB;AACnD,UAAM,WAAW,WAAW,IAAI,EAAE,MAAM,CAAC;AACzC,SAAK,OAAO,KAAK,YAAY;AAC7B,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,eAAe,CAAC,cAAkD;AAC7E,MAAI,CAAC,QAAQ,SAAS,SAAS,GAAG;AAChC,WAAO;AAAA,EACT;AAEA,SAAO,UAAU,aAAa,aAAa,aAAa,gBAAgB,aAAa,YAAY;AACnG;AAEO,IAAM,wBAAwB,CAAC,cAA2D;AAC/F,SAAO,qBAAqB;AAC9B;AAEO,IAAM,KAAK,CAAC,YAA2C;AAC5D,QAAM,OAAO,QAAQ;AAErB,SAAO;AAAA,IACL;AAAA,IACA,SAAS,QAAQ,WAAW;AAAA,IAC5B,YAAY,QAAQ,cAAc,CAAC;AAAA,IACnC,QAAQ,QAAQ,UAAU,CAAC;AAAA,EAC7B;AACF;AAEO,IAAM,OAAO,CAAC,cAAqC;AACxD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,OAAO,QAAQ,SAAS,GAAG;AAC9B,WAAO,UAAU;AAAA,EACnB;AAEA,QAAM,sBAAsB,OAAO,kBAAkB,WAAW,qBAAqB;AACrF,MAAI,QAAQ,MAAM,mBAAmB,GAAG;AACtC,WAAO,UAAU;AAAA,EACnB;AAEA,SAAO,oBAAoB;AAC7B;AAEO,IAAM,0BAA0B,CAAC,OAAmB,SAAyC;AAClG,SAAO,kBAAkB,OAAO,CAAC,OAAO,GAAG,SAAS,IAAI;AAC1D;AAOO,IAAM,oBAAoB,CAAC,OAAmB,cAAsE;AACzH,MAAI,UAAU,KAAK,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,MAAM,MAAM,OAAO,IAAI,CAAC,OAAO,kBAAkB,IAAI,SAAS,CAAC,EAAE,OAAO,QAAQ,SAAS,CAAC;AAC1G;AAEO,IAAM,YAAY,CAAC,SAA4B,WAAsD;AAC1G,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,SAAO,GAAG,EAAE,GAAG,SAAS,OAAO,CAAC;AAClC;AAEO,IAAM,qBAAgC;AACtC,IAAM,oBAA+B;AAErC,IAAM,gCAAwD;AAC9D,IAAM,0BAAkD;AAExD,IAAM,YAAY,CAAC,YACxB;AAAA,EACE,QAAQ,MAAM,SAAS;AAAA,IACrB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY,EAAE,CAAC,uBAAuB,GAAG,IAAI;AAAA,EAC/C,CAAC;AACH;AAEK,IAAM,WAAW,CAAC,YACvB;AAAA,EACE,QAAQ,MAAM,SAAS;AAAA,IACrB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY,EAAE,CAAC,uBAAuB,GAAG,IAAI;AAAA,EAC/C,CAAC;AACH;","names":[]}
1
+ {"version":3,"sources":["../src/error-event.ts"],"sourcesContent":["import { Arrays, Errors, Objects } from '@bessemer/cornerstone'\nimport { NominalType, Throwable } from '@bessemer/cornerstone/types'\nimport { RecordAttribute } from '@bessemer/cornerstone/object'\n\n/*\n Represents a structured error event. The code can be mapped to a unique type of error while the\n message and attributes can provide contextual information about the error. Finally,\n an ErrorEvent could have multiple causes which get aggregated into a single parent error.\n */\nexport type ErrorCode = NominalType<string, 'ErrorCode'>\nexport type ErrorAttribute<Type = unknown> = RecordAttribute<Type, 'ErrorAttribute'>\n\nexport type ErrorEvent = {\n code: ErrorCode\n message: string\n attributes: Record<ErrorAttribute, unknown>\n causes: Array<ErrorEvent>\n}\n\n// Builder object that allows for 'partial' representation of ErrorEvents\nexport type ErrorEventBuilder = {\n code: ErrorCode\n message?: string | null\n attributes?: Record<ErrorAttribute, unknown>\n causes?: Array<ErrorEvent>\n}\n\n// An exception type that contains an ErrorEvent\nexport class ErrorEventException extends Error {\n readonly errorEvent: ErrorEvent\n\n constructor(errorEvent: ErrorEvent, cause?: unknown) {\n super(errorEvent.message ?? '', { cause })\n this.name = this.constructor.name\n this.errorEvent = errorEvent\n }\n}\n\nexport const isErrorEvent = (throwable: Throwable): throwable is ErrorEvent => {\n if (!Objects.isObject(throwable)) {\n return false\n }\n\n return 'code' in throwable && 'message' in throwable && 'attributes' in throwable && 'causes' in throwable\n}\n\nexport const isErrorEventException = (throwable: Throwable): throwable is ErrorEventException => {\n return throwable instanceof ErrorEventException\n}\n\nexport const of = (builder: ErrorEventBuilder): ErrorEvent => {\n const code = builder.code\n\n return {\n code,\n message: builder.message ?? code,\n attributes: builder.attributes ?? {},\n causes: builder.causes ?? [],\n }\n}\n\nexport const from = (throwable: Throwable): ErrorEvent => {\n if (isErrorEvent(throwable)) {\n return throwable\n }\n\n if (!Errors.isError(throwable)) {\n return unhandled()\n }\n\n const errorEventException = Errors.findInCausalChain(throwable, isErrorEventException) as ErrorEventException | undefined\n if (Objects.isNil(errorEventException)) {\n return unhandled()\n }\n\n return errorEventException.errorEvent\n}\n\nexport const findByCodeInCausalChain = (error: ErrorEvent, code: string): ErrorEvent | undefined => {\n return findInCausalChain(error, (it) => it.code === code)\n}\n\n/*\n Traverses the causal chain of the ErrorEvent, searching for a predicate that matches (including matching on the parent error event)\n This is useful if you want to find whether or not a given error was caused by a specific failure. The search executes depth-first and\n will return te first matching instance that satisfies the predicate, or undefined otherwise\n */\nexport const findInCausalChain = (error: ErrorEvent, predicate: (error: ErrorEvent) => boolean): ErrorEvent | undefined => {\n if (predicate(error)) {\n return error\n }\n\n return Arrays.first(error.causes.map((it) => findInCausalChain(it, predicate)).filter(Objects.isPresent))\n}\n\nexport const aggregate = (builder: ErrorEventBuilder, causes: Array<ErrorEvent>): ErrorEvent | undefined => {\n if (causes.length === 0) {\n return undefined\n }\n\n return of({ ...builder, causes })\n}\n\nexport const UnhandledErrorCode: ErrorCode = 'error-event.unhandled'\nexport const NotFoundErrorCode: ErrorCode = 'error-event.not-found'\n\nexport const RequestCorrelationIdAttribute: ErrorAttribute<string> = 'requestCorrelationId'\nexport const HttpStatusCodeAttribute: ErrorAttribute<number> = 'httpStatusCode'\n\nexport const unhandled = (builder?: ErrorEventBuilder) =>\n of(\n Objects.deepMerge(builder, {\n code: UnhandledErrorCode,\n message: 'An Unhandled Error has occurred.',\n attributes: { [HttpStatusCodeAttribute]: 500 },\n })\n )\n\nexport const notFound = (builder?: ErrorEventBuilder) =>\n of(\n Objects.deepMerge(builder, {\n code: NotFoundErrorCode,\n message: 'The requested Resource could not be found.',\n attributes: { [HttpStatusCodeAttribute]: 404 },\n })\n )\n"],"mappings":";AAAA,SAAS,QAAQ,QAAQ,eAAe;AA4BjC,IAAM,sBAAN,cAAkC,MAAM;AAAA,EACpC;AAAA,EAET,YAAY,YAAwB,OAAiB;AACnD,UAAM,WAAW,WAAW,IAAI,EAAE,MAAM,CAAC;AACzC,SAAK,OAAO,KAAK,YAAY;AAC7B,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,eAAe,CAAC,cAAkD;AAC7E,MAAI,CAAC,QAAQ,SAAS,SAAS,GAAG;AAChC,WAAO;AAAA,EACT;AAEA,SAAO,UAAU,aAAa,aAAa,aAAa,gBAAgB,aAAa,YAAY;AACnG;AAEO,IAAM,wBAAwB,CAAC,cAA2D;AAC/F,SAAO,qBAAqB;AAC9B;AAEO,IAAM,KAAK,CAAC,YAA2C;AAC5D,QAAM,OAAO,QAAQ;AAErB,SAAO;AAAA,IACL;AAAA,IACA,SAAS,QAAQ,WAAW;AAAA,IAC5B,YAAY,QAAQ,cAAc,CAAC;AAAA,IACnC,QAAQ,QAAQ,UAAU,CAAC;AAAA,EAC7B;AACF;AAEO,IAAM,OAAO,CAAC,cAAqC;AACxD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,OAAO,QAAQ,SAAS,GAAG;AAC9B,WAAO,UAAU;AAAA,EACnB;AAEA,QAAM,sBAAsB,OAAO,kBAAkB,WAAW,qBAAqB;AACrF,MAAI,QAAQ,MAAM,mBAAmB,GAAG;AACtC,WAAO,UAAU;AAAA,EACnB;AAEA,SAAO,oBAAoB;AAC7B;AAEO,IAAM,0BAA0B,CAAC,OAAmB,SAAyC;AAClG,SAAO,kBAAkB,OAAO,CAAC,OAAO,GAAG,SAAS,IAAI;AAC1D;AAOO,IAAM,oBAAoB,CAAC,OAAmB,cAAsE;AACzH,MAAI,UAAU,KAAK,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,MAAM,MAAM,OAAO,IAAI,CAAC,OAAO,kBAAkB,IAAI,SAAS,CAAC,EAAE,OAAO,QAAQ,SAAS,CAAC;AAC1G;AAEO,IAAM,YAAY,CAAC,SAA4B,WAAsD;AAC1G,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,SAAO,GAAG,EAAE,GAAG,SAAS,OAAO,CAAC;AAClC;AAEO,IAAM,qBAAgC;AACtC,IAAM,oBAA+B;AAErC,IAAM,gCAAwD;AAC9D,IAAM,0BAAkD;AAExD,IAAM,YAAY,CAAC,YACxB;AAAA,EACE,QAAQ,UAAU,SAAS;AAAA,IACzB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY,EAAE,CAAC,uBAAuB,GAAG,IAAI;AAAA,EAC/C,CAAC;AACH;AAEK,IAAM,WAAW,CAAC,YACvB;AAAA,EACE,QAAQ,UAAU,SAAS;AAAA,IACzB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY,EAAE,CAAC,uBAAuB,GAAG,IAAI;AAAA,EAC/C,CAAC;AACH;","names":[]}
package/dist/logger.js CHANGED
@@ -45,7 +45,7 @@ var applyDefaultOptions = (options) => {
45
45
  // JOHN need to find a better way to include
46
46
  // ...getPrettyTransport(),
47
47
  };
48
- return Objects.merge(defaultOptions, options);
48
+ return Objects.deepMerge(defaultOptions, options);
49
49
  };
50
50
  var createProxyHandler = (getLogger) => {
51
51
  let cachedLogger = null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/logger.ts"],"sourcesContent":["import pino from 'pino'\nimport { Lazy, Objects } from '@bessemer/cornerstone'\nimport { createGlobalVariable } from '@bessemer/cornerstone/global-variable'\nimport { LazyValue } from '@bessemer/cornerstone/lazy'\nimport { UnknownRecord } from 'type-fest'\n\ntype PinoLogger = pino.Logger\ntype PinoBindings = pino.Bindings\nexport type LoggerOptions = pino.LoggerOptions\n\ntype LogOptions = { error?: unknown; context?: UnknownRecord }\ntype LogFunction = (message: LazyValue<string>, options?: LogOptions) => void\n\nexport class Logger {\n constructor(private readonly logger: PinoLogger) {}\n\n trace: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('trace') ?? true) {\n this.logger.trace({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n\n debug: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('debug') ?? true) {\n this.logger.debug({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n\n info: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('info') ?? true) {\n this.logger.info({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n\n warn: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('warn') ?? true) {\n this.logger.warn({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n\n error: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('error') ?? true) {\n this.logger.error({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n\n fatal: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('fatal') ?? true) {\n this.logger.fatal({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n}\n\nconst getPrettyTransport = (): LoggerOptions => {\n if (process.env.NODE_ENV === 'production' || typeof window !== 'undefined') {\n return {}\n }\n\n return {\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n ignore: 'pid,hostname,module',\n messageFormat: '{if module}{module} - {end}{msg}',\n },\n },\n }\n}\n\nconst applyDefaultOptions = (options?: LoggerOptions): LoggerOptions => {\n const defaultOptions: LoggerOptions = {\n browser: {\n asObject: true,\n },\n // JOHN need to find a better way to include\n // ...getPrettyTransport(),\n }\n\n return Objects.merge(defaultOptions, options)\n}\n\nconst createProxyHandler = (getLogger: () => PinoLogger): ProxyHandler<PinoLogger> => {\n let cachedLogger: PinoLogger | null = null\n let cachedVersion = GlobalLoggerState.getValue().version\n\n const getOrCreateLogger = () => {\n if (cachedVersion !== GlobalLoggerState.getValue().version) {\n cachedLogger = null\n cachedVersion = GlobalLoggerState.getValue().version\n }\n\n if (Objects.isNil(cachedLogger)) {\n cachedLogger = getLogger()\n }\n\n return cachedLogger\n }\n\n return {\n get(_: any, prop: string): any {\n if (prop === 'child') {\n return (bindings: PinoBindings) => {\n return new Proxy(\n {} as PinoLogger,\n createProxyHandler(() => getOrCreateLogger().child(bindings))\n )\n }\n }\n\n return (getOrCreateLogger() as any)[prop]\n },\n }\n}\n\nconst GlobalLoggerState = createGlobalVariable<{\n version: number\n logger: pino.Logger\n}>('GlobalLoggerState', () => ({\n version: 0,\n logger: pino(applyDefaultOptions({ level: 'info' })),\n}))\n\nconst LoggerProxy: PinoLogger = new Proxy(\n {} as PinoLogger,\n createProxyHandler(() => GlobalLoggerState.getValue().logger)\n)\n\nconst Primary: Logger = new Logger(LoggerProxy)\n\nexport const initialize = (initialOptions?: LoggerOptions): void => {\n const options = applyDefaultOptions(initialOptions)\n GlobalLoggerState.setValue({ version: GlobalLoggerState.getValue().version + 1, logger: pino(options) })\n}\n\nexport const child = (module: string): Logger => {\n return new Logger(LoggerProxy.child({ module }))\n}\n\nexport const trace = Primary.trace\nexport const debug = Primary.debug\nexport const info = Primary.info\nexport const warn = Primary.warn\nexport const error = Primary.error\nexport const fatal = Primary.fatal\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/logger.ts"],"sourcesContent":["import pino from 'pino'\nimport { Lazy, Objects } from '@bessemer/cornerstone'\nimport { createGlobalVariable } from '@bessemer/cornerstone/global-variable'\nimport { LazyValue } from '@bessemer/cornerstone/lazy'\nimport { UnknownRecord } from 'type-fest'\n\ntype PinoLogger = pino.Logger\ntype PinoBindings = pino.Bindings\nexport type LoggerOptions = pino.LoggerOptions\n\ntype LogOptions = { error?: unknown; context?: UnknownRecord }\ntype LogFunction = (message: LazyValue<string>, options?: LogOptions) => void\n\nexport class Logger {\n constructor(private readonly logger: PinoLogger) {}\n\n trace: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('trace') ?? true) {\n this.logger.trace({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n\n debug: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('debug') ?? true) {\n this.logger.debug({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n\n info: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('info') ?? true) {\n this.logger.info({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n\n warn: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('warn') ?? true) {\n this.logger.warn({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n\n error: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('error') ?? true) {\n this.logger.error({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n\n fatal: LogFunction = (message: LazyValue<string>, options?: LogOptions): void => {\n if (this.logger.isLevelEnabled?.('fatal') ?? true) {\n this.logger.fatal({ err: options?.error, context: options?.context }, Lazy.evaluate(message))\n }\n }\n}\n\nconst getPrettyTransport = (): LoggerOptions => {\n if (process.env.NODE_ENV === 'production' || typeof window !== 'undefined') {\n return {}\n }\n\n return {\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n ignore: 'pid,hostname,module',\n messageFormat: '{if module}{module} - {end}{msg}',\n },\n },\n }\n}\n\nconst applyDefaultOptions = (options?: LoggerOptions): LoggerOptions => {\n const defaultOptions: LoggerOptions = {\n browser: {\n asObject: true,\n },\n // JOHN need to find a better way to include\n // ...getPrettyTransport(),\n }\n\n return Objects.deepMerge(defaultOptions, options)\n}\n\nconst createProxyHandler = (getLogger: () => PinoLogger): ProxyHandler<PinoLogger> => {\n let cachedLogger: PinoLogger | null = null\n let cachedVersion = GlobalLoggerState.getValue().version\n\n const getOrCreateLogger = () => {\n if (cachedVersion !== GlobalLoggerState.getValue().version) {\n cachedLogger = null\n cachedVersion = GlobalLoggerState.getValue().version\n }\n\n if (Objects.isNil(cachedLogger)) {\n cachedLogger = getLogger()\n }\n\n return cachedLogger\n }\n\n return {\n get(_: any, prop: string): any {\n if (prop === 'child') {\n return (bindings: PinoBindings) => {\n return new Proxy(\n {} as PinoLogger,\n createProxyHandler(() => getOrCreateLogger().child(bindings))\n )\n }\n }\n\n return (getOrCreateLogger() as any)[prop]\n },\n }\n}\n\nconst GlobalLoggerState = createGlobalVariable<{\n version: number\n logger: pino.Logger\n}>('GlobalLoggerState', () => ({\n version: 0,\n logger: pino(applyDefaultOptions({ level: 'info' })),\n}))\n\nconst LoggerProxy: PinoLogger = new Proxy(\n {} as PinoLogger,\n createProxyHandler(() => GlobalLoggerState.getValue().logger)\n)\n\nconst Primary: Logger = new Logger(LoggerProxy)\n\nexport const initialize = (initialOptions?: LoggerOptions): void => {\n const options = applyDefaultOptions(initialOptions)\n GlobalLoggerState.setValue({ version: GlobalLoggerState.getValue().version + 1, logger: pino(options) })\n}\n\nexport const child = (module: string): Logger => {\n return new Logger(LoggerProxy.child({ module }))\n}\n\nexport const trace = Primary.trace\nexport const debug = Primary.debug\nexport const info = Primary.info\nexport const warn = Primary.warn\nexport const error = Primary.error\nexport const fatal = Primary.fatal\n"],"mappings":"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","names":[]}
package/dist/object.d.ts CHANGED
@@ -35,13 +35,13 @@ export declare const mapValues: {
35
35
  };
36
36
  export declare const clone: <T>(value: T) => T;
37
37
  export declare const cloneDeep: <T>(value: T) => T;
38
- export declare const mergeAll: <T>(objects: Array<T>) => T;
39
- export declare function merge<TObject, TSource>(object: TObject, source: TSource): TObject & TSource;
40
- export declare function merge<TObject, TSource1, TSource2>(object: TObject, source1: TSource1, source2: TSource2): TObject & TSource1 & TSource2;
41
- export declare function merge<TObject, TSource1, TSource2, TSource3>(object: TObject, source1: TSource1, source2: TSource2, source3: TSource3): TObject & TSource1 & TSource2 & TSource3;
42
- export declare function merge<TObject, TSource1, TSource2, TSource3, TSource4>(object: TObject, source1: TSource1, source2: TSource2, source3: TSource3, source4: TSource4): TObject & TSource1 & TSource2 & TSource3 & TSource4;
43
- export declare function mergeInto<Source1, Source2>(source: Source1, values: Source2): asserts source is Source1 & Source2;
44
- export declare const mergeWith: typeof unsafeMergeWith;
38
+ export declare function deepMerge<TObject, TSource>(object: TObject, source: TSource): TObject & TSource;
39
+ export declare function deepMerge<TObject, TSource1, TSource2>(object: TObject, source1: TSource1, source2: TSource2): TObject & TSource1 & TSource2;
40
+ export declare function deepMerge<TObject, TSource1, TSource2, TSource3>(object: TObject, source1: TSource1, source2: TSource2, source3: TSource3): TObject & TSource1 & TSource2 & TSource3;
41
+ export declare function deepMerge<TObject, TSource1, TSource2, TSource3, TSource4>(object: TObject, source1: TSource1, source2: TSource2, source3: TSource3, source4: TSource4): TObject & TSource1 & TSource2 & TSource3 & TSource4;
42
+ export declare const deepMergeAll: <T>(objects: Array<T>) => T;
43
+ export declare function deepMergeInto<Source1, Source2>(source: Source1, values: Source2): asserts source is Source1 & Source2;
44
+ export declare const deepMergeWith: typeof unsafeMergeWith;
45
45
  export type ObjectDiffResult = {
46
46
  elementsUpdated: Record<string, {
47
47
  originalValue: unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"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"}
package/dist/object.js CHANGED
@@ -32,16 +32,16 @@ var invert = _invert;
32
32
  var mapValues = _mapValues;
33
33
  var clone = _clone;
34
34
  var cloneDeep = _cloneDeep;
35
- var mergeAll = (objects) => {
36
- return objects.reduce((x, y) => merge(x, y));
37
- };
38
- function merge(object, ...otherArgs) {
35
+ function deepMerge(object, ...otherArgs) {
39
36
  return unsafeMerge({}, object, ...otherArgs);
40
37
  }
41
- function mergeInto(source, values) {
38
+ var deepMergeAll = (objects) => {
39
+ return objects.reduce((x, y) => deepMerge(x, y));
40
+ };
41
+ function deepMergeInto(source, values) {
42
42
  unsafeMerge(source, values);
43
43
  }
44
- var mergeWith = (...args) => {
44
+ var deepMergeWith = (...args) => {
45
45
  const clone2 = cloneDeep(args[0]);
46
46
  return unsafeMergeWith.apply(null, [clone2, ...args.slice(1)]);
47
47
  };
@@ -155,6 +155,10 @@ export {
155
155
  cloneDeep,
156
156
  coerceNil,
157
157
  deepEqual,
158
+ deepMerge,
159
+ deepMergeAll,
160
+ deepMergeInto,
161
+ deepMergeWith,
158
162
  diffShallow,
159
163
  fieldsPresent,
160
164
  getAttribute,
@@ -170,10 +174,6 @@ export {
170
174
  isUndefined,
171
175
  isValidKey,
172
176
  mapValues,
173
- merge,
174
- mergeAll,
175
- mergeInto,
176
- mergeWith,
177
177
  parsePath,
178
178
  path,
179
179
  update
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/object.ts"],"sourcesContent":["import {\n clone as _clone,\n cloneDeep as _cloneDeep,\n invert as _invert,\n isBoolean as _isBoolean,\n isDate,\n isEmpty as _isEmpty,\n isEqual as _isEqual,\n isNil as _isNil,\n isNumber,\n isPlainObject,\n isString,\n isUndefined as _isUndefined,\n mapValues as _mapValues,\n merge as unsafeMerge,\n mergeWith as unsafeMergeWith,\n} from 'lodash-es'\nimport { produce } from 'immer'\nimport { BasicType, Dictionary, NominalType } from '@bessemer/cornerstone/types'\nimport { Primitive, UnknownRecord } from 'type-fest'\n\nexport const update: typeof produce = produce\n\nexport const isUndefined = _isUndefined\nexport const isNil = _isNil\nexport const isPresent = <T>(value: T): value is NonNullable<T> => {\n return !isNil(value)\n}\nexport const isObject = (value?: any): value is Dictionary<unknown> => {\n return isPlainObject(value)\n}\nexport const isEmpty = _isEmpty\nexport const deepEqual = _isEqual\nexport const invert = _invert\nexport const mapValues = _mapValues\n\nexport const clone = _clone\nexport const cloneDeep = _cloneDeep\n\nexport const mergeAll = <T>(objects: Array<T>): T => {\n return objects.reduce((x, y) => merge(x, y))\n}\n\nexport function merge<TObject, TSource>(object: TObject, source: TSource): TObject & TSource\nexport function merge<TObject, TSource1, TSource2>(object: TObject, source1: TSource1, source2: TSource2): TObject & TSource1 & TSource2\nexport function merge<TObject, TSource1, TSource2, TSource3>(\n object: TObject,\n source1: TSource1,\n source2: TSource2,\n source3: TSource3\n): TObject & TSource1 & TSource2 & TSource3\nexport function merge<TObject, TSource1, TSource2, TSource3, TSource4>(\n object: TObject,\n source1: TSource1,\n source2: TSource2,\n source3: TSource3,\n source4: TSource4\n): TObject & TSource1 & TSource2 & TSource3 & TSource4\nexport function merge(object: any, ...otherArgs: any[]): any {\n return unsafeMerge({}, object, ...otherArgs)\n}\n\nexport function mergeInto<Source1, Source2>(source: Source1, values: Source2): asserts source is Source1 & Source2 {\n unsafeMerge(source, values)\n}\n\nexport const mergeWith: typeof unsafeMergeWith = (...args: Array<any>) => {\n const clone = cloneDeep(args[0])\n return unsafeMergeWith.apply(null, [clone, ...args.slice(1)])\n}\n\nexport type ObjectDiffResult = {\n elementsUpdated: Record<string, { originalValue: unknown; updatedValue: unknown }>\n elementsAdded: UnknownRecord\n elementsRemoved: UnknownRecord\n}\n\nexport function diffShallow(original: UnknownRecord, updated: UnknownRecord): ObjectDiffResult {\n const result: ObjectDiffResult = {\n elementsUpdated: {},\n elementsAdded: {},\n elementsRemoved: {},\n }\n\n for (const [key, originalValue] of Object.entries(original)) {\n const updatedValue = updated[key]\n if (updatedValue === undefined) {\n result.elementsRemoved[key] = originalValue\n } else if (!deepEqual(originalValue, updatedValue)) {\n result.elementsUpdated[key] = { originalValue: originalValue, updatedValue: updatedValue }\n }\n }\n\n for (const [key, updatedValue] of Object.entries(updated)) {\n const originalValue = original[key]\n if (originalValue === undefined) {\n result.elementsAdded[key] = updatedValue\n }\n }\n return result\n}\n\nexport const isValidKey = (field: PropertyKey, obj: object): field is keyof typeof obj => {\n return field in obj\n}\n\n/** Determines if the list of fields are present on the object (not null or undefined), with type inference */\nexport function fieldsPresent<T extends object, K extends keyof T>(\n object: T,\n fields: Array<K>\n): object is Exclude<T, K> & Required<{ [P in K]: NonNullable<T[P]> }> {\n return fields.every((field) => isPresent(object[field]))\n}\n\nexport type ObjectPath = {\n path: Array<string | number>\n}\n\nexport const path = (path: Array<string | number>): ObjectPath => {\n return { path }\n}\n\nexport const parsePath = (path: string): ObjectPath => {\n const result: Array<string | number> = []\n const regex = /([^.\\[\\]]+)|\\[(\\d+)]/g\n\n let match: RegExpExecArray | null\n while ((match = regex.exec(path)) !== null) {\n if (match[1] !== undefined) {\n result.push(match[1])\n } else if (match[2] !== undefined) {\n result.push(Number(match[2]))\n }\n }\n\n return { path: result }\n}\n\nconst pathify = (path: ObjectPath | string): ObjectPath => {\n if (isString(path)) {\n return parsePath(path)\n }\n\n return path as ObjectPath\n}\n\nexport const getPathValue = (object: UnknownRecord, initialPath: ObjectPath | string): unknown | undefined => {\n const path = pathify(initialPath)\n let current: any = object\n\n for (const key of path.path) {\n if (isPrimitive(current)) {\n return undefined\n }\n\n current = current[key]\n }\n\n return current\n}\n\nexport const applyPathValue = (object: UnknownRecord, initialPath: ObjectPath | string, value: unknown): UnknownRecord | undefined => {\n const path = pathify(initialPath)\n\n const newObject = update(object, (draft) => {\n let current: any = draft\n\n for (let i = 0; i < path.path.length; i++) {\n const key = path.path[i]!\n const isLastKey = i === path.path.length - 1\n\n if (isPrimitive(current)) {\n return\n }\n\n if (Array.isArray(current)) {\n if (!isNumber(key)) {\n return\n }\n\n if (key >= current.length) {\n return\n }\n }\n\n if (isLastKey) {\n current[key] = value\n } else {\n current = current[key]\n }\n }\n })\n\n if (newObject === object) {\n return undefined\n }\n\n return newObject\n}\n\nexport const isPrimitive = (value: any): value is Primitive => {\n return value === null || (typeof value !== 'object' && typeof value !== 'function')\n}\n\nexport const isBasic = (value: any): value is BasicType => {\n return isNumber(value) || isString(value) || isDate(value) || isBoolean(value)\n}\n\nexport const isBoolean = _isBoolean\n\ntype TransformFunction = (value: any, path: (string | number)[], key: string | number, parent: any) => any\n\nconst walk = (value: any, transform: TransformFunction, path: (string | number)[] = []): any => {\n if (isNil(value) || isPrimitive(value)) {\n return value\n }\n\n if (Array.isArray(value)) {\n return value.map((value, index) => {\n const currentPath = [...path, index]\n return walk(transform(value, currentPath, index, value), transform, currentPath)\n })\n }\n\n const result: any = {}\n for (const key in value) {\n if (Object.prototype.hasOwnProperty.call(value, key)) {\n const currentPath = [...path, key]\n const transformedValue = transform(value[key], currentPath, key, value)\n result[key] = walk(transformedValue, transform, currentPath)\n }\n }\n\n return result\n}\n\nexport type RecordAttribute<Type = unknown, Class extends string = 'RecordAttribute'> = NominalType<string, [Type, Class]>\ntype RecordAttributeType<Attribute> = Attribute extends RecordAttribute<infer Type, string> ? Type : never\n\nexport const getAttribute = <T extends RecordAttribute<unknown, string>>(record: UnknownRecord, attribute: T): RecordAttributeType<T> | undefined => {\n return record[attribute] as RecordAttributeType<T> | undefined\n}\n\nexport const coerceNil = <T>(value: T | null | undefined): T | undefined => {\n return isNil(value) ? undefined : value\n}\n"],"mappings":";AAAA;AAAA,EACE,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU;AAAA,EACV,aAAa;AAAA,EACb;AAAA,EACA,WAAW;AAAA,EACX,WAAW;AAAA,EACX,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,aAAa;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,OACR;AACP,SAAS,eAAe;AAIjB,IAAM,SAAyB;AAE/B,IAAM,cAAc;AACpB,IAAM,QAAQ;AACd,IAAM,YAAY,CAAI,UAAsC;AACjE,SAAO,CAAC,MAAM,KAAK;AACrB;AACO,IAAM,WAAW,CAAC,UAA8C;AACrE,SAAO,cAAc,KAAK;AAC5B;AACO,IAAM,UAAU;AAChB,IAAM,YAAY;AAClB,IAAM,SAAS;AACf,IAAM,YAAY;AAElB,IAAM,QAAQ;AACd,IAAM,YAAY;AAElB,IAAM,WAAW,CAAI,YAAyB;AACnD,SAAO,QAAQ,OAAO,CAAC,GAAG,MAAM,MAAM,GAAG,CAAC,CAAC;AAC7C;AAiBO,SAAS,MAAM,WAAgB,WAAuB;AAC3D,SAAO,YAAY,CAAC,GAAG,QAAQ,GAAG,SAAS;AAC7C;AAEO,SAAS,UAA4B,QAAiB,QAAsD;AACjH,cAAY,QAAQ,MAAM;AAC5B;AAEO,IAAM,YAAoC,IAAI,SAAqB;AACxE,QAAMA,SAAQ,UAAU,KAAK,CAAC,CAAC;AAC/B,SAAO,gBAAgB,MAAM,MAAM,CAACA,QAAO,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC;AAC9D;AAQO,SAAS,YAAY,UAAyB,SAA0C;AAC7F,QAAM,SAA2B;AAAA,IAC/B,iBAAiB,CAAC;AAAA,IAClB,eAAe,CAAC;AAAA,IAChB,iBAAiB,CAAC;AAAA,EACpB;AAEA,aAAW,CAAC,KAAK,aAAa,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAC3D,UAAM,eAAe,QAAQ,GAAG;AAChC,QAAI,iBAAiB,QAAW;AAC9B,aAAO,gBAAgB,GAAG,IAAI;AAAA,IAChC,WAAW,CAAC,UAAU,eAAe,YAAY,GAAG;AAClD,aAAO,gBAAgB,GAAG,IAAI,EAAE,eAA8B,aAA2B;AAAA,IAC3F;AAAA,EACF;AAEA,aAAW,CAAC,KAAK,YAAY,KAAK,OAAO,QAAQ,OAAO,GAAG;AACzD,UAAM,gBAAgB,SAAS,GAAG;AAClC,QAAI,kBAAkB,QAAW;AAC/B,aAAO,cAAc,GAAG,IAAI;AAAA,IAC9B;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,aAAa,CAAC,OAAoB,QAA2C;AACxF,SAAO,SAAS;AAClB;AAGO,SAAS,cACd,QACA,QACqE;AACrE,SAAO,OAAO,MAAM,CAAC,UAAU,UAAU,OAAO,KAAK,CAAC,CAAC;AACzD;AAMO,IAAM,OAAO,CAACC,UAA6C;AAChE,SAAO,EAAE,MAAAA,MAAK;AAChB;AAEO,IAAM,YAAY,CAACA,UAA6B;AACrD,QAAM,SAAiC,CAAC;AACxC,QAAM,QAAQ;AAEd,MAAI;AACJ,UAAQ,QAAQ,MAAM,KAAKA,KAAI,OAAO,MAAM;AAC1C,QAAI,MAAM,CAAC,MAAM,QAAW;AAC1B,aAAO,KAAK,MAAM,CAAC,CAAC;AAAA,IACtB,WAAW,MAAM,CAAC,MAAM,QAAW;AACjC,aAAO,KAAK,OAAO,MAAM,CAAC,CAAC,CAAC;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,OAAO;AACxB;AAEA,IAAM,UAAU,CAACA,UAA0C;AACzD,MAAI,SAASA,KAAI,GAAG;AAClB,WAAO,UAAUA,KAAI;AAAA,EACvB;AAEA,SAAOA;AACT;AAEO,IAAM,eAAe,CAAC,QAAuB,gBAA0D;AAC5G,QAAMA,QAAO,QAAQ,WAAW;AAChC,MAAI,UAAe;AAEnB,aAAW,OAAOA,MAAK,MAAM;AAC3B,QAAI,YAAY,OAAO,GAAG;AACxB,aAAO;AAAA,IACT;AAEA,cAAU,QAAQ,GAAG;AAAA,EACvB;AAEA,SAAO;AACT;AAEO,IAAM,iBAAiB,CAAC,QAAuB,aAAkC,UAA8C;AACpI,QAAMA,QAAO,QAAQ,WAAW;AAEhC,QAAM,YAAY,OAAO,QAAQ,CAAC,UAAU;AAC1C,QAAI,UAAe;AAEnB,aAAS,IAAI,GAAG,IAAIA,MAAK,KAAK,QAAQ,KAAK;AACzC,YAAM,MAAMA,MAAK,KAAK,CAAC;AACvB,YAAM,YAAY,MAAMA,MAAK,KAAK,SAAS;AAE3C,UAAI,YAAY,OAAO,GAAG;AACxB;AAAA,MACF;AAEA,UAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,YAAI,CAAC,SAAS,GAAG,GAAG;AAClB;AAAA,QACF;AAEA,YAAI,OAAO,QAAQ,QAAQ;AACzB;AAAA,QACF;AAAA,MACF;AAEA,UAAI,WAAW;AACb,gBAAQ,GAAG,IAAI;AAAA,MACjB,OAAO;AACL,kBAAU,QAAQ,GAAG;AAAA,MACvB;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,cAAc,QAAQ;AACxB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,IAAM,cAAc,CAAC,UAAmC;AAC7D,SAAO,UAAU,QAAS,OAAO,UAAU,YAAY,OAAO,UAAU;AAC1E;AAEO,IAAM,UAAU,CAAC,UAAmC;AACzD,SAAO,SAAS,KAAK,KAAK,SAAS,KAAK,KAAK,OAAO,KAAK,KAAK,UAAU,KAAK;AAC/E;AAEO,IAAM,YAAY;AA+BlB,IAAM,eAAe,CAA6C,QAAuB,cAAqD;AACnJ,SAAO,OAAO,SAAS;AACzB;AAEO,IAAM,YAAY,CAAI,UAA+C;AAC1E,SAAO,MAAM,KAAK,IAAI,SAAY;AACpC;","names":["clone","path"]}
1
+ {"version":3,"sources":["../src/object.ts"],"sourcesContent":["import {\n clone as _clone,\n cloneDeep as _cloneDeep,\n invert as _invert,\n isBoolean as _isBoolean,\n isDate,\n isEmpty as _isEmpty,\n isEqual as _isEqual,\n isNil as _isNil,\n isNumber,\n isPlainObject,\n isString,\n isUndefined as _isUndefined,\n mapValues as _mapValues,\n merge as unsafeMerge,\n mergeWith as unsafeMergeWith,\n} from 'lodash-es'\nimport { produce } from 'immer'\nimport { BasicType, Dictionary, NominalType } from '@bessemer/cornerstone/types'\nimport { Primitive, UnknownRecord } from 'type-fest'\n\nexport const update: typeof produce = produce\n\nexport const isUndefined = _isUndefined\nexport const isNil = _isNil\nexport const isPresent = <T>(value: T): value is NonNullable<T> => {\n return !isNil(value)\n}\nexport const isObject = (value?: any): value is Dictionary<unknown> => {\n return isPlainObject(value)\n}\nexport const isEmpty = _isEmpty\nexport const deepEqual = _isEqual\nexport const invert = _invert\nexport const mapValues = _mapValues\n\nexport const clone = _clone\nexport const cloneDeep = _cloneDeep\n\nexport function deepMerge<TObject, TSource>(object: TObject, source: TSource): TObject & TSource\nexport function deepMerge<TObject, TSource1, TSource2>(object: TObject, source1: TSource1, source2: TSource2): TObject & TSource1 & TSource2\nexport function deepMerge<TObject, TSource1, TSource2, TSource3>(\n object: TObject,\n source1: TSource1,\n source2: TSource2,\n source3: TSource3\n): TObject & TSource1 & TSource2 & TSource3\nexport function deepMerge<TObject, TSource1, TSource2, TSource3, TSource4>(\n object: TObject,\n source1: TSource1,\n source2: TSource2,\n source3: TSource3,\n source4: TSource4\n): TObject & TSource1 & TSource2 & TSource3 & TSource4\nexport function deepMerge(object: any, ...otherArgs: any[]): any {\n return unsafeMerge({}, object, ...otherArgs)\n}\n\nexport const deepMergeAll = <T>(objects: Array<T>): T => {\n return objects.reduce((x, y) => deepMerge(x, y))\n}\n\nexport function deepMergeInto<Source1, Source2>(source: Source1, values: Source2): asserts source is Source1 & Source2 {\n unsafeMerge(source, values)\n}\n\nexport const deepMergeWith: typeof unsafeMergeWith = (...args: Array<any>) => {\n const clone = cloneDeep(args[0])\n return unsafeMergeWith.apply(null, [clone, ...args.slice(1)])\n}\n\nexport type ObjectDiffResult = {\n elementsUpdated: Record<string, { originalValue: unknown; updatedValue: unknown }>\n elementsAdded: UnknownRecord\n elementsRemoved: UnknownRecord\n}\n\nexport function diffShallow(original: UnknownRecord, updated: UnknownRecord): ObjectDiffResult {\n const result: ObjectDiffResult = {\n elementsUpdated: {},\n elementsAdded: {},\n elementsRemoved: {},\n }\n\n for (const [key, originalValue] of Object.entries(original)) {\n const updatedValue = updated[key]\n if (updatedValue === undefined) {\n result.elementsRemoved[key] = originalValue\n } else if (!deepEqual(originalValue, updatedValue)) {\n result.elementsUpdated[key] = { originalValue: originalValue, updatedValue: updatedValue }\n }\n }\n\n for (const [key, updatedValue] of Object.entries(updated)) {\n const originalValue = original[key]\n if (originalValue === undefined) {\n result.elementsAdded[key] = updatedValue\n }\n }\n return result\n}\n\nexport const isValidKey = (field: PropertyKey, obj: object): field is keyof typeof obj => {\n return field in obj\n}\n\n/** Determines if the list of fields are present on the object (not null or undefined), with type inference */\nexport function fieldsPresent<T extends object, K extends keyof T>(\n object: T,\n fields: Array<K>\n): object is Exclude<T, K> & Required<{ [P in K]: NonNullable<T[P]> }> {\n return fields.every((field) => isPresent(object[field]))\n}\n\nexport type ObjectPath = {\n path: Array<string | number>\n}\n\nexport const path = (path: Array<string | number>): ObjectPath => {\n return { path }\n}\n\nexport const parsePath = (path: string): ObjectPath => {\n const result: Array<string | number> = []\n const regex = /([^.\\[\\]]+)|\\[(\\d+)]/g\n\n let match: RegExpExecArray | null\n while ((match = regex.exec(path)) !== null) {\n if (match[1] !== undefined) {\n result.push(match[1])\n } else if (match[2] !== undefined) {\n result.push(Number(match[2]))\n }\n }\n\n return { path: result }\n}\n\nconst pathify = (path: ObjectPath | string): ObjectPath => {\n if (isString(path)) {\n return parsePath(path)\n }\n\n return path as ObjectPath\n}\n\nexport const getPathValue = (object: UnknownRecord, initialPath: ObjectPath | string): unknown | undefined => {\n const path = pathify(initialPath)\n let current: any = object\n\n for (const key of path.path) {\n if (isPrimitive(current)) {\n return undefined\n }\n\n current = current[key]\n }\n\n return current\n}\n\nexport const applyPathValue = (object: UnknownRecord, initialPath: ObjectPath | string, value: unknown): UnknownRecord | undefined => {\n const path = pathify(initialPath)\n\n const newObject = update(object, (draft) => {\n let current: any = draft\n\n for (let i = 0; i < path.path.length; i++) {\n const key = path.path[i]!\n const isLastKey = i === path.path.length - 1\n\n if (isPrimitive(current)) {\n return\n }\n\n if (Array.isArray(current)) {\n if (!isNumber(key)) {\n return\n }\n\n if (key >= current.length) {\n return\n }\n }\n\n if (isLastKey) {\n current[key] = value\n } else {\n current = current[key]\n }\n }\n })\n\n if (newObject === object) {\n return undefined\n }\n\n return newObject\n}\n\nexport const isPrimitive = (value: any): value is Primitive => {\n return value === null || (typeof value !== 'object' && typeof value !== 'function')\n}\n\nexport const isBasic = (value: any): value is BasicType => {\n return isNumber(value) || isString(value) || isDate(value) || isBoolean(value)\n}\n\nexport const isBoolean = _isBoolean\n\ntype TransformFunction = (value: any, path: (string | number)[], key: string | number, parent: any) => any\n\nconst walk = (value: any, transform: TransformFunction, path: (string | number)[] = []): any => {\n if (isNil(value) || isPrimitive(value)) {\n return value\n }\n\n if (Array.isArray(value)) {\n return value.map((value, index) => {\n const currentPath = [...path, index]\n return walk(transform(value, currentPath, index, value), transform, currentPath)\n })\n }\n\n const result: any = {}\n for (const key in value) {\n if (Object.prototype.hasOwnProperty.call(value, key)) {\n const currentPath = [...path, key]\n const transformedValue = transform(value[key], currentPath, key, value)\n result[key] = walk(transformedValue, transform, currentPath)\n }\n }\n\n return result\n}\n\nexport type RecordAttribute<Type = unknown, Class extends string = 'RecordAttribute'> = NominalType<string, [Type, Class]>\ntype RecordAttributeType<Attribute> = Attribute extends RecordAttribute<infer Type, string> ? Type : never\n\nexport const getAttribute = <T extends RecordAttribute<unknown, string>>(record: UnknownRecord, attribute: T): RecordAttributeType<T> | undefined => {\n return record[attribute] as RecordAttributeType<T> | undefined\n}\n\nexport const coerceNil = <T>(value: T | null | undefined): T | undefined => {\n return isNil(value) ? undefined : value\n}\n"],"mappings":"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","names":["clone","path"]}
package/dist/patch.js CHANGED
@@ -63,7 +63,7 @@ var resolve = (value, patches, evaluate) => {
63
63
  return resolveWithDetails(value, patches, evaluate).value;
64
64
  };
65
65
  var applyPatch = (value, patch2, evaluate) => {
66
- return Objects.mergeWith(value, patch2, (value2, patch3) => {
66
+ return Objects.deepMergeWith(value, patch2, (value2, patch3) => {
67
67
  if (Objects.isNil(patch3)) {
68
68
  return value2;
69
69
  }
package/dist/patch.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/patch.ts"],"sourcesContent":["import {\n ArrayExpressions,\n EvaluateExpression,\n Expression,\n Expressions,\n NumericExpressions,\n ReducingExpression,\n} from '@bessemer/cornerstone/expression'\nimport { Objects, Preconditions } from '@bessemer/cornerstone'\nimport { UnknownRecord } from 'type-fest'\n\nexport enum PatchType {\n Set = 'Set',\n Apply = 'Apply',\n Patch = 'Patch',\n}\n\nexport type SetPatch<T> = {\n _PatchType: PatchType.Set\n value: Expression<T>\n}\n\nexport type ApplyPatch<T> = {\n _PatchType: PatchType.Apply\n value: Expression<T>\n reducer: ReducingExpression<T, T>\n}\n\nexport type PatchPatch<T> = {\n _PatchType: PatchType.Patch\n patch: Patchable<T>\n}\n\nexport type Patch<T> = SetPatch<T> | ApplyPatch<T> | PatchPatch<T>\n\nexport type PatchValue<T> = {\n value: T\n patch: Patch<T>\n}\n\nexport type Patchable<T> = {\n [P in keyof T]?: T[P] extends Array<infer U>\n ? Patch<U[]> | Patchable<U[]>\n : T[P] extends object | undefined\n ? Patch<T[P]> | Patchable<T[P]>\n : Patch<T[P]> | T[P]\n}\n\nexport const set = <T>(value: Expression<T>): Patch<T> => {\n return {\n _PatchType: PatchType.Set,\n value: value as any,\n }\n}\n\nexport const apply = <T>(value: Expression<T>, reducer: ReducingExpression<T, T>): Patch<T> => {\n return {\n _PatchType: PatchType.Apply,\n value,\n reducer,\n }\n}\n\nexport const patch = <T extends UnknownRecord, N extends Patchable<T> = Patchable<T>>(patch: N): Patch<T> => {\n return {\n _PatchType: PatchType.Patch,\n patch,\n }\n}\n\nexport const sum = (value: Expression<number>): Patch<number> => {\n return apply(value, Expressions.reference(NumericExpressions.SumExpression))\n}\n\nexport const multiply = (value: Expression<number>): Patch<number> => {\n return apply(value, Expressions.reference(NumericExpressions.MultiplyExpression))\n}\n\nexport const concatenate = <T extends Array<Expression<unknown>>>(value: Expression<T>): Patch<T> => {\n return apply(value, Expressions.reference(ArrayExpressions.ConcatenateExpression)) as Patch<T>\n}\n\nexport type ResolvePatchesResult<T> = {\n value: T\n patchValues: Array<PatchValue<T>>\n}\n\nexport const resolveWithDetails = <T>(value: T, patches: Array<Patch<T>>, evaluate: EvaluateExpression): ResolvePatchesResult<T> => {\n let currentValue: T = value\n\n const patchValues = patches.map((patch) => {\n switch (patch._PatchType) {\n case PatchType.Set:\n currentValue = evaluate(patch.value)\n break\n case PatchType.Apply:\n currentValue = evaluate(Expressions.dereference(patch.reducer, [currentValue, patch.value]))\n break\n case PatchType.Patch:\n currentValue = applyPatch(currentValue, patch.patch, evaluate)\n break\n default:\n Preconditions.isUnreachable(() => `Unrecognized PatchType for value: ${JSON.stringify(it)}`)\n }\n\n return { value: currentValue, patch }\n })\n\n return { value: currentValue, patchValues }\n}\n\nexport const resolve = <T>(value: T, patches: Array<Patch<T>>, evaluate: EvaluateExpression): T => {\n return resolveWithDetails(value, patches, evaluate).value\n}\n\nconst applyPatch = <T>(value: T, patch: Patchable<T>, evaluate: EvaluateExpression): T => {\n return Objects.mergeWith(value, patch, (value, patch) => {\n if (Objects.isNil(patch)) {\n return value\n }\n\n if (!Objects.isObject(patch) || !('_PatchType' in patch)) {\n return undefined\n }\n\n return evaluate(resolve(value, [patch as Patch<T>], evaluate))\n })\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,SAAS,qBAAqB;AAGhC,IAAK,YAAL,kBAAKA,eAAL;AACL,EAAAA,WAAA,SAAM;AACN,EAAAA,WAAA,WAAQ;AACR,EAAAA,WAAA,WAAQ;AAHE,SAAAA;AAAA,GAAA;AAqCL,IAAM,MAAM,CAAI,UAAmC;AACxD,SAAO;AAAA,IACL,YAAY;AAAA,IACZ;AAAA,EACF;AACF;AAEO,IAAM,QAAQ,CAAI,OAAsB,YAAgD;AAC7F,SAAO;AAAA,IACL,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AAEO,IAAM,QAAQ,CAAiEC,WAAuB;AAC3G,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,OAAAA;AAAA,EACF;AACF;AAEO,IAAM,MAAM,CAAC,UAA6C;AAC/D,SAAO,MAAM,OAAO,YAAY,UAAU,mBAAmB,aAAa,CAAC;AAC7E;AAEO,IAAM,WAAW,CAAC,UAA6C;AACpE,SAAO,MAAM,OAAO,YAAY,UAAU,mBAAmB,kBAAkB,CAAC;AAClF;AAEO,IAAM,cAAc,CAAuC,UAAmC;AACnG,SAAO,MAAM,OAAO,YAAY,UAAU,iBAAiB,qBAAqB,CAAC;AACnF;AAOO,IAAM,qBAAqB,CAAI,OAAU,SAA0B,aAA0D;AAClI,MAAI,eAAkB;AAEtB,QAAM,cAAc,QAAQ,IAAI,CAACA,WAAU;AACzC,YAAQA,OAAM,YAAY;AAAA,MACxB,KAAK;AACH,uBAAe,SAASA,OAAM,KAAK;AACnC;AAAA,MACF,KAAK;AACH,uBAAe,SAAS,YAAY,YAAYA,OAAM,SAAS,CAAC,cAAcA,OAAM,KAAK,CAAC,CAAC;AAC3F;AAAA,MACF,KAAK;AACH,uBAAe,WAAW,cAAcA,OAAM,OAAO,QAAQ;AAC7D;AAAA,MACF;AACE,sBAAc,cAAc,MAAM,qCAAqC,KAAK,UAAU,EAAE,CAAC,EAAE;AAAA,IAC/F;AAEA,WAAO,EAAE,OAAO,cAAc,OAAAA,OAAM;AAAA,EACtC,CAAC;AAED,SAAO,EAAE,OAAO,cAAc,YAAY;AAC5C;AAEO,IAAM,UAAU,CAAI,OAAU,SAA0B,aAAoC;AACjG,SAAO,mBAAmB,OAAO,SAAS,QAAQ,EAAE;AACtD;AAEA,IAAM,aAAa,CAAI,OAAUA,QAAqB,aAAoC;AACxF,SAAO,QAAQ,UAAU,OAAOA,QAAO,CAACC,QAAOD,WAAU;AACvD,QAAI,QAAQ,MAAMA,MAAK,GAAG;AACxB,aAAOC;AAAA,IACT;AAEA,QAAI,CAAC,QAAQ,SAASD,MAAK,KAAK,EAAE,gBAAgBA,SAAQ;AACxD,aAAO;AAAA,IACT;AAEA,WAAO,SAAS,QAAQC,QAAO,CAACD,MAAiB,GAAG,QAAQ,CAAC;AAAA,EAC/D,CAAC;AACH;","names":["PatchType","patch","value"]}
1
+ {"version":3,"sources":["../src/patch.ts"],"sourcesContent":["import {\n ArrayExpressions,\n EvaluateExpression,\n Expression,\n Expressions,\n NumericExpressions,\n ReducingExpression,\n} from '@bessemer/cornerstone/expression'\nimport { Objects, Preconditions } from '@bessemer/cornerstone'\nimport { UnknownRecord } from 'type-fest'\n\nexport enum PatchType {\n Set = 'Set',\n Apply = 'Apply',\n Patch = 'Patch',\n}\n\nexport type SetPatch<T> = {\n _PatchType: PatchType.Set\n value: Expression<T>\n}\n\nexport type ApplyPatch<T> = {\n _PatchType: PatchType.Apply\n value: Expression<T>\n reducer: ReducingExpression<T, T>\n}\n\nexport type PatchPatch<T> = {\n _PatchType: PatchType.Patch\n patch: Patchable<T>\n}\n\nexport type Patch<T> = SetPatch<T> | ApplyPatch<T> | PatchPatch<T>\n\nexport type PatchValue<T> = {\n value: T\n patch: Patch<T>\n}\n\nexport type Patchable<T> = {\n [P in keyof T]?: T[P] extends Array<infer U>\n ? Patch<U[]> | Patchable<U[]>\n : T[P] extends object | undefined\n ? Patch<T[P]> | Patchable<T[P]>\n : Patch<T[P]> | T[P]\n}\n\nexport const set = <T>(value: Expression<T>): Patch<T> => {\n return {\n _PatchType: PatchType.Set,\n value: value as any,\n }\n}\n\nexport const apply = <T>(value: Expression<T>, reducer: ReducingExpression<T, T>): Patch<T> => {\n return {\n _PatchType: PatchType.Apply,\n value,\n reducer,\n }\n}\n\nexport const patch = <T extends UnknownRecord, N extends Patchable<T> = Patchable<T>>(patch: N): Patch<T> => {\n return {\n _PatchType: PatchType.Patch,\n patch,\n }\n}\n\nexport const sum = (value: Expression<number>): Patch<number> => {\n return apply(value, Expressions.reference(NumericExpressions.SumExpression))\n}\n\nexport const multiply = (value: Expression<number>): Patch<number> => {\n return apply(value, Expressions.reference(NumericExpressions.MultiplyExpression))\n}\n\nexport const concatenate = <T extends Array<Expression<unknown>>>(value: Expression<T>): Patch<T> => {\n return apply(value, Expressions.reference(ArrayExpressions.ConcatenateExpression)) as Patch<T>\n}\n\nexport type ResolvePatchesResult<T> = {\n value: T\n patchValues: Array<PatchValue<T>>\n}\n\nexport const resolveWithDetails = <T>(value: T, patches: Array<Patch<T>>, evaluate: EvaluateExpression): ResolvePatchesResult<T> => {\n let currentValue: T = value\n\n const patchValues = patches.map((patch) => {\n switch (patch._PatchType) {\n case PatchType.Set:\n currentValue = evaluate(patch.value)\n break\n case PatchType.Apply:\n currentValue = evaluate(Expressions.dereference(patch.reducer, [currentValue, patch.value]))\n break\n case PatchType.Patch:\n currentValue = applyPatch(currentValue, patch.patch, evaluate)\n break\n default:\n Preconditions.isUnreachable(() => `Unrecognized PatchType for value: ${JSON.stringify(it)}`)\n }\n\n return { value: currentValue, patch }\n })\n\n return { value: currentValue, patchValues }\n}\n\nexport const resolve = <T>(value: T, patches: Array<Patch<T>>, evaluate: EvaluateExpression): T => {\n return resolveWithDetails(value, patches, evaluate).value\n}\n\nconst applyPatch = <T>(value: T, patch: Patchable<T>, evaluate: EvaluateExpression): T => {\n return Objects.deepMergeWith(value, patch, (value, patch) => {\n if (Objects.isNil(patch)) {\n return value\n }\n\n if (!Objects.isObject(patch) || !('_PatchType' in patch)) {\n return undefined\n }\n\n return evaluate(resolve(value, [patch as Patch<T>], evaluate))\n })\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,SAAS,qBAAqB;AAGhC,IAAK,YAAL,kBAAKA,eAAL;AACL,EAAAA,WAAA,SAAM;AACN,EAAAA,WAAA,WAAQ;AACR,EAAAA,WAAA,WAAQ;AAHE,SAAAA;AAAA,GAAA;AAqCL,IAAM,MAAM,CAAI,UAAmC;AACxD,SAAO;AAAA,IACL,YAAY;AAAA,IACZ;AAAA,EACF;AACF;AAEO,IAAM,QAAQ,CAAI,OAAsB,YAAgD;AAC7F,SAAO;AAAA,IACL,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AAEO,IAAM,QAAQ,CAAiEC,WAAuB;AAC3G,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,OAAAA;AAAA,EACF;AACF;AAEO,IAAM,MAAM,CAAC,UAA6C;AAC/D,SAAO,MAAM,OAAO,YAAY,UAAU,mBAAmB,aAAa,CAAC;AAC7E;AAEO,IAAM,WAAW,CAAC,UAA6C;AACpE,SAAO,MAAM,OAAO,YAAY,UAAU,mBAAmB,kBAAkB,CAAC;AAClF;AAEO,IAAM,cAAc,CAAuC,UAAmC;AACnG,SAAO,MAAM,OAAO,YAAY,UAAU,iBAAiB,qBAAqB,CAAC;AACnF;AAOO,IAAM,qBAAqB,CAAI,OAAU,SAA0B,aAA0D;AAClI,MAAI,eAAkB;AAEtB,QAAM,cAAc,QAAQ,IAAI,CAACA,WAAU;AACzC,YAAQA,OAAM,YAAY;AAAA,MACxB,KAAK;AACH,uBAAe,SAASA,OAAM,KAAK;AACnC;AAAA,MACF,KAAK;AACH,uBAAe,SAAS,YAAY,YAAYA,OAAM,SAAS,CAAC,cAAcA,OAAM,KAAK,CAAC,CAAC;AAC3F;AAAA,MACF,KAAK;AACH,uBAAe,WAAW,cAAcA,OAAM,OAAO,QAAQ;AAC7D;AAAA,MACF;AACE,sBAAc,cAAc,MAAM,qCAAqC,KAAK,UAAU,EAAE,CAAC,EAAE;AAAA,IAC/F;AAEA,WAAO,EAAE,OAAO,cAAc,OAAAA,OAAM;AAAA,EACtC,CAAC;AAED,SAAO,EAAE,OAAO,cAAc,YAAY;AAC5C;AAEO,IAAM,UAAU,CAAI,OAAU,SAA0B,aAAoC;AACjG,SAAO,mBAAmB,OAAO,SAAS,QAAQ,EAAE;AACtD;AAEA,IAAM,aAAa,CAAI,OAAUA,QAAqB,aAAoC;AACxF,SAAO,QAAQ,cAAc,OAAOA,QAAO,CAACC,QAAOD,WAAU;AAC3D,QAAI,QAAQ,MAAMA,MAAK,GAAG;AACxB,aAAOC;AAAA,IACT;AAEA,QAAI,CAAC,QAAQ,SAASD,MAAK,KAAK,EAAE,gBAAgBA,SAAQ;AACxD,aAAO;AAAA,IACT;AAEA,WAAO,SAAS,QAAQC,QAAO,CAACD,MAAiB,GAAG,QAAQ,CAAC;AAAA,EAC/D,CAAC;AACH;","names":["PatchType","patch","value"]}
package/dist/property.js CHANGED
@@ -12,7 +12,7 @@ var properties = (values, overrides) => {
12
12
  };
13
13
  var resolve = (properties2, tags) => {
14
14
  const overrides = Tags.resolve(Object.values(properties2.overrides), tags);
15
- return Objects.mergeAll([properties2.values, ...overrides.reverse()]);
15
+ return Objects.deepMergeAll([properties2.values, ...overrides.reverse()]);
16
16
  };
17
17
  export {
18
18
  properties,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/property.ts"],"sourcesContent":["import { Objects, Tags } from '@bessemer/cornerstone'\nimport { SerializedTags, Tag, TaggedValue } from '@bessemer/cornerstone/tag'\nimport { UnknownRecord } from 'type-fest'\nimport { DeepPartial } from '@bessemer/cornerstone/types'\n\nexport type PropertyRecord<T extends UnknownRecord> = {\n values: T\n overrides: Record<SerializedTags, PropertyOverride<T>>\n}\n\nexport type PropertyOverride<T> = TaggedValue<DeepPartial<T>>\n\nexport const properties = <T extends UnknownRecord>(values: T, overrides?: Array<PropertyOverride<T>>): PropertyRecord<T> => {\n const propertyOverrideEntries = (overrides ?? []).map((override) => {\n return [Tags.serializeTags(override.tags), override]\n })\n\n const propertyOverrides: Record<SerializedTags, PropertyOverride<T>> = Object.fromEntries(propertyOverrideEntries)\n\n return {\n values,\n overrides: propertyOverrides,\n }\n}\n\nexport const resolve = <T extends UnknownRecord>(properties: PropertyRecord<T>, tags: Array<Tag>): T => {\n const overrides = Tags.resolve(Object.values(properties.overrides), tags)\n return Objects.mergeAll([properties.values, ...overrides.reverse()]) as T\n}\n"],"mappings":";AAAA,SAAS,SAAS,YAAY;AAYvB,IAAM,aAAa,CAA0B,QAAW,cAA8D;AAC3H,QAAM,2BAA2B,aAAa,CAAC,GAAG,IAAI,CAAC,aAAa;AAClE,WAAO,CAAC,KAAK,cAAc,SAAS,IAAI,GAAG,QAAQ;AAAA,EACrD,CAAC;AAED,QAAM,oBAAiE,OAAO,YAAY,uBAAuB;AAEjH,SAAO;AAAA,IACL;AAAA,IACA,WAAW;AAAA,EACb;AACF;AAEO,IAAM,UAAU,CAA0BA,aAA+B,SAAwB;AACtG,QAAM,YAAY,KAAK,QAAQ,OAAO,OAAOA,YAAW,SAAS,GAAG,IAAI;AACxE,SAAO,QAAQ,SAAS,CAACA,YAAW,QAAQ,GAAG,UAAU,QAAQ,CAAC,CAAC;AACrE;","names":["properties"]}
1
+ {"version":3,"sources":["../src/property.ts"],"sourcesContent":["import { Objects, Tags } from '@bessemer/cornerstone'\nimport { SerializedTags, Tag, TaggedValue } from '@bessemer/cornerstone/tag'\nimport { UnknownRecord } from 'type-fest'\nimport { DeepPartial } from '@bessemer/cornerstone/types'\n\nexport type PropertyRecord<T extends UnknownRecord> = {\n values: T\n overrides: Record<SerializedTags, PropertyOverride<T>>\n}\n\nexport type PropertyOverride<T> = TaggedValue<DeepPartial<T>>\n\nexport const properties = <T extends UnknownRecord>(values: T, overrides?: Array<PropertyOverride<T>>): PropertyRecord<T> => {\n const propertyOverrideEntries = (overrides ?? []).map((override) => {\n return [Tags.serializeTags(override.tags), override]\n })\n\n const propertyOverrides: Record<SerializedTags, PropertyOverride<T>> = Object.fromEntries(propertyOverrideEntries)\n\n return {\n values,\n overrides: propertyOverrides,\n }\n}\n\nexport const resolve = <T extends UnknownRecord>(properties: PropertyRecord<T>, tags: Array<Tag>): T => {\n const overrides = Tags.resolve(Object.values(properties.overrides), tags)\n return Objects.deepMergeAll([properties.values, ...overrides.reverse()]) as T\n}\n"],"mappings":";AAAA,SAAS,SAAS,YAAY;AAYvB,IAAM,aAAa,CAA0B,QAAW,cAA8D;AAC3H,QAAM,2BAA2B,aAAa,CAAC,GAAG,IAAI,CAAC,aAAa;AAClE,WAAO,CAAC,KAAK,cAAc,SAAS,IAAI,GAAG,QAAQ;AAAA,EACrD,CAAC;AAED,QAAM,oBAAiE,OAAO,YAAY,uBAAuB;AAEjH,SAAO;AAAA,IACL;AAAA,IACA,WAAW;AAAA,EACb;AACF;AAEO,IAAM,UAAU,CAA0BA,aAA+B,SAAwB;AACtG,QAAM,YAAY,KAAK,QAAQ,OAAO,OAAOA,YAAW,SAAS,GAAG,IAAI;AACxE,SAAO,QAAQ,aAAa,CAACA,YAAW,QAAQ,GAAG,UAAU,QAAQ,CAAC,CAAC;AACzE;","names":["properties"]}
package/dist/retry.js CHANGED
@@ -9,7 +9,7 @@ var DefaultRetryProps = {
9
9
  delay: Durations.ofMilliseconds(500)
10
10
  };
11
11
  var initialize = (initialOptions) => {
12
- const props = Objects.merge(DefaultRetryProps, initialOptions);
12
+ const props = Objects.deepMerge(DefaultRetryProps, initialOptions);
13
13
  Preconditions.isTrue(props.attempts >= 0, () => "usingRetry attempts must be >= 0");
14
14
  return {
15
15
  attempt: 0,
package/dist/retry.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/retry.ts"],"sourcesContent":["import { Duration } from '@bessemer/cornerstone/duration'\nimport { Async, Durations, Maths, Objects, Preconditions, Results } from '@bessemer/cornerstone'\nimport { AsyncResult, Result } from '@bessemer/cornerstone/result'\nimport { PartialDeep } from 'type-fest'\n\nexport type RetryProps = {\n attempts: number\n delay: Duration\n}\n\nexport type RetryOptions = PartialDeep<RetryProps>\n\nexport const None: RetryProps = {\n attempts: 0,\n delay: Durations.Zero,\n}\n\nexport const DefaultRetryProps: RetryProps = {\n attempts: 3,\n delay: Durations.ofMilliseconds(500),\n}\n\nexport type RetryState = {\n attempt: number\n props: RetryProps\n}\n\nexport const initialize = (initialOptions?: RetryOptions): RetryState => {\n const props = Objects.merge(DefaultRetryProps, initialOptions)\n Preconditions.isTrue(props.attempts >= 0, () => 'usingRetry attempts must be >= 0')\n\n return {\n attempt: 0,\n props,\n }\n}\n\nexport const retry = async (state: RetryState): Promise<RetryState | undefined> => {\n if (state.attempt >= state.props.attempts - 1) {\n return undefined\n }\n\n const delayMs = Durations.inMilliseconds(state.props.delay)\n const maxJitterMs = delayMs * 0.3 // We calculate max jitter as 30% of the delay\n await Async.sleep(Durations.ofMilliseconds(delayMs + Maths.random(0, maxJitterMs)))\n\n return {\n props: state.props,\n attempt: state.attempt + 1,\n }\n}\n\nexport const usingRetry = async <T>(runnable: () => Promise<Result<T>>, initialOptions?: RetryOptions): AsyncResult<T> => {\n let retryState: RetryState | undefined = initialize(initialOptions)\n let previousResult: Result<T> = Results.failure()\n\n do {\n // JOHN Should this be a try/catch? it was causing debugging problems\n const result = await runnable()\n previousResult = result\n\n if (result.isSuccess) {\n return result\n }\n\n retryState = await retry(retryState)\n } while (!Objects.isUndefined(retryState))\n\n return previousResult\n}\n"],"mappings":";AACA,SAAS,OAAO,WAAW,OAAO,SAAS,eAAe,eAAe;AAWlE,IAAM,OAAmB;AAAA,EAC9B,UAAU;AAAA,EACV,OAAO,UAAU;AACnB;AAEO,IAAM,oBAAgC;AAAA,EAC3C,UAAU;AAAA,EACV,OAAO,UAAU,eAAe,GAAG;AACrC;AAOO,IAAM,aAAa,CAAC,mBAA8C;AACvE,QAAM,QAAQ,QAAQ,MAAM,mBAAmB,cAAc;AAC7D,gBAAc,OAAO,MAAM,YAAY,GAAG,MAAM,kCAAkC;AAElF,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,EACF;AACF;AAEO,IAAM,QAAQ,OAAO,UAAuD;AACjF,MAAI,MAAM,WAAW,MAAM,MAAM,WAAW,GAAG;AAC7C,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,UAAU,eAAe,MAAM,MAAM,KAAK;AAC1D,QAAM,cAAc,UAAU;AAC9B,QAAM,MAAM,MAAM,UAAU,eAAe,UAAU,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC;AAElF,SAAO;AAAA,IACL,OAAO,MAAM;AAAA,IACb,SAAS,MAAM,UAAU;AAAA,EAC3B;AACF;AAEO,IAAM,aAAa,OAAU,UAAoC,mBAAkD;AACxH,MAAI,aAAqC,WAAW,cAAc;AAClE,MAAI,iBAA4B,QAAQ,QAAQ;AAEhD,KAAG;AAED,UAAM,SAAS,MAAM,SAAS;AAC9B,qBAAiB;AAEjB,QAAI,OAAO,WAAW;AACpB,aAAO;AAAA,IACT;AAEA,iBAAa,MAAM,MAAM,UAAU;AAAA,EACrC,SAAS,CAAC,QAAQ,YAAY,UAAU;AAExC,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/retry.ts"],"sourcesContent":["import { Duration } from '@bessemer/cornerstone/duration'\nimport { Async, Durations, Maths, Objects, Preconditions, Results } from '@bessemer/cornerstone'\nimport { AsyncResult, Result } from '@bessemer/cornerstone/result'\nimport { PartialDeep } from 'type-fest'\n\nexport type RetryProps = {\n attempts: number\n delay: Duration\n}\n\nexport type RetryOptions = PartialDeep<RetryProps>\n\nexport const None: RetryProps = {\n attempts: 0,\n delay: Durations.Zero,\n}\n\nexport const DefaultRetryProps: RetryProps = {\n attempts: 3,\n delay: Durations.ofMilliseconds(500),\n}\n\nexport type RetryState = {\n attempt: number\n props: RetryProps\n}\n\nexport const initialize = (initialOptions?: RetryOptions): RetryState => {\n const props = Objects.deepMerge(DefaultRetryProps, initialOptions)\n Preconditions.isTrue(props.attempts >= 0, () => 'usingRetry attempts must be >= 0')\n\n return {\n attempt: 0,\n props,\n }\n}\n\nexport const retry = async (state: RetryState): Promise<RetryState | undefined> => {\n if (state.attempt >= state.props.attempts - 1) {\n return undefined\n }\n\n const delayMs = Durations.inMilliseconds(state.props.delay)\n const maxJitterMs = delayMs * 0.3 // We calculate max jitter as 30% of the delay\n await Async.sleep(Durations.ofMilliseconds(delayMs + Maths.random(0, maxJitterMs)))\n\n return {\n props: state.props,\n attempt: state.attempt + 1,\n }\n}\n\nexport const usingRetry = async <T>(runnable: () => Promise<Result<T>>, initialOptions?: RetryOptions): AsyncResult<T> => {\n let retryState: RetryState | undefined = initialize(initialOptions)\n let previousResult: Result<T> = Results.failure()\n\n do {\n // JOHN Should this be a try/catch? it was causing debugging problems\n const result = await runnable()\n previousResult = result\n\n if (result.isSuccess) {\n return result\n }\n\n retryState = await retry(retryState)\n } while (!Objects.isUndefined(retryState))\n\n return previousResult\n}\n"],"mappings":";AACA,SAAS,OAAO,WAAW,OAAO,SAAS,eAAe,eAAe;AAWlE,IAAM,OAAmB;AAAA,EAC9B,UAAU;AAAA,EACV,OAAO,UAAU;AACnB;AAEO,IAAM,oBAAgC;AAAA,EAC3C,UAAU;AAAA,EACV,OAAO,UAAU,eAAe,GAAG;AACrC;AAOO,IAAM,aAAa,CAAC,mBAA8C;AACvE,QAAM,QAAQ,QAAQ,UAAU,mBAAmB,cAAc;AACjE,gBAAc,OAAO,MAAM,YAAY,GAAG,MAAM,kCAAkC;AAElF,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,EACF;AACF;AAEO,IAAM,QAAQ,OAAO,UAAuD;AACjF,MAAI,MAAM,WAAW,MAAM,MAAM,WAAW,GAAG;AAC7C,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,UAAU,eAAe,MAAM,MAAM,KAAK;AAC1D,QAAM,cAAc,UAAU;AAC9B,QAAM,MAAM,MAAM,UAAU,eAAe,UAAU,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC;AAElF,SAAO;AAAA,IACL,OAAO,MAAM;AAAA,IACb,SAAS,MAAM,UAAU;AAAA,EAC3B;AACF;AAEO,IAAM,aAAa,OAAU,UAAoC,mBAAkD;AACxH,MAAI,aAAqC,WAAW,cAAc;AAClE,MAAI,iBAA4B,QAAQ,QAAQ;AAEhD,KAAG;AAED,UAAM,SAAS,MAAM,SAAS;AAC9B,qBAAiB;AAEjB,QAAI,OAAO,WAAW;AACpB,aAAO;AAAA,IACT;AAEA,iBAAa,MAAM,MAAM,UAAU;AAAA,EACrC,SAAS,CAAC,QAAQ,YAAY,UAAU;AAExC,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bessemer/cornerstone",
3
3
  "type": "module",
4
- "version": "0.5.37",
4
+ "version": "0.5.38",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "sideEffects": false,