@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.
- package/README.md +860 -0
- package/package.json +121 -0
- package/src/cache/cache.ts +46 -0
- package/src/cache/contract.ts +9 -0
- package/src/cache/manager.ts +110 -0
- package/src/cache/provider.ts +11 -0
- package/src/config/contract.ts +63 -0
- package/src/config/discovery.ts +99 -0
- package/src/config/env.global.d.ts +6 -0
- package/src/config/env.ts +68 -0
- package/src/config/index.ts +5 -0
- package/src/config/provider.ts +17 -0
- package/src/config/repository.ts +164 -0
- package/src/container/adapters/builtin.ts +323 -0
- package/src/container/contract.ts +43 -0
- package/src/container/runtime.ts +29 -0
- package/src/events/bus.ts +174 -0
- package/src/events/concerns/dispatchable.ts +10 -0
- package/src/events/provider.ts +9 -0
- package/src/events/types.ts +9 -0
- package/src/foundation/application.ts +136 -0
- package/src/foundation/current-application.ts +20 -0
- package/src/index.ts +58 -0
- package/src/log/contract.ts +21 -0
- package/src/log/drivers/console.ts +54 -0
- package/src/log/drivers/null.ts +23 -0
- package/src/log/drivers/stack.ts +46 -0
- package/src/log/manager.ts +76 -0
- package/src/log/provider.ts +11 -0
- package/src/react.ts +2 -0
- package/src/renderers/adapters/react.tsx +25 -0
- package/src/renderers/adapters/solid.tsx +26 -0
- package/src/renderers/adapters/svelte.ts +73 -0
- package/src/renderers/adapters/vue.ts +22 -0
- package/src/renderers/contract.ts +12 -0
- package/src/runtimes/react.tsx +81 -0
- package/src/runtimes/solid.tsx +47 -0
- package/src/runtimes/svelte.ts +17 -0
- package/src/runtimes/vue.ts +34 -0
- package/src/solid.ts +2 -0
- package/src/store/adapters/contract.ts +11 -0
- package/src/store/adapters/indexed-db.ts +187 -0
- package/src/store/adapters/local-storage.ts +48 -0
- package/src/store/adapters/memory.ts +35 -0
- package/src/store/manager.ts +68 -0
- package/src/store/provider.ts +10 -0
- package/src/store/store.ts +1 -0
- package/src/support/arr.ts +372 -0
- package/src/support/collection.ts +889 -0
- package/src/support/facades/cache.ts +6 -0
- package/src/support/facades/config.ts +6 -0
- package/src/support/facades/event.ts +6 -0
- package/src/support/facades/facade.ts +146 -0
- package/src/support/facades/index.ts +5 -0
- package/src/support/facades/log.ts +6 -0
- package/src/support/facades/store.ts +6 -0
- package/src/support/fluent.ts +56 -0
- package/src/support/globals.ts +8 -0
- package/src/support/lazy-collection.ts +341 -0
- package/src/support/manager.ts +53 -0
- package/src/support/num.ts +50 -0
- package/src/support/pipeline.ts +29 -0
- package/src/support/service-provider.ts +19 -0
- package/src/support/str.ts +682 -0
- package/src/svelte.ts +2 -0
- package/src/types/peer-deps.d.ts +10 -0
- package/src/vue.ts +2 -0
- 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
|
+
}
|