@flurryx/core 0.8.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/keyed-resource.ts","../src/constants.ts"],"sourcesContent":["export type { ResourceState, StoreEnum } from './resource-state';\nexport type {\n KeyedResourceData,\n KeyedResourceKey,\n ResourceStatus,\n ResourceErrors,\n} from './keyed-resource';\nexport {\n isKeyedResourceData,\n createKeyedResourceData,\n isAnyKeyLoading,\n} from './keyed-resource';\nexport { CACHE_NO_TIMEOUT, DEFAULT_CACHE_TTL_MS } from './constants';\n","import { ResourceState } from './resource-state';\n\nexport type KeyedResourceKey = string | number;\n\nexport type ResourceStatus = NonNullable<ResourceState<unknown>['status']>;\nexport type ResourceErrors = NonNullable<ResourceState<unknown>['errors']>;\n\nexport interface KeyedResourceData<TKey extends KeyedResourceKey, TValue> {\n entities: Partial<Record<TKey, TValue>>;\n isLoading: Partial<Record<TKey, boolean>>;\n status: Partial<Record<TKey, ResourceStatus>>;\n errors: Partial<Record<TKey, ResourceErrors>>;\n}\n\nexport function isKeyedResourceData(\n value: unknown\n): value is KeyedResourceData<KeyedResourceKey, unknown> {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const data = value as Partial<KeyedResourceData<KeyedResourceKey, unknown>>;\n return (\n typeof data.entities === 'object' &&\n data.entities !== null &&\n typeof data.isLoading === 'object' &&\n data.isLoading !== null &&\n typeof data.status === 'object' &&\n data.status !== null &&\n typeof data.errors === 'object' &&\n data.errors !== null\n );\n}\n\nexport function createKeyedResourceData<\n TKey extends KeyedResourceKey,\n TValue,\n>(): KeyedResourceData<TKey, TValue> {\n return {\n entities: {} as Partial<Record<TKey, TValue>>,\n isLoading: {} as Partial<Record<TKey, boolean>>,\n status: {} as Partial<Record<TKey, ResourceStatus>>,\n errors: {} as Partial<Record<TKey, ResourceErrors>>,\n };\n}\n\nexport function isAnyKeyLoading<TKey extends KeyedResourceKey>(\n loading: Partial<Record<TKey, boolean>>\n): boolean {\n return Object.values(loading).some((value) => value === true);\n}\n","export const CACHE_NO_TIMEOUT = Infinity;\nexport const DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACcO,SAAS,oBACd,OACuD;AACvD,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,OAAO;AACb,SACE,OAAO,KAAK,aAAa,YACzB,KAAK,aAAa,QAClB,OAAO,KAAK,cAAc,YAC1B,KAAK,cAAc,QACnB,OAAO,KAAK,WAAW,YACvB,KAAK,WAAW,QAChB,OAAO,KAAK,WAAW,YACvB,KAAK,WAAW;AAEpB;AAEO,SAAS,0BAGqB;AACnC,SAAO;AAAA,IACL,UAAU,CAAC;AAAA,IACX,WAAW,CAAC;AAAA,IACZ,QAAQ,CAAC;AAAA,IACT,QAAQ,CAAC;AAAA,EACX;AACF;AAEO,SAAS,gBACd,SACS;AACT,SAAO,OAAO,OAAO,OAAO,EAAE,KAAK,CAAC,UAAU,UAAU,IAAI;AAC9D;;;AClDO,IAAM,mBAAmB;AACzB,IAAM,uBAAuB,IAAI,KAAK;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/keyed-resource.ts","../src/constants.ts"],"sourcesContent":["export type { ResourceState, StoreEnum } from './resource-state';\nexport type {\n KeyedResourceData,\n KeyedResourceKey,\n ResourceStatus,\n ResourceErrors,\n} from './keyed-resource';\nexport {\n isKeyedResourceData,\n createKeyedResourceData,\n isAnyKeyLoading,\n} from './keyed-resource';\nexport { CACHE_NO_TIMEOUT, DEFAULT_CACHE_TTL_MS } from './constants';\n","import { ResourceState } from \"./resource-state\";\n\n/**\n * Type for resource keys used to index entities in a {@link KeyedResourceData} slot.\n */\nexport type KeyedResourceKey = string | number;\n\n/**\n * Literal union for resource status: `'Success'` or `'Error'`.\n */\nexport type ResourceStatus = NonNullable<ResourceState<unknown>[\"status\"]>;\n\n/**\n * Normalized error array shape: `Array<{ code: string; message: string }>`.\n */\nexport type ResourceErrors = NonNullable<ResourceState<unknown>[\"errors\"]>;\n\n/**\n * Container for keyed (indexed by ID) resource data.\n *\n * Each entity gets **independent** loading, status, and error tracking.\n * Use this when a single store slot manages multiple entities (e.g. user profiles by ID).\n *\n * @template TKey - The entity identifier type (`string` or `number`).\n * @template TValue - The entity type.\n *\n * @example\n * ```ts\n * interface InvoiceStoreConfig {\n * ITEMS: KeyedResourceData<string, Invoice>;\n * }\n *\n * // Accessing per-key state:\n * const data = store.get('ITEMS')().data;\n * const invoice = data?.entities['inv-123'];\n * const loading = data?.isLoading['inv-123'];\n * const errors = data?.errors['inv-123'];\n * ```\n */\nexport interface KeyedResourceData<TKey extends KeyedResourceKey, TValue> {\n /** Map of entity ID → entity value. */\n entities: Partial<Record<TKey, TValue>>;\n /** Map of entity ID → whether that entity is currently loading. */\n isLoading: Partial<Record<TKey, boolean>>;\n /** Map of entity ID → resource status (`'Success'` or `'Error'`). */\n status: Partial<Record<TKey, ResourceStatus>>;\n /** Map of entity ID → error array for that entity. */\n errors: Partial<Record<TKey, ResourceErrors>>;\n}\n\n/**\n * Type guard that checks whether a value is a {@link KeyedResourceData} structure.\n *\n * @param value - The value to check.\n * @returns `true` if the value has `entities`, `isLoading`, `status`, and `errors` object fields.\n *\n * @example\n * ```ts\n * const state = store.get('ITEMS')();\n * if (isKeyedResourceData(state.data)) {\n * console.log(state.data.entities);\n * }\n * ```\n */\nexport function isKeyedResourceData(\n value: unknown\n): value is KeyedResourceData<KeyedResourceKey, unknown> {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const data = value as Partial<KeyedResourceData<KeyedResourceKey, unknown>>;\n return (\n typeof data.entities === \"object\" &&\n data.entities !== null &&\n typeof data.isLoading === \"object\" &&\n data.isLoading !== null &&\n typeof data.status === \"object\" &&\n data.status !== null &&\n typeof data.errors === \"object\" &&\n data.errors !== null\n );\n}\n\n/**\n * Creates an empty {@link KeyedResourceData} with all maps initialized to `{}`.\n *\n * @template TKey - The entity identifier type.\n * @template TValue - The entity type.\n * @returns A new `KeyedResourceData` with empty `entities`, `isLoading`, `status`, and `errors`.\n *\n * @example\n * ```ts\n * const initial = createKeyedResourceData<string, Invoice>();\n * // { entities: {}, isLoading: {}, status: {}, errors: {} }\n * ```\n */\nexport function createKeyedResourceData<\n TKey extends KeyedResourceKey,\n TValue\n>(): KeyedResourceData<TKey, TValue> {\n return {\n entities: {} as Partial<Record<TKey, TValue>>,\n isLoading: {} as Partial<Record<TKey, boolean>>,\n status: {} as Partial<Record<TKey, ResourceStatus>>,\n errors: {} as Partial<Record<TKey, ResourceErrors>>,\n };\n}\n\n/**\n * Checks whether any entity in a keyed loading map is currently loading.\n *\n * @param loading - The `isLoading` map from a {@link KeyedResourceData}.\n * @returns `true` if at least one key has a value of `true`.\n *\n * @example\n * ```ts\n * const data = store.get('ITEMS')().data;\n * if (data && isAnyKeyLoading(data.isLoading)) {\n * console.log('At least one item is loading');\n * }\n * ```\n */\nexport function isAnyKeyLoading<TKey extends KeyedResourceKey>(\n loading: Partial<Record<TKey, boolean>>\n): boolean {\n return Object.values(loading).some((value) => value === true);\n}\n","/**\n * Sentinel value indicating the cache should never expire.\n * Pass to `@SkipIfCached` `timeoutMs` parameter to disable TTL-based invalidation.\n *\n * @example\n * ```ts\n * @SkipIfCached('LIST', (i) => i.store, false, CACHE_NO_TIMEOUT)\n * ```\n */\nexport const CACHE_NO_TIMEOUT = Infinity;\n\n/**\n * Default cache time-to-live in milliseconds: **5 minutes** (300 000 ms).\n * Used by `@SkipIfCached` when no `timeoutMs` is provided.\n */\nexport const DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACgEO,SAAS,oBACd,OACuD;AACvD,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,OAAO;AACb,SACE,OAAO,KAAK,aAAa,YACzB,KAAK,aAAa,QAClB,OAAO,KAAK,cAAc,YAC1B,KAAK,cAAc,QACnB,OAAO,KAAK,WAAW,YACvB,KAAK,WAAW,QAChB,OAAO,KAAK,WAAW,YACvB,KAAK,WAAW;AAEpB;AAeO,SAAS,0BAGqB;AACnC,SAAO;AAAA,IACL,UAAU,CAAC;AAAA,IACX,WAAW,CAAC;AAAA,IACZ,QAAQ,CAAC;AAAA,IACT,QAAQ,CAAC;AAAA,EACX;AACF;AAgBO,SAAS,gBACd,SACS;AACT,SAAO,OAAO,OAAO,OAAO,EAAE,KAAK,CAAC,UAAU,UAAU,IAAI;AAC9D;;;ACtHO,IAAM,mBAAmB;AAMzB,IAAM,uBAAuB,IAAI,KAAK;","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,28 +1,147 @@
1
+ /**
2
+ * Generic state wrapper for an async resource (e.g. an HTTP call).
3
+ *
4
+ * Every store slot holds a `ResourceState`. It starts as idle and transitions
5
+ * through loading → success/error as the underlying operation progresses.
6
+ *
7
+ * @template T - The type of the data payload.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * // Initial (idle) state
12
+ * { data: undefined, isLoading: false, status: undefined, errors: undefined }
13
+ *
14
+ * // Loading
15
+ * { data: undefined, isLoading: true, status: undefined, errors: undefined }
16
+ *
17
+ * // Success
18
+ * { data: product, isLoading: false, status: 'Success', errors: undefined }
19
+ *
20
+ * // Error
21
+ * { data: undefined, isLoading: false, status: 'Error', errors: [{ code: '404', message: 'Not found' }] }
22
+ * ```
23
+ */
1
24
  interface ResourceState<T> {
25
+ /** Whether the resource is currently being fetched. */
2
26
  isLoading?: boolean;
27
+ /** The data payload. `undefined` until the first successful fetch. */
3
28
  data?: T;
4
- status?: 'Success' | 'Error';
29
+ /** `'Success'` after a successful fetch, `'Error'` after a failure. `undefined` while idle or loading. */
30
+ status?: "Success" | "Error";
31
+ /** Normalized error array. Present only when `status` is `'Error'`. */
5
32
  errors?: Array<{
6
33
  code: string;
7
34
  message: string;
8
35
  }>;
9
36
  }
37
+ /**
38
+ * Union type accepted as a store key identifier.
39
+ */
10
40
  type StoreEnum = string | number | symbol;
11
41
 
42
+ /**
43
+ * Type for resource keys used to index entities in a {@link KeyedResourceData} slot.
44
+ */
12
45
  type KeyedResourceKey = string | number;
13
- type ResourceStatus = NonNullable<ResourceState<unknown>['status']>;
14
- type ResourceErrors = NonNullable<ResourceState<unknown>['errors']>;
46
+ /**
47
+ * Literal union for resource status: `'Success'` or `'Error'`.
48
+ */
49
+ type ResourceStatus = NonNullable<ResourceState<unknown>["status"]>;
50
+ /**
51
+ * Normalized error array shape: `Array<{ code: string; message: string }>`.
52
+ */
53
+ type ResourceErrors = NonNullable<ResourceState<unknown>["errors"]>;
54
+ /**
55
+ * Container for keyed (indexed by ID) resource data.
56
+ *
57
+ * Each entity gets **independent** loading, status, and error tracking.
58
+ * Use this when a single store slot manages multiple entities (e.g. user profiles by ID).
59
+ *
60
+ * @template TKey - The entity identifier type (`string` or `number`).
61
+ * @template TValue - The entity type.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * interface InvoiceStoreConfig {
66
+ * ITEMS: KeyedResourceData<string, Invoice>;
67
+ * }
68
+ *
69
+ * // Accessing per-key state:
70
+ * const data = store.get('ITEMS')().data;
71
+ * const invoice = data?.entities['inv-123'];
72
+ * const loading = data?.isLoading['inv-123'];
73
+ * const errors = data?.errors['inv-123'];
74
+ * ```
75
+ */
15
76
  interface KeyedResourceData<TKey extends KeyedResourceKey, TValue> {
77
+ /** Map of entity ID → entity value. */
16
78
  entities: Partial<Record<TKey, TValue>>;
79
+ /** Map of entity ID → whether that entity is currently loading. */
17
80
  isLoading: Partial<Record<TKey, boolean>>;
81
+ /** Map of entity ID → resource status (`'Success'` or `'Error'`). */
18
82
  status: Partial<Record<TKey, ResourceStatus>>;
83
+ /** Map of entity ID → error array for that entity. */
19
84
  errors: Partial<Record<TKey, ResourceErrors>>;
20
85
  }
86
+ /**
87
+ * Type guard that checks whether a value is a {@link KeyedResourceData} structure.
88
+ *
89
+ * @param value - The value to check.
90
+ * @returns `true` if the value has `entities`, `isLoading`, `status`, and `errors` object fields.
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * const state = store.get('ITEMS')();
95
+ * if (isKeyedResourceData(state.data)) {
96
+ * console.log(state.data.entities);
97
+ * }
98
+ * ```
99
+ */
21
100
  declare function isKeyedResourceData(value: unknown): value is KeyedResourceData<KeyedResourceKey, unknown>;
101
+ /**
102
+ * Creates an empty {@link KeyedResourceData} with all maps initialized to `{}`.
103
+ *
104
+ * @template TKey - The entity identifier type.
105
+ * @template TValue - The entity type.
106
+ * @returns A new `KeyedResourceData` with empty `entities`, `isLoading`, `status`, and `errors`.
107
+ *
108
+ * @example
109
+ * ```ts
110
+ * const initial = createKeyedResourceData<string, Invoice>();
111
+ * // { entities: {}, isLoading: {}, status: {}, errors: {} }
112
+ * ```
113
+ */
22
114
  declare function createKeyedResourceData<TKey extends KeyedResourceKey, TValue>(): KeyedResourceData<TKey, TValue>;
115
+ /**
116
+ * Checks whether any entity in a keyed loading map is currently loading.
117
+ *
118
+ * @param loading - The `isLoading` map from a {@link KeyedResourceData}.
119
+ * @returns `true` if at least one key has a value of `true`.
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * const data = store.get('ITEMS')().data;
124
+ * if (data && isAnyKeyLoading(data.isLoading)) {
125
+ * console.log('At least one item is loading');
126
+ * }
127
+ * ```
128
+ */
23
129
  declare function isAnyKeyLoading<TKey extends KeyedResourceKey>(loading: Partial<Record<TKey, boolean>>): boolean;
24
130
 
131
+ /**
132
+ * Sentinel value indicating the cache should never expire.
133
+ * Pass to `@SkipIfCached` `timeoutMs` parameter to disable TTL-based invalidation.
134
+ *
135
+ * @example
136
+ * ```ts
137
+ * @SkipIfCached('LIST', (i) => i.store, false, CACHE_NO_TIMEOUT)
138
+ * ```
139
+ */
25
140
  declare const CACHE_NO_TIMEOUT: number;
141
+ /**
142
+ * Default cache time-to-live in milliseconds: **5 minutes** (300 000 ms).
143
+ * Used by `@SkipIfCached` when no `timeoutMs` is provided.
144
+ */
26
145
  declare const DEFAULT_CACHE_TTL_MS: number;
27
146
 
28
147
  export { CACHE_NO_TIMEOUT, DEFAULT_CACHE_TTL_MS, type KeyedResourceData, type KeyedResourceKey, type ResourceErrors, type ResourceState, type ResourceStatus, type StoreEnum, createKeyedResourceData, isAnyKeyLoading, isKeyedResourceData };
package/dist/index.d.ts CHANGED
@@ -1,28 +1,147 @@
1
+ /**
2
+ * Generic state wrapper for an async resource (e.g. an HTTP call).
3
+ *
4
+ * Every store slot holds a `ResourceState`. It starts as idle and transitions
5
+ * through loading → success/error as the underlying operation progresses.
6
+ *
7
+ * @template T - The type of the data payload.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * // Initial (idle) state
12
+ * { data: undefined, isLoading: false, status: undefined, errors: undefined }
13
+ *
14
+ * // Loading
15
+ * { data: undefined, isLoading: true, status: undefined, errors: undefined }
16
+ *
17
+ * // Success
18
+ * { data: product, isLoading: false, status: 'Success', errors: undefined }
19
+ *
20
+ * // Error
21
+ * { data: undefined, isLoading: false, status: 'Error', errors: [{ code: '404', message: 'Not found' }] }
22
+ * ```
23
+ */
1
24
  interface ResourceState<T> {
25
+ /** Whether the resource is currently being fetched. */
2
26
  isLoading?: boolean;
27
+ /** The data payload. `undefined` until the first successful fetch. */
3
28
  data?: T;
4
- status?: 'Success' | 'Error';
29
+ /** `'Success'` after a successful fetch, `'Error'` after a failure. `undefined` while idle or loading. */
30
+ status?: "Success" | "Error";
31
+ /** Normalized error array. Present only when `status` is `'Error'`. */
5
32
  errors?: Array<{
6
33
  code: string;
7
34
  message: string;
8
35
  }>;
9
36
  }
37
+ /**
38
+ * Union type accepted as a store key identifier.
39
+ */
10
40
  type StoreEnum = string | number | symbol;
11
41
 
42
+ /**
43
+ * Type for resource keys used to index entities in a {@link KeyedResourceData} slot.
44
+ */
12
45
  type KeyedResourceKey = string | number;
13
- type ResourceStatus = NonNullable<ResourceState<unknown>['status']>;
14
- type ResourceErrors = NonNullable<ResourceState<unknown>['errors']>;
46
+ /**
47
+ * Literal union for resource status: `'Success'` or `'Error'`.
48
+ */
49
+ type ResourceStatus = NonNullable<ResourceState<unknown>["status"]>;
50
+ /**
51
+ * Normalized error array shape: `Array<{ code: string; message: string }>`.
52
+ */
53
+ type ResourceErrors = NonNullable<ResourceState<unknown>["errors"]>;
54
+ /**
55
+ * Container for keyed (indexed by ID) resource data.
56
+ *
57
+ * Each entity gets **independent** loading, status, and error tracking.
58
+ * Use this when a single store slot manages multiple entities (e.g. user profiles by ID).
59
+ *
60
+ * @template TKey - The entity identifier type (`string` or `number`).
61
+ * @template TValue - The entity type.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * interface InvoiceStoreConfig {
66
+ * ITEMS: KeyedResourceData<string, Invoice>;
67
+ * }
68
+ *
69
+ * // Accessing per-key state:
70
+ * const data = store.get('ITEMS')().data;
71
+ * const invoice = data?.entities['inv-123'];
72
+ * const loading = data?.isLoading['inv-123'];
73
+ * const errors = data?.errors['inv-123'];
74
+ * ```
75
+ */
15
76
  interface KeyedResourceData<TKey extends KeyedResourceKey, TValue> {
77
+ /** Map of entity ID → entity value. */
16
78
  entities: Partial<Record<TKey, TValue>>;
79
+ /** Map of entity ID → whether that entity is currently loading. */
17
80
  isLoading: Partial<Record<TKey, boolean>>;
81
+ /** Map of entity ID → resource status (`'Success'` or `'Error'`). */
18
82
  status: Partial<Record<TKey, ResourceStatus>>;
83
+ /** Map of entity ID → error array for that entity. */
19
84
  errors: Partial<Record<TKey, ResourceErrors>>;
20
85
  }
86
+ /**
87
+ * Type guard that checks whether a value is a {@link KeyedResourceData} structure.
88
+ *
89
+ * @param value - The value to check.
90
+ * @returns `true` if the value has `entities`, `isLoading`, `status`, and `errors` object fields.
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * const state = store.get('ITEMS')();
95
+ * if (isKeyedResourceData(state.data)) {
96
+ * console.log(state.data.entities);
97
+ * }
98
+ * ```
99
+ */
21
100
  declare function isKeyedResourceData(value: unknown): value is KeyedResourceData<KeyedResourceKey, unknown>;
101
+ /**
102
+ * Creates an empty {@link KeyedResourceData} with all maps initialized to `{}`.
103
+ *
104
+ * @template TKey - The entity identifier type.
105
+ * @template TValue - The entity type.
106
+ * @returns A new `KeyedResourceData` with empty `entities`, `isLoading`, `status`, and `errors`.
107
+ *
108
+ * @example
109
+ * ```ts
110
+ * const initial = createKeyedResourceData<string, Invoice>();
111
+ * // { entities: {}, isLoading: {}, status: {}, errors: {} }
112
+ * ```
113
+ */
22
114
  declare function createKeyedResourceData<TKey extends KeyedResourceKey, TValue>(): KeyedResourceData<TKey, TValue>;
115
+ /**
116
+ * Checks whether any entity in a keyed loading map is currently loading.
117
+ *
118
+ * @param loading - The `isLoading` map from a {@link KeyedResourceData}.
119
+ * @returns `true` if at least one key has a value of `true`.
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * const data = store.get('ITEMS')().data;
124
+ * if (data && isAnyKeyLoading(data.isLoading)) {
125
+ * console.log('At least one item is loading');
126
+ * }
127
+ * ```
128
+ */
23
129
  declare function isAnyKeyLoading<TKey extends KeyedResourceKey>(loading: Partial<Record<TKey, boolean>>): boolean;
24
130
 
131
+ /**
132
+ * Sentinel value indicating the cache should never expire.
133
+ * Pass to `@SkipIfCached` `timeoutMs` parameter to disable TTL-based invalidation.
134
+ *
135
+ * @example
136
+ * ```ts
137
+ * @SkipIfCached('LIST', (i) => i.store, false, CACHE_NO_TIMEOUT)
138
+ * ```
139
+ */
25
140
  declare const CACHE_NO_TIMEOUT: number;
141
+ /**
142
+ * Default cache time-to-live in milliseconds: **5 minutes** (300 000 ms).
143
+ * Used by `@SkipIfCached` when no `timeoutMs` is provided.
144
+ */
26
145
  declare const DEFAULT_CACHE_TTL_MS: number;
27
146
 
28
147
  export { CACHE_NO_TIMEOUT, DEFAULT_CACHE_TTL_MS, type KeyedResourceData, type KeyedResourceKey, type ResourceErrors, type ResourceState, type ResourceStatus, type StoreEnum, createKeyedResourceData, isAnyKeyLoading, isKeyedResourceData };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/keyed-resource.ts","../src/constants.ts"],"sourcesContent":["import { ResourceState } from './resource-state';\n\nexport type KeyedResourceKey = string | number;\n\nexport type ResourceStatus = NonNullable<ResourceState<unknown>['status']>;\nexport type ResourceErrors = NonNullable<ResourceState<unknown>['errors']>;\n\nexport interface KeyedResourceData<TKey extends KeyedResourceKey, TValue> {\n entities: Partial<Record<TKey, TValue>>;\n isLoading: Partial<Record<TKey, boolean>>;\n status: Partial<Record<TKey, ResourceStatus>>;\n errors: Partial<Record<TKey, ResourceErrors>>;\n}\n\nexport function isKeyedResourceData(\n value: unknown\n): value is KeyedResourceData<KeyedResourceKey, unknown> {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const data = value as Partial<KeyedResourceData<KeyedResourceKey, unknown>>;\n return (\n typeof data.entities === 'object' &&\n data.entities !== null &&\n typeof data.isLoading === 'object' &&\n data.isLoading !== null &&\n typeof data.status === 'object' &&\n data.status !== null &&\n typeof data.errors === 'object' &&\n data.errors !== null\n );\n}\n\nexport function createKeyedResourceData<\n TKey extends KeyedResourceKey,\n TValue,\n>(): KeyedResourceData<TKey, TValue> {\n return {\n entities: {} as Partial<Record<TKey, TValue>>,\n isLoading: {} as Partial<Record<TKey, boolean>>,\n status: {} as Partial<Record<TKey, ResourceStatus>>,\n errors: {} as Partial<Record<TKey, ResourceErrors>>,\n };\n}\n\nexport function isAnyKeyLoading<TKey extends KeyedResourceKey>(\n loading: Partial<Record<TKey, boolean>>\n): boolean {\n return Object.values(loading).some((value) => value === true);\n}\n","export const CACHE_NO_TIMEOUT = Infinity;\nexport const DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000;\n"],"mappings":";AAcO,SAAS,oBACd,OACuD;AACvD,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,OAAO;AACb,SACE,OAAO,KAAK,aAAa,YACzB,KAAK,aAAa,QAClB,OAAO,KAAK,cAAc,YAC1B,KAAK,cAAc,QACnB,OAAO,KAAK,WAAW,YACvB,KAAK,WAAW,QAChB,OAAO,KAAK,WAAW,YACvB,KAAK,WAAW;AAEpB;AAEO,SAAS,0BAGqB;AACnC,SAAO;AAAA,IACL,UAAU,CAAC;AAAA,IACX,WAAW,CAAC;AAAA,IACZ,QAAQ,CAAC;AAAA,IACT,QAAQ,CAAC;AAAA,EACX;AACF;AAEO,SAAS,gBACd,SACS;AACT,SAAO,OAAO,OAAO,OAAO,EAAE,KAAK,CAAC,UAAU,UAAU,IAAI;AAC9D;;;AClDO,IAAM,mBAAmB;AACzB,IAAM,uBAAuB,IAAI,KAAK;","names":[]}
1
+ {"version":3,"sources":["../src/keyed-resource.ts","../src/constants.ts"],"sourcesContent":["import { ResourceState } from \"./resource-state\";\n\n/**\n * Type for resource keys used to index entities in a {@link KeyedResourceData} slot.\n */\nexport type KeyedResourceKey = string | number;\n\n/**\n * Literal union for resource status: `'Success'` or `'Error'`.\n */\nexport type ResourceStatus = NonNullable<ResourceState<unknown>[\"status\"]>;\n\n/**\n * Normalized error array shape: `Array<{ code: string; message: string }>`.\n */\nexport type ResourceErrors = NonNullable<ResourceState<unknown>[\"errors\"]>;\n\n/**\n * Container for keyed (indexed by ID) resource data.\n *\n * Each entity gets **independent** loading, status, and error tracking.\n * Use this when a single store slot manages multiple entities (e.g. user profiles by ID).\n *\n * @template TKey - The entity identifier type (`string` or `number`).\n * @template TValue - The entity type.\n *\n * @example\n * ```ts\n * interface InvoiceStoreConfig {\n * ITEMS: KeyedResourceData<string, Invoice>;\n * }\n *\n * // Accessing per-key state:\n * const data = store.get('ITEMS')().data;\n * const invoice = data?.entities['inv-123'];\n * const loading = data?.isLoading['inv-123'];\n * const errors = data?.errors['inv-123'];\n * ```\n */\nexport interface KeyedResourceData<TKey extends KeyedResourceKey, TValue> {\n /** Map of entity ID → entity value. */\n entities: Partial<Record<TKey, TValue>>;\n /** Map of entity ID → whether that entity is currently loading. */\n isLoading: Partial<Record<TKey, boolean>>;\n /** Map of entity ID → resource status (`'Success'` or `'Error'`). */\n status: Partial<Record<TKey, ResourceStatus>>;\n /** Map of entity ID → error array for that entity. */\n errors: Partial<Record<TKey, ResourceErrors>>;\n}\n\n/**\n * Type guard that checks whether a value is a {@link KeyedResourceData} structure.\n *\n * @param value - The value to check.\n * @returns `true` if the value has `entities`, `isLoading`, `status`, and `errors` object fields.\n *\n * @example\n * ```ts\n * const state = store.get('ITEMS')();\n * if (isKeyedResourceData(state.data)) {\n * console.log(state.data.entities);\n * }\n * ```\n */\nexport function isKeyedResourceData(\n value: unknown\n): value is KeyedResourceData<KeyedResourceKey, unknown> {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const data = value as Partial<KeyedResourceData<KeyedResourceKey, unknown>>;\n return (\n typeof data.entities === \"object\" &&\n data.entities !== null &&\n typeof data.isLoading === \"object\" &&\n data.isLoading !== null &&\n typeof data.status === \"object\" &&\n data.status !== null &&\n typeof data.errors === \"object\" &&\n data.errors !== null\n );\n}\n\n/**\n * Creates an empty {@link KeyedResourceData} with all maps initialized to `{}`.\n *\n * @template TKey - The entity identifier type.\n * @template TValue - The entity type.\n * @returns A new `KeyedResourceData` with empty `entities`, `isLoading`, `status`, and `errors`.\n *\n * @example\n * ```ts\n * const initial = createKeyedResourceData<string, Invoice>();\n * // { entities: {}, isLoading: {}, status: {}, errors: {} }\n * ```\n */\nexport function createKeyedResourceData<\n TKey extends KeyedResourceKey,\n TValue\n>(): KeyedResourceData<TKey, TValue> {\n return {\n entities: {} as Partial<Record<TKey, TValue>>,\n isLoading: {} as Partial<Record<TKey, boolean>>,\n status: {} as Partial<Record<TKey, ResourceStatus>>,\n errors: {} as Partial<Record<TKey, ResourceErrors>>,\n };\n}\n\n/**\n * Checks whether any entity in a keyed loading map is currently loading.\n *\n * @param loading - The `isLoading` map from a {@link KeyedResourceData}.\n * @returns `true` if at least one key has a value of `true`.\n *\n * @example\n * ```ts\n * const data = store.get('ITEMS')().data;\n * if (data && isAnyKeyLoading(data.isLoading)) {\n * console.log('At least one item is loading');\n * }\n * ```\n */\nexport function isAnyKeyLoading<TKey extends KeyedResourceKey>(\n loading: Partial<Record<TKey, boolean>>\n): boolean {\n return Object.values(loading).some((value) => value === true);\n}\n","/**\n * Sentinel value indicating the cache should never expire.\n * Pass to `@SkipIfCached` `timeoutMs` parameter to disable TTL-based invalidation.\n *\n * @example\n * ```ts\n * @SkipIfCached('LIST', (i) => i.store, false, CACHE_NO_TIMEOUT)\n * ```\n */\nexport const CACHE_NO_TIMEOUT = Infinity;\n\n/**\n * Default cache time-to-live in milliseconds: **5 minutes** (300 000 ms).\n * Used by `@SkipIfCached` when no `timeoutMs` is provided.\n */\nexport const DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000;\n"],"mappings":";AAgEO,SAAS,oBACd,OACuD;AACvD,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,OAAO;AACb,SACE,OAAO,KAAK,aAAa,YACzB,KAAK,aAAa,QAClB,OAAO,KAAK,cAAc,YAC1B,KAAK,cAAc,QACnB,OAAO,KAAK,WAAW,YACvB,KAAK,WAAW,QAChB,OAAO,KAAK,WAAW,YACvB,KAAK,WAAW;AAEpB;AAeO,SAAS,0BAGqB;AACnC,SAAO;AAAA,IACL,UAAU,CAAC;AAAA,IACX,WAAW,CAAC;AAAA,IACZ,QAAQ,CAAC;AAAA,IACT,QAAQ,CAAC;AAAA,EACX;AACF;AAgBO,SAAS,gBACd,SACS;AACT,SAAO,OAAO,OAAO,OAAO,EAAE,KAAK,CAAC,UAAU,UAAU,IAAI;AAC9D;;;ACtHO,IAAM,mBAAmB;AAMzB,IAAM,uBAAuB,IAAI,KAAK;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flurryx/core",
3
- "version": "0.8.0",
3
+ "version": "1.0.0",
4
4
  "description": "Core types and utilities for flurryx state management",
5
5
  "license": "MIT",
6
6
  "type": "module",