@raubjo/architect 0.5.1

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.
Files changed (68) hide show
  1. package/README.md +860 -0
  2. package/package.json +121 -0
  3. package/src/cache/cache.ts +46 -0
  4. package/src/cache/contract.ts +9 -0
  5. package/src/cache/manager.ts +110 -0
  6. package/src/cache/provider.ts +11 -0
  7. package/src/config/contract.ts +63 -0
  8. package/src/config/discovery.ts +99 -0
  9. package/src/config/env.global.d.ts +6 -0
  10. package/src/config/env.ts +68 -0
  11. package/src/config/index.ts +5 -0
  12. package/src/config/provider.ts +17 -0
  13. package/src/config/repository.ts +164 -0
  14. package/src/container/adapters/builtin.ts +323 -0
  15. package/src/container/contract.ts +43 -0
  16. package/src/container/runtime.ts +29 -0
  17. package/src/events/bus.ts +174 -0
  18. package/src/events/concerns/dispatchable.ts +10 -0
  19. package/src/events/provider.ts +9 -0
  20. package/src/events/types.ts +9 -0
  21. package/src/foundation/application.ts +136 -0
  22. package/src/foundation/current-application.ts +20 -0
  23. package/src/index.ts +58 -0
  24. package/src/log/contract.ts +21 -0
  25. package/src/log/drivers/console.ts +54 -0
  26. package/src/log/drivers/null.ts +23 -0
  27. package/src/log/drivers/stack.ts +46 -0
  28. package/src/log/manager.ts +76 -0
  29. package/src/log/provider.ts +11 -0
  30. package/src/react.ts +2 -0
  31. package/src/renderers/adapters/react.tsx +25 -0
  32. package/src/renderers/adapters/solid.tsx +26 -0
  33. package/src/renderers/adapters/svelte.ts +73 -0
  34. package/src/renderers/adapters/vue.ts +22 -0
  35. package/src/renderers/contract.ts +12 -0
  36. package/src/runtimes/react.tsx +81 -0
  37. package/src/runtimes/solid.tsx +47 -0
  38. package/src/runtimes/svelte.ts +17 -0
  39. package/src/runtimes/vue.ts +34 -0
  40. package/src/solid.ts +2 -0
  41. package/src/store/adapters/contract.ts +11 -0
  42. package/src/store/adapters/indexed-db.ts +187 -0
  43. package/src/store/adapters/local-storage.ts +48 -0
  44. package/src/store/adapters/memory.ts +35 -0
  45. package/src/store/manager.ts +68 -0
  46. package/src/store/provider.ts +10 -0
  47. package/src/store/store.ts +1 -0
  48. package/src/support/arr.ts +372 -0
  49. package/src/support/collection.ts +889 -0
  50. package/src/support/facades/cache.ts +6 -0
  51. package/src/support/facades/config.ts +6 -0
  52. package/src/support/facades/event.ts +6 -0
  53. package/src/support/facades/facade.ts +146 -0
  54. package/src/support/facades/index.ts +5 -0
  55. package/src/support/facades/log.ts +6 -0
  56. package/src/support/facades/store.ts +6 -0
  57. package/src/support/fluent.ts +56 -0
  58. package/src/support/globals.ts +8 -0
  59. package/src/support/lazy-collection.ts +341 -0
  60. package/src/support/manager.ts +53 -0
  61. package/src/support/num.ts +50 -0
  62. package/src/support/pipeline.ts +29 -0
  63. package/src/support/service-provider.ts +19 -0
  64. package/src/support/str.ts +682 -0
  65. package/src/svelte.ts +2 -0
  66. package/src/types/peer-deps.d.ts +10 -0
  67. package/src/vue.ts +2 -0
  68. package/tsconfig.json +15 -0
@@ -0,0 +1,68 @@
1
+ import type ConfigRepository from "../config/repository"
2
+ import Manager from "../support/manager"
3
+ import type { Adapter } from "./adapters/contract"
4
+ import IndexedDbAdapter from "./adapters/indexed-db"
5
+ import LocalStorageAdapter from "./adapters/local-storage"
6
+ import MemoryStoreAdapter from "./adapters/memory"
7
+
8
+ type DriverName = "memory" | "local" | "indexed"
9
+
10
+ export default class StoreManager extends Manager<Adapter> implements Adapter {
11
+ protected createDriver(raw: Adapter): Adapter {
12
+ return raw
13
+ }
14
+
15
+ protected driverType(): string {
16
+ return "Store driver"
17
+ }
18
+
19
+ static fromConfig(config: ConfigRepository): StoreManager {
20
+ const adapters = StoreManager.defaultAdapters()
21
+ const active = config.get<string>("store.driver", "memory")
22
+
23
+ return new StoreManager(adapters, active, config)
24
+ }
25
+
26
+ static defaultAdapters(): Record<DriverName, Adapter> {
27
+ const memory = new MemoryStoreAdapter()
28
+ const hasWindow = typeof window !== "undefined"
29
+ const hasLocal = hasWindow && typeof window.localStorage !== "undefined"
30
+ const hasIndexed = typeof globalThis.indexedDB !== "undefined"
31
+
32
+ return {
33
+ memory,
34
+ local: hasLocal ? new LocalStorageAdapter(window.localStorage) : memory,
35
+ indexed: hasIndexed ? new IndexedDbAdapter() : memory,
36
+ }
37
+ }
38
+
39
+ driver(name?: string): Adapter {
40
+ return this.resolve(name ?? this.active)
41
+ }
42
+
43
+ get(key: string): Promise<unknown>
44
+ get<T>(key: string): Promise<T | null>
45
+ get<T = unknown>(key: string): Promise<T | null> {
46
+ return this.driver().get<T>(key)
47
+ }
48
+
49
+ set<T = unknown>(key: string, value: T): Promise<void> {
50
+ return this.driver().set<T>(key, value)
51
+ }
52
+
53
+ has(key: string): Promise<boolean> {
54
+ return this.driver().has(key)
55
+ }
56
+
57
+ delete(key: string): Promise<void> {
58
+ return this.driver().delete(key)
59
+ }
60
+
61
+ clear(): Promise<void> {
62
+ return this.driver().clear()
63
+ }
64
+
65
+ keys(): Promise<string[]> {
66
+ return this.driver().keys()
67
+ }
68
+ }
@@ -0,0 +1,10 @@
1
+ import type ConfigRepository from "../config/repository"
2
+ import type { ServiceProviderContext } from "../support/service-provider"
3
+ import ServiceProvider from "../support/service-provider"
4
+ import StoreManager from "./manager"
5
+
6
+ export class StoreProvider extends ServiceProvider {
7
+ register({ container }: ServiceProviderContext) {
8
+ container.singleton("store", (c) => StoreManager.fromConfig(c.make<ConfigRepository>("config")))
9
+ }
10
+ }
@@ -0,0 +1 @@
1
+ export type { Adapter as StoreAdapter, Contract } from "./adapters/contract"
@@ -0,0 +1,372 @@
1
+ type AnyObject = Record<string, unknown>
2
+
3
+ export function accessible(value: unknown): value is unknown[] | AnyObject {
4
+ return Array.isArray(value) || (typeof value === "object" && value !== null)
5
+ }
6
+
7
+ export function add<T extends AnyObject>(obj: T, key: string, value: unknown): T {
8
+ if (get(obj, key) === null) set(obj as AnyObject, key, value)
9
+ return obj
10
+ }
11
+
12
+ export function collapse<T>(arr: (T | T[])[]): T[] {
13
+ const result: T[] = []
14
+ for (const item of arr) {
15
+ if (Array.isArray(item)) result.push(...item)
16
+ else result.push(item)
17
+ }
18
+ return result
19
+ }
20
+
21
+ export function crossJoin<T>(...arrays: T[][]): T[][] {
22
+ let result: T[][] = [[]]
23
+ for (const arr of arrays) {
24
+ const next: T[][] = []
25
+ for (const existing of result) {
26
+ for (const item of arr) next.push([...existing, item])
27
+ }
28
+ result = next
29
+ }
30
+ return result
31
+ }
32
+
33
+ export function divide<T extends AnyObject>(obj: T): [string[], unknown[]] {
34
+ return [Object.keys(obj), Object.values(obj)]
35
+ }
36
+
37
+ export function dot(obj: AnyObject, prepend = ""): AnyObject {
38
+ const result: AnyObject = {}
39
+ for (const [key, value] of Object.entries(obj)) {
40
+ const fullKey = prepend ? `${prepend}.${key}` : key
41
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
42
+ Object.assign(result, dot(value as AnyObject, fullKey))
43
+ } else {
44
+ result[fullKey] = value
45
+ }
46
+ }
47
+ return result
48
+ }
49
+
50
+ export function undot(obj: AnyObject): AnyObject {
51
+ const result: AnyObject = {}
52
+ for (const [key, value] of Object.entries(obj)) set(result, key, value)
53
+ return result
54
+ }
55
+
56
+ export function every<T>(arr: T[], callback: (item: T, index: number) => boolean): boolean {
57
+ return arr.every(callback)
58
+ }
59
+
60
+ export function except<T extends AnyObject>(obj: T, keys: string[]): AnyObject {
61
+ const result = { ...obj } as AnyObject
62
+ for (const key of keys) forget(result, key)
63
+ return result
64
+ }
65
+
66
+ export function exceptValues<T>(arr: T[], values: T[]): T[] {
67
+ return arr.filter((item) => !values.includes(item))
68
+ }
69
+
70
+ export function exists<T extends AnyObject>(obj: T, key: string): boolean {
71
+ return Object.hasOwn(obj, key)
72
+ }
73
+
74
+ export function first<T>(arr: T[], callback?: (item: T) => boolean, fallback: T | null = null): T | null {
75
+ if (!callback) return arr[0] ?? fallback
76
+ return arr.find(callback) ?? fallback
77
+ }
78
+
79
+ export function last<T>(arr: T[], callback?: (item: T) => boolean, fallback: T | null = null): T | null {
80
+ if (!callback) return arr[arr.length - 1] ?? fallback
81
+ return [...arr].reverse().find(callback) ?? fallback
82
+ }
83
+
84
+ export function flatten(arr: unknown[], depth = Infinity): unknown[] {
85
+ return arr.flat(depth)
86
+ }
87
+
88
+ export function forget(obj: AnyObject, keys: string | string[]): void {
89
+ const keyList = Array.isArray(keys) ? keys : [keys]
90
+ for (const key of keyList) {
91
+ const parts = key.split(".")
92
+ let current: AnyObject = obj
93
+ for (let i = 0; i < parts.length - 1; i++) {
94
+ const part = parts[i]
95
+ if (typeof current[part] !== "object" || current[part] === null) return
96
+ current = current[part] as AnyObject
97
+ }
98
+ delete current[parts[parts.length - 1]]
99
+ }
100
+ }
101
+
102
+ export function get(obj: AnyObject, key: string): unknown
103
+ export function get<T>(obj: AnyObject, key: string, fallback?: T | null): T | null
104
+ export function get<T = unknown>(obj: AnyObject, key: string, fallback: T | null = null): T | null {
105
+ const parts = key.split(".")
106
+ let current: unknown = obj
107
+ for (const part of parts) {
108
+ if (typeof current !== "object" || current === null || !(part in (current as AnyObject))) return fallback
109
+ current = (current as AnyObject)[part]
110
+ }
111
+ return current as T
112
+ }
113
+
114
+ export function has(obj: AnyObject, keys: string | string[]): boolean {
115
+ const keyList = Array.isArray(keys) ? keys : [keys]
116
+ return keyList.every((key) => get(obj, key) !== null)
117
+ }
118
+
119
+ export function hasAll(obj: AnyObject, keys: string[]): boolean {
120
+ return keys.every((key) => get(obj, key) !== null)
121
+ }
122
+
123
+ export function hasAny(obj: AnyObject, keys: string[]): boolean {
124
+ return keys.some((key) => get(obj, key) !== null)
125
+ }
126
+
127
+ export function isList(arr: unknown): boolean {
128
+ return Array.isArray(arr)
129
+ }
130
+
131
+ export function join<T>(arr: T[], glue: string, finalGlue = ""): string {
132
+ if (arr.length === 0) return ""
133
+ if (arr.length === 1) return String(arr[0])
134
+ if (!finalGlue) return arr.join(glue)
135
+ return arr.slice(0, -1).join(glue) + finalGlue + String(arr[arr.length - 1])
136
+ }
137
+
138
+ export function keyBy<T>(arr: T[], key: keyof T): AnyObject {
139
+ const result: AnyObject = {}
140
+ for (const item of arr) result[String(item[key])] = item
141
+ return result
142
+ }
143
+
144
+ export function map<T, U>(arr: T[], callback: (item: T, index: number) => U): U[] {
145
+ return arr.map(callback)
146
+ }
147
+
148
+ export function mapSpread<T extends unknown[], U>(arr: T[], callback: (...args: unknown[]) => U): U[] {
149
+ return arr.map((item) => callback(...(item as unknown[])))
150
+ }
151
+
152
+ export function mapWithKeys<T, U>(arr: T[], callback: (item: T) => [string, U]): Record<string, U> {
153
+ const result: Record<string, U> = {}
154
+ for (const item of arr) {
155
+ const [key, value] = callback(item)
156
+ result[key] = value
157
+ }
158
+ return result
159
+ }
160
+
161
+ export function only<T extends AnyObject>(obj: T, keys: string[]): AnyObject {
162
+ const result: AnyObject = {}
163
+ for (const key of keys) if (key in obj) result[key] = obj[key]
164
+ return result
165
+ }
166
+
167
+ export function onlyValues<T>(arr: T[], values: T[]): T[] {
168
+ return arr.filter((item) => values.includes(item))
169
+ }
170
+
171
+ export function partition<T>(arr: T[], callback: (item: T) => boolean): [T[], T[]] {
172
+ const pass: T[] = []
173
+ const fail: T[] = []
174
+ for (const item of arr) (callback(item) ? pass : fail).push(item)
175
+ return [pass, fail]
176
+ }
177
+
178
+ export function pluck<T>(arr: T[], key: keyof T): unknown[] {
179
+ return arr.map((item) => item[key])
180
+ }
181
+
182
+ export function prepend<T>(arr: T[], value: T): T[] {
183
+ return [value, ...arr]
184
+ }
185
+
186
+ export function prependKeysWith(obj: AnyObject, prefix: string): AnyObject {
187
+ const result: AnyObject = {}
188
+ for (const [key, value] of Object.entries(obj)) result[`${prefix}${key}`] = value
189
+ return result
190
+ }
191
+
192
+ export function pull<T extends AnyObject>(obj: T, key: string, fallback: unknown = null): unknown {
193
+ const value = get(obj, key, fallback as null)
194
+ forget(obj as AnyObject, key)
195
+ return value
196
+ }
197
+
198
+ export function push<T extends AnyObject>(obj: T, key: string, value: unknown): T {
199
+ set(obj as AnyObject, key, value)
200
+ return obj
201
+ }
202
+
203
+ export function query(obj: AnyObject): string {
204
+ return new URLSearchParams(Object.entries(dot(obj)).map(([k, v]) => [k, String(v)])).toString()
205
+ }
206
+
207
+ export function random<T>(arr: T[]): T
208
+ export function random<T>(arr: T[], number: number): T[]
209
+ export function random<T>(arr: T[], number?: number): T | T[] {
210
+ const shuffled = [...arr].sort(() => Math.random() - 0.5)
211
+ if (number === undefined) return shuffled[0]
212
+ return shuffled.slice(0, number)
213
+ }
214
+
215
+ export function reject<T>(arr: T[], callback: (item: T) => boolean): T[] {
216
+ return arr.filter((item) => !callback(item))
217
+ }
218
+
219
+ export function select<T extends AnyObject>(arr: T[], keys: string[]): AnyObject[] {
220
+ return arr.map((item) => only(item, keys))
221
+ }
222
+
223
+ export function set(obj: AnyObject, key: string, value: unknown): AnyObject {
224
+ const parts = key.split(".")
225
+ let current: AnyObject = obj
226
+ for (let i = 0; i < parts.length - 1; i++) {
227
+ const part = parts[i]
228
+ if (typeof current[part] !== "object" || current[part] === null) current[part] = {}
229
+ current = current[part] as AnyObject
230
+ }
231
+ current[parts[parts.length - 1]] = value
232
+ return obj
233
+ }
234
+
235
+ export function shuffle<T>(arr: T[]): T[] {
236
+ const result = [...arr]
237
+ for (let i = result.length - 1; i > 0; i--) {
238
+ const j = Math.floor(Math.random() * (i + 1))
239
+ ;[result[i], result[j]] = [result[j], result[i]]
240
+ }
241
+ return result
242
+ }
243
+
244
+ export function sole<T>(arr: T[], callback: (item: T) => boolean): T {
245
+ const matches = arr.filter(callback)
246
+ if (matches.length !== 1) throw new Error(`Expected exactly one match, found ${matches.length}.`)
247
+ return matches[0]
248
+ }
249
+
250
+ export function some<T>(arr: T[], callback: (item: T) => boolean): boolean {
251
+ return arr.some(callback)
252
+ }
253
+
254
+ export function sort<T>(arr: T[], callback?: (a: T, b: T) => number): T[] {
255
+ return [...arr].sort(callback)
256
+ }
257
+
258
+ export function sortDesc<T>(arr: T[], key?: keyof T): T[] {
259
+ return [...arr].sort((a, b) => {
260
+ const va = key ? a[key] : a
261
+ const vb = key ? b[key] : b
262
+ if (va < vb) return 1
263
+ if (va > vb) return -1
264
+ return 0
265
+ })
266
+ }
267
+
268
+ export function sortRecursive(arr: unknown[]): unknown[] {
269
+ return [...arr]
270
+ .map((item) => {
271
+ if (Array.isArray(item)) return sortRecursive(item)
272
+ if (typeof item === "object" && item !== null) {
273
+ const obj = item as AnyObject
274
+ return Object.fromEntries(
275
+ Object.entries(obj)
276
+ .sort(([a], [b]) => a.localeCompare(b))
277
+ .map(([k, v]) => [k, Array.isArray(v) ? sortRecursive(v) : v]),
278
+ )
279
+ }
280
+ return item
281
+ })
282
+ .sort((a, b) => {
283
+ if (typeof a === "string" && typeof b === "string") return a.localeCompare(b)
284
+ if (typeof a === "number" && typeof b === "number") return a - b
285
+ return 0
286
+ })
287
+ }
288
+
289
+ export function take<T>(arr: T[], limit: number): T[] {
290
+ return limit < 0 ? arr.slice(limit) : arr.slice(0, limit)
291
+ }
292
+
293
+ export function toCssClasses(classes: Record<string, boolean | null | undefined>): string {
294
+ return Object.entries(classes)
295
+ .filter(([, v]) => Boolean(v))
296
+ .map(([k]) => k)
297
+ .join(" ")
298
+ }
299
+
300
+ export function toCssStyles(styles: Record<string, string | null | undefined>): string {
301
+ return Object.entries(styles)
302
+ .filter(([, v]) => v != null)
303
+ .map(([k, v]) => `${k}: ${v};`)
304
+ .join(" ")
305
+ }
306
+
307
+ export function where<T>(arr: T[], callback: (item: T) => boolean): T[] {
308
+ return arr.filter(callback)
309
+ }
310
+
311
+ export function whereNotNull<T>(arr: (T | null | undefined)[]): T[] {
312
+ return arr.filter((item): item is T => item != null)
313
+ }
314
+
315
+ export function wrap<T>(value: T | T[] | null | undefined): T[] {
316
+ if (value === null || value === undefined) return []
317
+ if (Array.isArray(value)) return value
318
+ return [value]
319
+ }
320
+
321
+ export const Arr = {
322
+ accessible,
323
+ add,
324
+ collapse,
325
+ crossJoin,
326
+ divide,
327
+ dot,
328
+ undot,
329
+ every,
330
+ except,
331
+ exceptValues,
332
+ exists,
333
+ first,
334
+ last,
335
+ flatten,
336
+ forget,
337
+ get,
338
+ has,
339
+ hasAll,
340
+ hasAny,
341
+ isList,
342
+ join,
343
+ keyBy,
344
+ map,
345
+ mapSpread,
346
+ mapWithKeys,
347
+ only,
348
+ onlyValues,
349
+ partition,
350
+ pluck,
351
+ prepend,
352
+ prependKeysWith,
353
+ pull,
354
+ push,
355
+ query,
356
+ random,
357
+ reject,
358
+ select,
359
+ set,
360
+ shuffle,
361
+ sole,
362
+ some,
363
+ sort,
364
+ sortDesc,
365
+ sortRecursive,
366
+ take,
367
+ toCssClasses,
368
+ toCssStyles,
369
+ where,
370
+ whereNotNull,
371
+ wrap,
372
+ }