@asaidimu/hestia 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +22 -0
- package/index.cjs +8 -0
- package/index.d.cts +920 -0
- package/index.d.mts +920 -0
- package/index.mjs +8 -0
- package/package.json +25 -22
- package/auth/store.ts +0 -75
- package/auth/types.ts +0 -38
- package/blobs/store.ts +0 -209
- package/blobs/types.ts +0 -28
- package/collections/store.ts +0 -88
- package/collections/types.ts +0 -11
- package/container.ts +0 -93
- package/core/client.ts +0 -408
- package/core/collection.ts +0 -145
- package/core/errors.ts +0 -55
- package/core/pager.ts +0 -162
- package/core/types.ts +0 -279
- package/index.ts +0 -39
- package/system/api-keys/store.ts +0 -107
- package/system/api-keys/types.ts +0 -31
- package/system/capabilities/store.ts +0 -67
- package/system/capabilities/types.ts +0 -1
- package/system/identity/store.ts +0 -113
- package/system/identity/types.ts +0 -31
- package/system/policies/store.ts +0 -177
- package/system/policies/types.ts +0 -43
- package/test-setup.ts +0 -53
- package/utils/index.ts +0 -1
- package/utils/pager.ts +0 -230
- package/vitest.config.ts +0 -8
package/core/pager.ts
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import type { QueryDSL, QueryFilter, SortConfiguration } from "@asaidimu/query";
|
|
2
|
-
import { DELETE_SYMBOL, type DataStore } from "@asaidimu/utils-store";
|
|
3
|
-
import type { Page, PagedData, PagerRefreshOptions } from "./types";
|
|
4
|
-
export type { PagerRefreshOptions }
|
|
5
|
-
import { Debouncer } from "@asaidimu/utils-sync";
|
|
6
|
-
|
|
7
|
-
declare function requestIdleCallback(cb: (deadline: { didTimeout: boolean }) => void): void;
|
|
8
|
-
|
|
9
|
-
export interface PageOptions<T extends Record<string, any>> {
|
|
10
|
-
page?: number;
|
|
11
|
-
size?: number;
|
|
12
|
-
sort?: SortConfiguration<T> | SortConfiguration<T>[];
|
|
13
|
-
filter?: QueryFilter<T>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const sentinel = {
|
|
17
|
-
data: [],
|
|
18
|
-
loading: true,
|
|
19
|
-
page: {
|
|
20
|
-
number: 1,
|
|
21
|
-
size: 20,
|
|
22
|
-
count: 0,
|
|
23
|
-
total: 0,
|
|
24
|
-
pages: 1,
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
export function createPagedController<T extends Record<string, any>>(
|
|
28
|
-
collectionName: string,
|
|
29
|
-
store: DataStore<any>,
|
|
30
|
-
options: PageOptions<T>,
|
|
31
|
-
find: (query: QueryDSL<T>) => Promise<Page<T>>,
|
|
32
|
-
): PagedData<T> {
|
|
33
|
-
let currentPage = options.page ?? 1;
|
|
34
|
-
let currentSize = options.size ?? 20;
|
|
35
|
-
let currentSort = options.sort;
|
|
36
|
-
let currentFilter = options.filter;
|
|
37
|
-
const debounce = new Debouncer({ delay: 50 });
|
|
38
|
-
|
|
39
|
-
const CACHE_KEY = `${collectionName}_pager_state_`;
|
|
40
|
-
store.set({
|
|
41
|
-
[CACHE_KEY]: {
|
|
42
|
-
data: [],
|
|
43
|
-
loading: false,
|
|
44
|
-
error: DELETE_SYMBOL,
|
|
45
|
-
page: { number: 1, size: 20, count: 0, total: 0, pages: 1 },
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const buildQuery = (opts?: PagerRefreshOptions): QueryDSL<T> => {
|
|
50
|
-
const page = opts?.page ?? currentPage;
|
|
51
|
-
const size = opts?.size ?? currentSize;
|
|
52
|
-
const query: QueryDSL<T> = {
|
|
53
|
-
pagination: {
|
|
54
|
-
type: "offset",
|
|
55
|
-
offset: (page - 1) * size,
|
|
56
|
-
limit: size,
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
const sort = opts?.sort ?? currentSort;
|
|
60
|
-
if (sort) {
|
|
61
|
-
query.sort = Array.isArray(sort) ? sort : [sort];
|
|
62
|
-
}
|
|
63
|
-
const filter = opts?.filter ?? currentFilter;
|
|
64
|
-
if (filter) {
|
|
65
|
-
query.filters = filter;
|
|
66
|
-
}
|
|
67
|
-
return query;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const load = async (opts?: PagerRefreshOptions) => {
|
|
71
|
-
await store.set({
|
|
72
|
-
[CACHE_KEY]: {
|
|
73
|
-
loading: true,
|
|
74
|
-
error: DELETE_SYMBOL,
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
return await new Promise((resolve) => {
|
|
79
|
-
resolve(
|
|
80
|
-
debounce.do(async () => {
|
|
81
|
-
requestIdleCallback(() => {
|
|
82
|
-
requestIdleCallback(async () => {
|
|
83
|
-
try {
|
|
84
|
-
const result = await find(buildQuery(opts));
|
|
85
|
-
await store.set({ [CACHE_KEY]: result });
|
|
86
|
-
} catch (error) {
|
|
87
|
-
await store.set({
|
|
88
|
-
[CACHE_KEY]: {
|
|
89
|
-
...sentinel,
|
|
90
|
-
error,
|
|
91
|
-
},
|
|
92
|
-
});
|
|
93
|
-
} finally {
|
|
94
|
-
await store.set({
|
|
95
|
-
[CACHE_KEY]: {
|
|
96
|
-
loading: false,
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
}),
|
|
103
|
-
);
|
|
104
|
-
});
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const selector = store.select((s: any) => s[CACHE_KEY]);
|
|
108
|
-
// TODO: Investigate bug. If by any chance a selectors subscription reaches
|
|
109
|
-
// zero, it is auto discarded. This might be a problem if we are holding it
|
|
110
|
-
// fix this
|
|
111
|
-
const unsub = selector.subscribe(() => {});
|
|
112
|
-
|
|
113
|
-
const controller: PagedData<T> = {
|
|
114
|
-
page: () => selector.get() ?? sentinel,
|
|
115
|
-
|
|
116
|
-
navigate: async (page: number) => {
|
|
117
|
-
if (page < 1) throw new Error("Page number must be >= 1");
|
|
118
|
-
currentPage = page;
|
|
119
|
-
await load({
|
|
120
|
-
page,
|
|
121
|
-
});
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
resize: async (size: number, page: number) => {
|
|
125
|
-
if (size < 1) throw new Error("Page size must be >= 1");
|
|
126
|
-
currentSize = size;
|
|
127
|
-
currentPage = page;
|
|
128
|
-
await load();
|
|
129
|
-
},
|
|
130
|
-
|
|
131
|
-
sort: async (sort) => {
|
|
132
|
-
currentSort = Array.isArray(sort) ? sort : [sort];
|
|
133
|
-
currentPage = 1;
|
|
134
|
-
await load();
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
filter: async (filter) => {
|
|
138
|
-
currentFilter = filter;
|
|
139
|
-
currentPage = 1;
|
|
140
|
-
await load();
|
|
141
|
-
},
|
|
142
|
-
|
|
143
|
-
refresh: async (opts) => {
|
|
144
|
-
await Promise.all([
|
|
145
|
-
new Promise((resolve) => setTimeout(resolve, opts?.delay || 0)),
|
|
146
|
-
load(opts),
|
|
147
|
-
]);
|
|
148
|
-
},
|
|
149
|
-
|
|
150
|
-
subscribe: (listener) => {
|
|
151
|
-
return selector.subscribe(listener);
|
|
152
|
-
},
|
|
153
|
-
|
|
154
|
-
invalidate: async () => {
|
|
155
|
-
await store.set({ [CACHE_KEY]: DELETE_SYMBOL });
|
|
156
|
-
unsub();
|
|
157
|
-
},
|
|
158
|
-
|
|
159
|
-
id: () => CACHE_KEY,
|
|
160
|
-
};
|
|
161
|
-
return controller;
|
|
162
|
-
}
|
package/core/types.ts
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import type { QueryFilter, SortConfiguration } from "@asaidimu/query";
|
|
2
|
-
|
|
3
|
-
// Internal metadata managed by Anansi
|
|
4
|
-
interface DocumentMetadata {
|
|
5
|
-
checksum: string; // Integrity hash of the document
|
|
6
|
-
created: string; // Timestamp (often as a numeric string / nanoseconds)
|
|
7
|
-
updated: string; // Timestamp (often as a numeric string / nanoseconds)
|
|
8
|
-
version: number; // Optimistic locking version (increments on each write)
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// The base envelope applied to every single document in the system
|
|
12
|
-
interface BaseDocument {
|
|
13
|
-
_id_: string;
|
|
14
|
-
_metadata_: DocumentMetadata;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Generic Document type: base envelope + your custom properties T
|
|
18
|
-
export type Document<T extends Record<string, any>> = BaseDocument & T;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Provides comprehensive pagination information for a collection of records.
|
|
22
|
-
*/
|
|
23
|
-
export type PaginationInfo = {
|
|
24
|
-
/** The current page number (1-based). */
|
|
25
|
-
number: number;
|
|
26
|
-
|
|
27
|
-
/** The maximum number of items requested per page. */
|
|
28
|
-
size: number;
|
|
29
|
-
|
|
30
|
-
/** The number of items in the current page */
|
|
31
|
-
count: number;
|
|
32
|
-
|
|
33
|
-
/** The total count of all items across all pages. */
|
|
34
|
-
total: number;
|
|
35
|
-
|
|
36
|
-
/** The total number of available pages. */
|
|
37
|
-
pages: number;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Represents a single paginated response containing a list of records and pagination details.
|
|
42
|
-
* @template T The type of the records in the page.
|
|
43
|
-
*/
|
|
44
|
-
export interface Page<T extends Record<string, any>> {
|
|
45
|
-
/** The array of records for the current page. */
|
|
46
|
-
data: Document<T>[];
|
|
47
|
-
|
|
48
|
-
/** Indicates if the data query is currently loading. */
|
|
49
|
-
loading: boolean;
|
|
50
|
-
|
|
51
|
-
/** An error object if the query failed, otherwise `undefined`. */
|
|
52
|
-
error?: any | undefined;
|
|
53
|
-
|
|
54
|
-
/** Pagination metadata providing details about the current page and total collection. */
|
|
55
|
-
page: PaginationInfo;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface PagerRefreshOptions {
|
|
59
|
-
sort?: SortConfiguration | SortConfiguration[];
|
|
60
|
-
filter?: QueryFilter;
|
|
61
|
-
delay?: number;
|
|
62
|
-
size?: number;
|
|
63
|
-
page?: number;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Represents the complete state and control mechanisms for consuming paginated data.
|
|
67
|
-
* @template T The type of the records in the page (`TableRowData` or an extension).
|
|
68
|
-
*/
|
|
69
|
-
export interface PagedData<T extends Record<string, any>> {
|
|
70
|
-
id: () => string
|
|
71
|
-
|
|
72
|
-
/** The current paginated data, or `undefined` if not found or still loading. */
|
|
73
|
-
page: () => Page<T>;
|
|
74
|
-
|
|
75
|
-
/** Function to fetch a specific page of data.
|
|
76
|
-
* @param page The 1-based page number to fetch.
|
|
77
|
-
*/
|
|
78
|
-
navigate: (page: number) => Promise<void>;
|
|
79
|
-
|
|
80
|
-
sort: (sort: SortConfiguration<T> | SortConfiguration<T>[]) => Promise<void>;
|
|
81
|
-
filter: (filter?: QueryFilter<T>) => Promise<void>;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Function to change the page size of the data
|
|
85
|
-
*/
|
|
86
|
-
resize: (size: number, page: number) => Promise<void>;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Function to force a refresh of the current page data, optionally with a delay.
|
|
90
|
-
* @param delay Optional delay in milliseconds before the refresh operation starts.
|
|
91
|
-
*/
|
|
92
|
-
refresh: (opts?: PagerRefreshOptions) => Promise<void>;
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Subscribes to page changes.
|
|
96
|
-
* The callback is invoked immediately with the current page, and then on every
|
|
97
|
-
* subsequent change (navigation, resize, SSE patch, refresh).
|
|
98
|
-
*
|
|
99
|
-
* @param listener A function that receives the current Page<T>.
|
|
100
|
-
* @returns An unsubscribe function.
|
|
101
|
-
*/
|
|
102
|
-
subscribe: (listener: (page: Page<T>) => void) => () => void;
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Invalidates the pagination controller, cleaning up any cached resources
|
|
106
|
-
* (e.g., store subscriptions, in‑flight requests) and removing internal state.
|
|
107
|
-
* After calling `invalidate()`, the controller should no longer be used.
|
|
108
|
-
*
|
|
109
|
-
* This is useful when the component using the pager is unmounted or when
|
|
110
|
-
* you need to reset the pagination state completely.
|
|
111
|
-
*/
|
|
112
|
-
invalidate: () => void;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Represents an event emitted by the store, typically for notifications or state changes.
|
|
117
|
-
*/
|
|
118
|
-
export interface StoreEvent {
|
|
119
|
-
/** The scope of the event, indicating its type and context. Custom scopes are allowed. */
|
|
120
|
-
scope: string;
|
|
121
|
-
/** Optional payload carrying data related to the event. */
|
|
122
|
-
payload?: any;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Defines the core interface for interacting with a remote data store.
|
|
127
|
-
* @template T The type of the records managed by the store, extending Record.
|
|
128
|
-
* @template TFindOptions Options for the find operation.
|
|
129
|
-
* @template TReadOptions Options for the read operation.
|
|
130
|
-
* @template TListOptions Options for the list operation.
|
|
131
|
-
* @template TPageOptions Options for the paging operation.
|
|
132
|
-
* @template TDeleteOptions Options for the delete operation.
|
|
133
|
-
* @template TUpdateOptions Options for the update operation.
|
|
134
|
-
* @template TCreateOptions Options for the create operation.
|
|
135
|
-
* @template TUploadOptions Options for the upload operation.
|
|
136
|
-
* @template TStreamOptions Options for the stream operation.
|
|
137
|
-
*/
|
|
138
|
-
export interface DocumentStore<
|
|
139
|
-
T extends Record<string, any>,
|
|
140
|
-
TFindOptions = Record<string, unknown>,
|
|
141
|
-
TReadOptions = Record<string, unknown>,
|
|
142
|
-
TListOptions = Record<string, unknown>,
|
|
143
|
-
TPageOptions = Record<string, unknown>,
|
|
144
|
-
TDeleteOptions = Record<string, unknown>,
|
|
145
|
-
TUpdateOptions = Record<string, unknown>,
|
|
146
|
-
TCreateOptions = Record<string, unknown>,
|
|
147
|
-
TUploadOptions = Record<string, unknown>,
|
|
148
|
-
TStreamOptions = Record<string, unknown>,
|
|
149
|
-
> {
|
|
150
|
-
/**
|
|
151
|
-
* Finds records based on provided options, returning a paginated result.
|
|
152
|
-
* @param options The options for the find operation.
|
|
153
|
-
* @returns A promise that resolves to a Page of records.
|
|
154
|
-
*/
|
|
155
|
-
find: (options: TFindOptions) => Promise<Page<T>>;
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Reads a single record by its identifier or other read options.
|
|
159
|
-
* @param options The options for the read operation, typically including an ID.
|
|
160
|
-
* @returns A promise that resolves to the record or undefined if not found.
|
|
161
|
-
*/
|
|
162
|
-
read: (options: TReadOptions) => Promise<Document<T> | undefined>;
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Lists records based on provided options, returning a paginated result.
|
|
166
|
-
* @param options The options for the list operation.
|
|
167
|
-
* @returns A promise that resolves to a Page of records.
|
|
168
|
-
*/
|
|
169
|
-
list: (options: TListOptions) => Promise<Page<T>>;
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Deletes a record based on provided options, typically including an ID.
|
|
173
|
-
* @param options The options for the delete operation.
|
|
174
|
-
* @returns A promise that resolves when the deletion is complete.
|
|
175
|
-
*/
|
|
176
|
-
delete: (options: TDeleteOptions) => Promise<void>;
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Updates an existing record.
|
|
180
|
-
* @param props An object containing the ID of the record to update, the partial data, and optional update options.
|
|
181
|
-
* @returns A promise that resolves to the updated record or undefined if not found.
|
|
182
|
-
*/
|
|
183
|
-
update: (props: {
|
|
184
|
-
data: Partial<T>;
|
|
185
|
-
options?: TUpdateOptions;
|
|
186
|
-
}) => Promise<Document<T> | undefined>;
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Creates a new record.
|
|
190
|
-
* @param props An object containing the data for the new record and optional create options.
|
|
191
|
-
* @returns A promise that resolves to the newly created record or undefined if creation failed.
|
|
192
|
-
*/
|
|
193
|
-
create: (props: {
|
|
194
|
-
data: Partial<T>;
|
|
195
|
-
options?: TCreateOptions;
|
|
196
|
-
}) => Promise<Document<T> | undefined>;
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Uploads a file associated with a record. Optionally updates the record with upload details.
|
|
200
|
-
* @param props An object containing the file to upload and optional upload options.
|
|
201
|
-
* @returns A promise that resolves to the updated record after upload or undefined if upload failed.
|
|
202
|
-
*/
|
|
203
|
-
upload: (props: {
|
|
204
|
-
file: File;
|
|
205
|
-
options?: TUploadOptions;
|
|
206
|
-
}) => Promise<Document<T> | undefined>;
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Subscribes to store events for a given scope.
|
|
210
|
-
* @param scope The event scope to subscribe to (e.g., 'todos:created:success', '*').
|
|
211
|
-
* @param callback The function to call when an event matching the scope is received.
|
|
212
|
-
* @returns A promise that resolves to an unsubscribe function. Call this function to stop receiving events.
|
|
213
|
-
*/
|
|
214
|
-
subscribe(
|
|
215
|
-
scope: string,
|
|
216
|
-
callback: (event: StoreEvent) => void,
|
|
217
|
-
): Promise<() => void>;
|
|
218
|
-
/**
|
|
219
|
-
* Notifies the store of an event, which can then be broadcast to subscribers.
|
|
220
|
-
* @param event The StoreEvent to notify.
|
|
221
|
-
* @returns A promise that resolves when the notification has been processed.
|
|
222
|
-
*/
|
|
223
|
-
notify: (event: StoreEvent) => Promise<void>;
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Establishes a stream of records based on provided options.
|
|
227
|
-
* @param options Options for configuring the stream (e.g., batch size, delay, filters).
|
|
228
|
-
* @param onStreamChange A callback function that is called when the stream's status changes.
|
|
229
|
-
* @returns An object containing the async iterable stream, a cancel function, and a status getter.
|
|
230
|
-
*/
|
|
231
|
-
stream: (
|
|
232
|
-
options: TStreamOptions,
|
|
233
|
-
onStreamChange: () => void,
|
|
234
|
-
) => {
|
|
235
|
-
/** An async iterable that yields records as they become available in the stream. */
|
|
236
|
-
stream: () => AsyncIterable<Document<T>>;
|
|
237
|
-
/** A function to call to cancel the ongoing stream. */
|
|
238
|
-
cancel: () => void;
|
|
239
|
-
/** A getter function that returns the current status of the stream ('active', 'cancelled', or 'completed'). */
|
|
240
|
-
status: () => "active" | "cancelled" | "completed";
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Creates a paginated data controller for this store.
|
|
245
|
-
*
|
|
246
|
-
* @param options - The pagination options, whose type is defined by the
|
|
247
|
-
* store's `TPageOptions` generic parameter. This lets you
|
|
248
|
-
* pass any configuration (e.g., filters, sorting, custom
|
|
249
|
-
* pagination metadata) that your store implementation needs.
|
|
250
|
-
* @returns A `PagedData<T>` controller that manages loading, navigation,
|
|
251
|
-
* resizing, and refresh.
|
|
252
|
-
*
|
|
253
|
-
* @example
|
|
254
|
-
* // Define your store with a custom TPageOptions type
|
|
255
|
-
* interface MyTodoStore extends DocumentStore<
|
|
256
|
-
* Todo,
|
|
257
|
-
* FindOptions,
|
|
258
|
-
* ReadOptions,
|
|
259
|
-
* ListOptions,
|
|
260
|
-
* { page: number; size: number; sort?: string; filter?: string }
|
|
261
|
-
* > {}
|
|
262
|
-
*
|
|
263
|
-
* // Use it
|
|
264
|
-
* const todosPaged = myTodoStore.page({
|
|
265
|
-
* page: 1,
|
|
266
|
-
* size: 10,
|
|
267
|
-
* sort: 'createdAt',
|
|
268
|
-
* filter: 'done:false'
|
|
269
|
-
* });
|
|
270
|
-
*
|
|
271
|
-
* // Get current page state
|
|
272
|
-
* const { data, loading, page } = todosPaged.page();
|
|
273
|
-
* console.log(`Page ${page.number} of ${page.pages}`);
|
|
274
|
-
*
|
|
275
|
-
* // Navigate
|
|
276
|
-
* await todosPaged.navigate(2);
|
|
277
|
-
*/
|
|
278
|
-
page(options: TPageOptions): PagedData<T>;
|
|
279
|
-
}
|
package/index.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// Core
|
|
2
|
-
export * from "./core/client"
|
|
3
|
-
export { HestiaCollection } from "./core/collection"
|
|
4
|
-
export * from "./core/errors"
|
|
5
|
-
export * from "./core/types"
|
|
6
|
-
export { createPagedController } from "./core/pager"
|
|
7
|
-
|
|
8
|
-
// Auth
|
|
9
|
-
export * from "./auth/store"
|
|
10
|
-
export * from "./auth/types"
|
|
11
|
-
|
|
12
|
-
// System: identity
|
|
13
|
-
export * from "./system/identity/store"
|
|
14
|
-
export * from "./system/identity/types"
|
|
15
|
-
|
|
16
|
-
// System: api-keys
|
|
17
|
-
export * from "./system/api-keys/store"
|
|
18
|
-
export * from "./system/api-keys/types"
|
|
19
|
-
|
|
20
|
-
// System: policies
|
|
21
|
-
export * from "./system/policies/store"
|
|
22
|
-
export * from "./system/policies/types"
|
|
23
|
-
|
|
24
|
-
// System: logs
|
|
25
|
-
export * from "./system/logs/store"
|
|
26
|
-
export * from "./system/logs/types"
|
|
27
|
-
|
|
28
|
-
// Blobs
|
|
29
|
-
export * from "./blobs/store"
|
|
30
|
-
export * from "./blobs/types"
|
|
31
|
-
|
|
32
|
-
// Collections
|
|
33
|
-
export * from "./collections/store"
|
|
34
|
-
export * from "./collections/types"
|
|
35
|
-
|
|
36
|
-
// Container
|
|
37
|
-
export { HestiaClient } from "./container"
|
|
38
|
-
|
|
39
|
-
export * from "./utils"
|
package/system/api-keys/store.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import type { QueryDSL } from "@asaidimu/query"
|
|
2
|
-
import { HestiaNetworkClient } from "../../core/client"
|
|
3
|
-
import { ReactiveDataStore } from "@asaidimu/utils-store"
|
|
4
|
-
import { createPagedController } from "../../core/pager"
|
|
5
|
-
import type { Document, Page, PagedData, StoreEvent } from "../../core/types"
|
|
6
|
-
import type { DocumentStore } from "../../core/types"
|
|
7
|
-
import type { APIKey, APIKeyWithSecret, CreateKeyRequest, UpdateKeyRequest } from "./types"
|
|
8
|
-
|
|
9
|
-
export class HestiaKeyStore implements DocumentStore<APIKey, QueryDSL<APIKey>, string, QueryDSL<APIKey>, Record<string, unknown>, string, string, Record<string, unknown>> {
|
|
10
|
-
private pager: PagedData<APIKey>
|
|
11
|
-
|
|
12
|
-
constructor(private client: HestiaNetworkClient) {
|
|
13
|
-
this.pager = createPagedController<APIKey>(
|
|
14
|
-
"_api_key_",
|
|
15
|
-
new ReactiveDataStore<any>({}),
|
|
16
|
-
{},
|
|
17
|
-
(query) => this.find(query),
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
private basePath = "/system/apikeys/key"
|
|
22
|
-
|
|
23
|
-
async find(_query?: QueryDSL<APIKey>): Promise<Page<APIKey>> {
|
|
24
|
-
const res = await this.client.get<{
|
|
25
|
-
data: Document<APIKey>[];
|
|
26
|
-
metadata?: { page?: any };
|
|
27
|
-
}>(this.basePath)
|
|
28
|
-
const items = res.data?.data ?? []
|
|
29
|
-
const pageMeta = res.data?.metadata?.page ?? {
|
|
30
|
-
number: 1,
|
|
31
|
-
size: items.length,
|
|
32
|
-
count: items.length,
|
|
33
|
-
total: items.length,
|
|
34
|
-
pages: 1,
|
|
35
|
-
}
|
|
36
|
-
return { data: items, loading: false, page: pageMeta }
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async list(options?: QueryDSL<APIKey>): Promise<Page<APIKey>> {
|
|
40
|
-
return options ? this.find(options) : this.find()
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async read(id: string): Promise<Document<APIKey> | undefined> {
|
|
44
|
-
try {
|
|
45
|
-
const res = await this.client.get<{ data: Document<APIKey> }>(
|
|
46
|
-
`${this.basePath}/${encodeURIComponent(id)}`,
|
|
47
|
-
)
|
|
48
|
-
return res.data?.data
|
|
49
|
-
} catch (err: any) {
|
|
50
|
-
if (err?.code === "SYNC-001-NF") return undefined
|
|
51
|
-
if (err?.code === "INTERNAL_ERROR" && typeof err?.message === "string" && err.message.includes("not found")) return undefined
|
|
52
|
-
throw err
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async create(props: { data: Partial<APIKey> }): Promise<Document<APIKey> | undefined> {
|
|
57
|
-
const res = await this.client.post<{ data: Document<APIKeyWithSecret> }>(
|
|
58
|
-
this.basePath,
|
|
59
|
-
props.data as CreateKeyRequest,
|
|
60
|
-
)
|
|
61
|
-
return res.data!.data
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async update(props: { data: Partial<APIKey>; options?: string }): Promise<Document<APIKey> | undefined> {
|
|
65
|
-
const id = props.options!
|
|
66
|
-
const res = await this.client.patch<{ data: Document<APIKey> }>(
|
|
67
|
-
`${this.basePath}/${encodeURIComponent(id)}`,
|
|
68
|
-
props.data as UpdateKeyRequest,
|
|
69
|
-
)
|
|
70
|
-
return res.data!.data
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async delete(id: string): Promise<void> {
|
|
74
|
-
await this.client.delete(`${this.basePath}/${encodeURIComponent(id)}`)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async upload(_props: { file: File }): Promise<Document<APIKey> | undefined> {
|
|
78
|
-
throw new Error("Upload not supported for API keys")
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async subscribe(_scope: string, _callback: (event: StoreEvent) => void): Promise<() => void> {
|
|
82
|
-
throw new Error("Subscription not supported for API keys")
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async notify(_event: StoreEvent): Promise<void> {
|
|
86
|
-
throw new Error("Notify not supported for API keys")
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
stream(_options: Record<string, unknown>, _onStreamChange: () => void): {
|
|
90
|
-
stream: () => AsyncIterable<Document<APIKey>>;
|
|
91
|
-
cancel: () => void;
|
|
92
|
-
status: () => "active" | "cancelled" | "completed";
|
|
93
|
-
} {
|
|
94
|
-
throw new Error("Stream not supported for API keys")
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
page(_options?: Record<string, unknown>): PagedData<APIKey> {
|
|
98
|
-
return this.pager
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async rotate(id: string): Promise<Document<APIKeyWithSecret>> {
|
|
102
|
-
const res = await this.client.post<{ data: Document<APIKeyWithSecret> }>(
|
|
103
|
-
`${this.basePath}/${encodeURIComponent(id)}`,
|
|
104
|
-
)
|
|
105
|
-
return res.data!.data
|
|
106
|
-
}
|
|
107
|
-
}
|
package/system/api-keys/types.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export interface APIKey {
|
|
2
|
-
_id_: string
|
|
3
|
-
name: string
|
|
4
|
-
prefix: string
|
|
5
|
-
operations: string[]
|
|
6
|
-
status: string
|
|
7
|
-
expiry?: string | null
|
|
8
|
-
environment?: string
|
|
9
|
-
usage?: number
|
|
10
|
-
last_used?: string | null
|
|
11
|
-
_metadata_: Record<string, unknown>
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface APIKeyWithSecret extends APIKey {
|
|
15
|
-
key: string
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface CreateKeyRequest {
|
|
19
|
-
name: string
|
|
20
|
-
environment?: string
|
|
21
|
-
operations?: string[]
|
|
22
|
-
expiry?: string
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface UpdateKeyRequest {
|
|
26
|
-
name?: string
|
|
27
|
-
environment?: string
|
|
28
|
-
operations?: string[]
|
|
29
|
-
status?: "active" | "revoked"
|
|
30
|
-
expiry?: string
|
|
31
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { HestiaNetworkClient } from "../../core/client";
|
|
2
|
-
import type { Document, Page, PagedData, StoreEvent } from "../../core/types";
|
|
3
|
-
import type { DocumentStore } from "../../core/types";
|
|
4
|
-
|
|
5
|
-
export class HestiaCapabilities implements DocumentStore<any, Record<string, unknown>, string, Record<string, unknown>, Record<string, unknown>, string, string, Record<string, unknown>> {
|
|
6
|
-
constructor(
|
|
7
|
-
private client: HestiaNetworkClient,
|
|
8
|
-
) {
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
async find(_query?: Record<string, unknown>): Promise<Page<any>> {
|
|
13
|
-
const res = await this.client.get<{ data: Array<Document<any>> }>(
|
|
14
|
-
`/system/core/docs`,
|
|
15
|
-
);
|
|
16
|
-
const items = res.data?.data ?? [];
|
|
17
|
-
return {
|
|
18
|
-
data: items,
|
|
19
|
-
loading: false,
|
|
20
|
-
page: { number: 1, size: items.length, count: items.length, total: items.length, pages: 1 },
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async read(_id: string): Promise<Document<any> | undefined> {
|
|
25
|
-
throw new Error("Read by ID not supported for capabilities; use find()")
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async create(_props: { data: Partial<any> }): Promise<Document<any> | undefined> {
|
|
29
|
-
throw new Error("Capabilities are read-only")
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async update(_props: { data: Partial<any>; options?: string }): Promise<Document<any> | undefined> {
|
|
33
|
-
throw new Error("Capabilities are read-only")
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async delete(_id: string): Promise<void> {
|
|
37
|
-
throw new Error("Capabilities are read-only")
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async list(_options?: Record<string, unknown>): Promise<Page<any>> {
|
|
41
|
-
return this.find()
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async upload(_props: { file: File }): Promise<Document<any> | undefined> {
|
|
45
|
-
throw new Error("Upload not supported for capabilities")
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async subscribe(_scope: string, _callback: (event: StoreEvent) => void): Promise<() => void> {
|
|
49
|
-
throw new Error("Subscription not supported for capabilities")
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async notify(_event: StoreEvent): Promise<void> {
|
|
53
|
-
throw new Error("Notify not supported for capabilities")
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
stream(_options: Record<string, unknown>, _onStreamChange: () => void): {
|
|
57
|
-
stream: () => AsyncIterable<Document<any>>;
|
|
58
|
-
cancel: () => void;
|
|
59
|
-
status: () => "active" | "cancelled" | "completed";
|
|
60
|
-
} {
|
|
61
|
-
throw new Error("Stream not supported for capabilities")
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
page(_options?: Record<string, unknown>): PagedData<any> {
|
|
65
|
-
throw new Error("Pagination not supported for capabilities")
|
|
66
|
-
}
|
|
67
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// Capabilities types — currently empty
|