effect-start 0.25.0 → 0.26.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.
- package/package.json +18 -86
- package/dist/ChildProcess.js +0 -42
- package/dist/Commander.js +0 -410
- package/dist/ContentNegotiation.js +0 -465
- package/dist/Cookies.js +0 -371
- package/dist/Development.js +0 -94
- package/dist/Effectify.js +0 -27
- package/dist/Entity.js +0 -289
- package/dist/Fetch.js +0 -192
- package/dist/FilePathPattern.js +0 -97
- package/dist/FileRouter.js +0 -204
- package/dist/FileRouterCodegen.js +0 -298
- package/dist/FileSystem.js +0 -132
- package/dist/Http.js +0 -107
- package/dist/PathPattern.js +0 -451
- package/dist/PlatformError.js +0 -40
- package/dist/PlatformRuntime.js +0 -71
- package/dist/Route.js +0 -143
- package/dist/RouteBody.js +0 -92
- package/dist/RouteError.js +0 -76
- package/dist/RouteHook.js +0 -64
- package/dist/RouteHttp.js +0 -367
- package/dist/RouteHttpTracer.js +0 -90
- package/dist/RouteMount.js +0 -86
- package/dist/RouteSchema.js +0 -271
- package/dist/RouteSse.js +0 -94
- package/dist/RouteTree.js +0 -119
- package/dist/RouteTrie.js +0 -179
- package/dist/SchemaExtra.js +0 -99
- package/dist/Socket.js +0 -40
- package/dist/SqlIntrospect.js +0 -515
- package/dist/Start.js +0 -79
- package/dist/StartApp.js +0 -3
- package/dist/StreamExtra.js +0 -135
- package/dist/System.js +0 -38
- package/dist/TuplePathPattern.js +0 -74
- package/dist/Unique.js +0 -226
- package/dist/Values.js +0 -52
- package/dist/bun/BunBundle.js +0 -186
- package/dist/bun/BunChildProcessSpawner.js +0 -142
- package/dist/bun/BunImportTrackerPlugin.js +0 -91
- package/dist/bun/BunRoute.js +0 -157
- package/dist/bun/BunRuntime.js +0 -41
- package/dist/bun/BunServer.js +0 -285
- package/dist/bun/BunVirtualFilesPlugin.js +0 -54
- package/dist/bun/_BunEnhancedResolve.js +0 -127
- package/dist/bun/index.js +0 -5
- package/dist/bundler/Bundle.js +0 -92
- package/dist/bundler/BundleFiles.js +0 -154
- package/dist/bundler/BundleRoute.js +0 -62
- package/dist/client/Overlay.js +0 -33
- package/dist/client/ScrollState.js +0 -106
- package/dist/client/index.js +0 -97
- package/dist/console/Console.js +0 -42
- package/dist/console/ConsoleErrors.js +0 -211
- package/dist/console/ConsoleLogger.js +0 -56
- package/dist/console/ConsoleMetrics.js +0 -72
- package/dist/console/ConsoleProcess.js +0 -59
- package/dist/console/ConsoleStore.js +0 -72
- package/dist/console/ConsoleTracer.js +0 -107
- package/dist/console/Simulation.js +0 -784
- package/dist/console/index.js +0 -3
- package/dist/console/routes/tree.js +0 -30
- package/dist/datastar/actions/fetch.js +0 -536
- package/dist/datastar/actions/peek.js +0 -13
- package/dist/datastar/actions/setAll.js +0 -19
- package/dist/datastar/actions/toggleAll.js +0 -19
- package/dist/datastar/attributes/attr.js +0 -49
- package/dist/datastar/attributes/bind.js +0 -194
- package/dist/datastar/attributes/class.js +0 -54
- package/dist/datastar/attributes/computed.js +0 -25
- package/dist/datastar/attributes/effect.js +0 -10
- package/dist/datastar/attributes/indicator.js +0 -33
- package/dist/datastar/attributes/init.js +0 -27
- package/dist/datastar/attributes/jsonSignals.js +0 -33
- package/dist/datastar/attributes/on.js +0 -81
- package/dist/datastar/attributes/onIntersect.js +0 -53
- package/dist/datastar/attributes/onInterval.js +0 -31
- package/dist/datastar/attributes/onSignalPatch.js +0 -51
- package/dist/datastar/attributes/ref.js +0 -11
- package/dist/datastar/attributes/show.js +0 -32
- package/dist/datastar/attributes/signals.js +0 -18
- package/dist/datastar/attributes/style.js +0 -57
- package/dist/datastar/attributes/text.js +0 -29
- package/dist/datastar/engine.js +0 -1145
- package/dist/datastar/index.js +0 -25
- package/dist/datastar/utils.js +0 -250
- package/dist/datastar/watchers/patchElements.js +0 -486
- package/dist/datastar/watchers/patchSignals.js +0 -14
- package/dist/experimental/EncryptedCookies.js +0 -328
- package/dist/experimental/index.js +0 -1
- package/dist/hyper/Hyper.js +0 -28
- package/dist/hyper/HyperHtml.js +0 -165
- package/dist/hyper/HyperNode.js +0 -13
- package/dist/hyper/HyperRoute.js +0 -45
- package/dist/hyper/html.js +0 -30
- package/dist/hyper/index.js +0 -5
- package/dist/hyper/jsx-runtime.js +0 -14
- package/dist/index.js +0 -8
- package/dist/node/NodeFileSystem.js +0 -675
- package/dist/node/NodeUtils.js +0 -23
- package/dist/sql/Sql.js +0 -8
- package/dist/sql/bun/index.js +0 -142
- package/dist/sql/index.js +0 -1
- package/dist/sql/libsql/index.js +0 -156
- package/dist/sql/mssql/docker.js +0 -110
- package/dist/sql/mssql/index.js +0 -194
- package/dist/testing/TestLogger.js +0 -42
- package/dist/testing/index.js +0 -2
- package/dist/testing/utils.js +0 -61
- package/dist/x/cloudflare/CloudflareTunnel.js +0 -63
- package/dist/x/cloudflare/index.js +0 -1
- package/dist/x/tailscale/TailscaleTunnel.js +0 -94
- package/dist/x/tailscale/index.js +0 -1
- package/dist/x/tailwind/TailwindPlugin.js +0 -294
- package/dist/x/tailwind/compile.js +0 -210
- package/dist/x/tailwind/plugin.js +0 -17
package/dist/Start.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import * as Context from "effect/Context"
|
|
2
|
-
import * as Deferred from "effect/Deferred"
|
|
3
|
-
import * as Effect from "effect/Effect"
|
|
4
|
-
import * as Function from "effect/Function"
|
|
5
|
-
import * as Layer from "effect/Layer"
|
|
6
|
-
import * as BunRuntime from "./bun/BunRuntime.js"
|
|
7
|
-
import * as BunServer from "./bun/BunServer.js"
|
|
8
|
-
import * as NodeFileSystem from "./node/NodeFileSystem.js"
|
|
9
|
-
import * as BunChildProcessSpawner from "./bun/BunChildProcessSpawner.js"
|
|
10
|
-
import * as StartApp from "./StartApp.js"
|
|
11
|
-
|
|
12
|
-
export function layer(
|
|
13
|
-
...layers
|
|
14
|
-
) {
|
|
15
|
-
return Layer.mergeAll(...layers)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Bundles layers together, wiring their dependencies automatically.
|
|
20
|
-
*
|
|
21
|
-
* Equivalent to chaining `Layer.provide` calls, but more concise.
|
|
22
|
-
*
|
|
23
|
-
* **Ordering: dependents first, dependencies last.**
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```ts
|
|
27
|
-
* // UserRepo needs Database, Database needs Logger
|
|
28
|
-
* const AppLayer = Start.pack(
|
|
29
|
-
* UserRepoLive, // needs Database, Logger
|
|
30
|
-
* DatabaseLive, // needs Logger
|
|
31
|
-
* LoggerLive, // no deps
|
|
32
|
-
* )
|
|
33
|
-
* // Result: Layer<UserRepo | Database | Logger, never, never>
|
|
34
|
-
* ```
|
|
35
|
-
*
|
|
36
|
-
* @since 1.0.0
|
|
37
|
-
* @category constructors
|
|
38
|
-
*/
|
|
39
|
-
export function pack(
|
|
40
|
-
...layers
|
|
41
|
-
) {
|
|
42
|
-
const layerArray = layers
|
|
43
|
-
const result = layerArray.reduce(
|
|
44
|
-
(acc, layer) => Layer.provideMerge(acc, layer),
|
|
45
|
-
Layer.succeedContext(Context.empty()),
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
return result
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export const Live = Layer.mergeAll(
|
|
52
|
-
NodeFileSystem.layer,
|
|
53
|
-
BunChildProcessSpawner.layer,
|
|
54
|
-
Layer.effect(
|
|
55
|
-
StartApp.StartApp,
|
|
56
|
-
Deferred.make().pipe(Effect.map((server) => ({ server }))),
|
|
57
|
-
),
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
export function serve(
|
|
61
|
-
load,
|
|
62
|
-
) {
|
|
63
|
-
const appLayer = Function.pipe(
|
|
64
|
-
Effect.tryPromise(load),
|
|
65
|
-
Effect.map((v) => v.default),
|
|
66
|
-
Effect.orDie,
|
|
67
|
-
Layer.unwrapEffect,
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
const appLayerResolved = Function.pipe(appLayer, Layer.provideMerge(Live))
|
|
71
|
-
|
|
72
|
-
const composed = Function.pipe(
|
|
73
|
-
BunServer.layerStart(),
|
|
74
|
-
BunServer.withLogAddress,
|
|
75
|
-
Layer.provide(appLayerResolved),
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
return Function.pipe(composed, Layer.launch, BunRuntime.runMain)
|
|
79
|
-
}
|
package/dist/StartApp.js
DELETED
package/dist/StreamExtra.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import * as Cause from "effect/Cause"
|
|
2
|
-
import * as Effect from "effect/Effect"
|
|
3
|
-
import * as Fiber from "effect/Fiber"
|
|
4
|
-
import * as Function from "effect/Function"
|
|
5
|
-
import * as Predicate from "effect/Predicate"
|
|
6
|
-
import * as Runtime from "effect/Runtime"
|
|
7
|
-
import * as Stream from "effect/Stream"
|
|
8
|
-
|
|
9
|
-
export const isStream = (u) =>
|
|
10
|
-
Predicate.hasProperty(u, Stream.StreamTypeId)
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Patched version of original Stream.toReadableStreamRuntime (v3.14.4) to
|
|
14
|
-
* fix an issue in Bun when native stream controller stops working when request
|
|
15
|
-
* is terminated by the client:
|
|
16
|
-
*
|
|
17
|
-
* TypeError: Value of "this" must be of type ReadableStreamDefaultController
|
|
18
|
-
*
|
|
19
|
-
* See related issues:
|
|
20
|
-
* https://github.com/Effect-TS/effect/issues/4538
|
|
21
|
-
* https://github.com/oven-sh/bun/issues/17837
|
|
22
|
-
*/
|
|
23
|
-
export const toReadableStreamRuntimePatched = Function.dual(
|
|
24
|
-
(args) => Predicate.hasProperty(args[0], Stream.StreamTypeId) || Effect.isEffect(args[0]),
|
|
25
|
-
(
|
|
26
|
-
self,
|
|
27
|
-
runtime,
|
|
28
|
-
options,
|
|
29
|
-
) => {
|
|
30
|
-
const runFork = Runtime.runFork(runtime)
|
|
31
|
-
let currentResolve = undefined
|
|
32
|
-
let fiber = undefined
|
|
33
|
-
const latch = Effect.unsafeMakeLatch(false)
|
|
34
|
-
|
|
35
|
-
return new ReadableStream(
|
|
36
|
-
{
|
|
37
|
-
start(controller) {
|
|
38
|
-
fiber = runFork(
|
|
39
|
-
Stream.runForEachChunk(self, (chunk) =>
|
|
40
|
-
latch.whenOpen(
|
|
41
|
-
Effect.sync(() => {
|
|
42
|
-
latch.unsafeClose()
|
|
43
|
-
try {
|
|
44
|
-
for (const item of chunk) {
|
|
45
|
-
controller.enqueue(item)
|
|
46
|
-
}
|
|
47
|
-
} catch (e) {
|
|
48
|
-
if (
|
|
49
|
-
(e).message ===
|
|
50
|
-
`Value of "this" must be of type ReadableStreamDefaultController`
|
|
51
|
-
) {
|
|
52
|
-
// Do nothing when this happens in Bun.
|
|
53
|
-
} else {
|
|
54
|
-
throw e
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
currentResolve()
|
|
58
|
-
currentResolve = undefined
|
|
59
|
-
}),
|
|
60
|
-
),
|
|
61
|
-
),
|
|
62
|
-
)
|
|
63
|
-
// --- CHANGES HERE ---
|
|
64
|
-
// In original code, we had fiber.addObserver here that called
|
|
65
|
-
// error() or close() on controller. This patched version removes it.
|
|
66
|
-
},
|
|
67
|
-
pull() {
|
|
68
|
-
return new Promise((resolve) => {
|
|
69
|
-
currentResolve = resolve
|
|
70
|
-
Effect.runSync(latch.open)
|
|
71
|
-
})
|
|
72
|
-
},
|
|
73
|
-
cancel() {
|
|
74
|
-
if (!fiber) return
|
|
75
|
-
return Effect.runPromise(Effect.asVoid(Fiber.interrupt(fiber)))
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
options?.strategy,
|
|
79
|
-
)
|
|
80
|
-
},
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
export const toReadableStreamRuntimePatched2 = Function.dual(
|
|
84
|
-
(args) => Predicate.hasProperty(args[0], Stream.StreamTypeId) || Effect.isEffect(args[0]),
|
|
85
|
-
(
|
|
86
|
-
self,
|
|
87
|
-
runtime,
|
|
88
|
-
options,
|
|
89
|
-
) => {
|
|
90
|
-
const runSync = Runtime.runSync(runtime)
|
|
91
|
-
const runFork = Runtime.runFork(runtime)
|
|
92
|
-
let currentResolve = undefined
|
|
93
|
-
let fiber = undefined
|
|
94
|
-
const latch = Effect.unsafeMakeLatch(false)
|
|
95
|
-
|
|
96
|
-
return new ReadableStream(
|
|
97
|
-
{
|
|
98
|
-
start(controller) {
|
|
99
|
-
fiber = runFork(
|
|
100
|
-
Stream.runForEachChunk(self, (chunk) =>
|
|
101
|
-
latch.whenOpen(
|
|
102
|
-
Effect.sync(() => {
|
|
103
|
-
latch.unsafeClose()
|
|
104
|
-
for (const item of chunk) {
|
|
105
|
-
controller.enqueue(item)
|
|
106
|
-
}
|
|
107
|
-
currentResolve()
|
|
108
|
-
currentResolve = undefined
|
|
109
|
-
}),
|
|
110
|
-
),
|
|
111
|
-
),
|
|
112
|
-
)
|
|
113
|
-
fiber.addObserver((exit) => {
|
|
114
|
-
if (exit._tag === "Failure") {
|
|
115
|
-
controller.error(Cause.squash(exit.cause))
|
|
116
|
-
} else {
|
|
117
|
-
controller.close()
|
|
118
|
-
}
|
|
119
|
-
})
|
|
120
|
-
},
|
|
121
|
-
pull() {
|
|
122
|
-
return new Promise((resolve) => {
|
|
123
|
-
currentResolve = resolve
|
|
124
|
-
Effect.runSync(latch.open)
|
|
125
|
-
})
|
|
126
|
-
},
|
|
127
|
-
cancel() {
|
|
128
|
-
if (!fiber) return
|
|
129
|
-
return Effect.runPromise(Effect.asVoid(Fiber.interrupt(fiber)))
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
options?.strategy,
|
|
133
|
-
)
|
|
134
|
-
},
|
|
135
|
-
)
|
package/dist/System.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import * as Effect from "effect/Effect"
|
|
2
|
-
|
|
3
|
-
import * as ChildProcess from "./ChildProcess.js"
|
|
4
|
-
import * as PlatformError from "./PlatformError.js"
|
|
5
|
-
|
|
6
|
-
export const cwd = Effect.sync(() => process.cwd())
|
|
7
|
-
|
|
8
|
-
export const which = (name) =>
|
|
9
|
-
Effect.flatMap(
|
|
10
|
-
Effect.try({
|
|
11
|
-
try: () => Bun.which(name),
|
|
12
|
-
catch: (err) =>
|
|
13
|
-
new PlatformError.SystemError({
|
|
14
|
-
reason: "Unknown",
|
|
15
|
-
module: "System",
|
|
16
|
-
method: "which",
|
|
17
|
-
description: err instanceof Error ? err.message : `Failed to look up "${name}"`,
|
|
18
|
-
cause: err,
|
|
19
|
-
}),
|
|
20
|
-
}),
|
|
21
|
-
(path) =>
|
|
22
|
-
path === null
|
|
23
|
-
? Effect.fail(
|
|
24
|
-
new PlatformError.SystemError({
|
|
25
|
-
reason: "NotFound",
|
|
26
|
-
module: "System",
|
|
27
|
-
method: "which",
|
|
28
|
-
description: `Executable not found: "${name}"`,
|
|
29
|
-
}),
|
|
30
|
-
)
|
|
31
|
-
: Effect.succeed(path),
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
export const spawn = (
|
|
35
|
-
command,
|
|
36
|
-
args,
|
|
37
|
-
options,
|
|
38
|
-
) => ChildProcess.spawn(ChildProcess.make(command, args, options))
|
package/dist/TuplePathPattern.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export function format(tuple) {
|
|
3
|
-
return ("/" +
|
|
4
|
-
tuple
|
|
5
|
-
.map((el) => {
|
|
6
|
-
if (typeof el === "string") return el
|
|
7
|
-
if (Array.isArray(el[0])) return "[[" + el[0][0] + "]]"
|
|
8
|
-
const [name, suffix, prefix] = el
|
|
9
|
-
return (prefix ?? "") + "[" + name + "]" + (suffix ?? "")
|
|
10
|
-
})
|
|
11
|
-
.join("/"))
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function toColon(tuple) {
|
|
15
|
-
return (
|
|
16
|
-
"/" +
|
|
17
|
-
tuple
|
|
18
|
-
.map((el) => {
|
|
19
|
-
if (typeof el === "string") return el
|
|
20
|
-
if (Array.isArray(el[0])) return "*"
|
|
21
|
-
const [name, suffix, prefix] = el
|
|
22
|
-
return (prefix ?? "") + ":" + name + (suffix ?? "")
|
|
23
|
-
})
|
|
24
|
-
.join("/")
|
|
25
|
-
)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export const toHono = toColon
|
|
29
|
-
|
|
30
|
-
export function toExpress(tuple) {
|
|
31
|
-
return (
|
|
32
|
-
"/" +
|
|
33
|
-
tuple
|
|
34
|
-
.map((el) => {
|
|
35
|
-
if (typeof el === "string") return el
|
|
36
|
-
if (Array.isArray(el[0])) return "*" + el[0][0]
|
|
37
|
-
const [name, suffix, prefix] = el
|
|
38
|
-
return (prefix ?? "") + ":" + name + (suffix ?? "")
|
|
39
|
-
})
|
|
40
|
-
.join("/")
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export const toEffect = toColon
|
|
45
|
-
|
|
46
|
-
export function toURLPattern(tuple) {
|
|
47
|
-
return (
|
|
48
|
-
"/" +
|
|
49
|
-
tuple
|
|
50
|
-
.map((el) => {
|
|
51
|
-
if (typeof el === "string") return el
|
|
52
|
-
if (Array.isArray(el[0])) return ":" + el[0][0] + "+"
|
|
53
|
-
const [name, suffix, prefix] = el
|
|
54
|
-
return (prefix ?? "") + ":" + name + (suffix ?? "")
|
|
55
|
-
})
|
|
56
|
-
.join("/")
|
|
57
|
-
)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function toRemix(tuple) {
|
|
61
|
-
return (
|
|
62
|
-
"/" +
|
|
63
|
-
tuple
|
|
64
|
-
.map((el) => {
|
|
65
|
-
if (typeof el === "string") return el
|
|
66
|
-
if (Array.isArray(el[0])) return "$"
|
|
67
|
-
const [name, suffix, prefix] = el
|
|
68
|
-
return (prefix ?? "") + "$" + name + (suffix ?? "")
|
|
69
|
-
})
|
|
70
|
-
.join("/")
|
|
71
|
-
)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export const toBun = toColon
|
package/dist/Unique.js
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
export const ALPHABET_BASE32_CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
|
|
2
|
-
export const ALPHABET_BASE32_RFC4648 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
|
|
3
|
-
export const ALPHABET_BASE64_URL =
|
|
4
|
-
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
|
|
5
|
-
export const ALPHABET_HEX = "0123456789abcdef"
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Generate a random string for ids, session tokens, and API keys.
|
|
9
|
-
* It uses human-friendly crockford base32 encoding (5 bit of entropy per char)
|
|
10
|
-
*
|
|
11
|
-
* Minimal recommended length:
|
|
12
|
-
* - public ids: 16 chars (~80 bits)
|
|
13
|
-
* - API keys: 32 chars (~160 bits)
|
|
14
|
-
* - session tokens: 32-40 chars (~160-200 bits)
|
|
15
|
-
*/
|
|
16
|
-
export function token(length = 32) {
|
|
17
|
-
if (length <= 0) return ""
|
|
18
|
-
|
|
19
|
-
const buf = new Uint8Array(length)
|
|
20
|
-
crypto.getRandomValues(buf)
|
|
21
|
-
|
|
22
|
-
let result = ""
|
|
23
|
-
for (let i = 0; i < buf.length; i++) {
|
|
24
|
-
result += ALPHABET_BASE32_CROCKFORD[buf[i] & 31]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return result
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function bytes(length) {
|
|
31
|
-
const buf = new Uint8Array(length)
|
|
32
|
-
crypto.getRandomValues(buf)
|
|
33
|
-
return buf
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const UUID_NIL = "00000000-0000-0000-0000-000000000000"
|
|
37
|
-
|
|
38
|
-
export function uuid4() {
|
|
39
|
-
return formatUuid(uuid4bytes())
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function uuid7(time = Date.now()) {
|
|
43
|
-
return formatUuid(uuid7Bytes(time))
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function uuid4bytes() {
|
|
47
|
-
const buf = bytes(16)
|
|
48
|
-
buf[6] = (buf[6] & 0x0f) | 0x40 // version 4
|
|
49
|
-
buf[8] = (buf[8] & 0x3f) | 0x80 // variant
|
|
50
|
-
|
|
51
|
-
return buf
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Decode a 48-bit Unix timestamp (ms) from UUID7 or ULID.
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* const bytes = Unique.uuid7Bytes()
|
|
59
|
-
* const timestamp = Unique.toTimestamp(bytes)
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* const bytes = Unique.ulidBytes()
|
|
63
|
-
* const timestamp = Unique.toTimestamp(bytes)
|
|
64
|
-
*/
|
|
65
|
-
export function toTimestamp(bytes) {
|
|
66
|
-
if (bytes.length < 6) return 0
|
|
67
|
-
|
|
68
|
-
return (
|
|
69
|
-
bytes[0] * 0x10000000000 +
|
|
70
|
-
bytes[1] * 0x100000000 +
|
|
71
|
-
bytes[2] * 0x1000000 +
|
|
72
|
-
bytes[3] * 0x10000 +
|
|
73
|
-
bytes[4] * 0x100 +
|
|
74
|
-
bytes[5]
|
|
75
|
-
)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function uuid7Bytes(time = Date.now()) {
|
|
79
|
-
const buf = new Uint8Array(16)
|
|
80
|
-
const timestamp = BigInt(toSafeTime(time))
|
|
81
|
-
|
|
82
|
-
// 48-bit timestamp (6 bytes)
|
|
83
|
-
buf[0] = Number((timestamp >> 40n) & 0xffn)
|
|
84
|
-
buf[1] = Number((timestamp >> 32n) & 0xffn)
|
|
85
|
-
buf[2] = Number((timestamp >> 24n) & 0xffn)
|
|
86
|
-
buf[3] = Number((timestamp >> 16n) & 0xffn)
|
|
87
|
-
buf[4] = Number((timestamp >> 8n) & 0xffn)
|
|
88
|
-
buf[5] = Number(timestamp & 0xffn)
|
|
89
|
-
|
|
90
|
-
// 12-bit random A (1.5 bytes)
|
|
91
|
-
crypto.getRandomValues(buf.subarray(6, 8))
|
|
92
|
-
buf[6] = (buf[6] & 0x0f) | 0x70 // version 7
|
|
93
|
-
|
|
94
|
-
// 2-bit variant + 62-bit random B (8 bytes)
|
|
95
|
-
crypto.getRandomValues(buf.subarray(8, 16))
|
|
96
|
-
buf[8] = (buf[8] & 0x3f) | 0x80 // variant
|
|
97
|
-
|
|
98
|
-
return buf
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Convert UUID bytes to canonical (RFC9562) representation.
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* Unique.formatUuid(new Uint8Array(16))
|
|
106
|
-
*/
|
|
107
|
-
export function formatUuid(bytes) {
|
|
108
|
-
if (bytes.length === 0) return ""
|
|
109
|
-
|
|
110
|
-
let result = ""
|
|
111
|
-
|
|
112
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
113
|
-
const byte = bytes[i]
|
|
114
|
-
result += ALPHABET_HEX[(byte >> 4) & 0x0f]
|
|
115
|
-
result += ALPHABET_HEX[byte & 0x0f]
|
|
116
|
-
|
|
117
|
-
if (i === 3 || i === 5 || i === 7 || i === 9) result += "-"
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return result
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export function ulid(time = Date.now()) {
|
|
124
|
-
const bytes = ulidBytes(time)
|
|
125
|
-
return formatUlid(bytes)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function ulidBytes(time = Date.now()) {
|
|
129
|
-
const buf = new Uint8Array(16)
|
|
130
|
-
const timestamp = BigInt(toSafeTime(time))
|
|
131
|
-
|
|
132
|
-
buf[0] = Number((timestamp >> 40n) & 0xffn)
|
|
133
|
-
buf[1] = Number((timestamp >> 32n) & 0xffn)
|
|
134
|
-
buf[2] = Number((timestamp >> 24n) & 0xffn)
|
|
135
|
-
buf[3] = Number((timestamp >> 16n) & 0xffn)
|
|
136
|
-
buf[4] = Number((timestamp >> 8n) & 0xffn)
|
|
137
|
-
buf[5] = Number(timestamp & 0xffn)
|
|
138
|
-
|
|
139
|
-
crypto.getRandomValues(buf.subarray(6, 16))
|
|
140
|
-
|
|
141
|
-
return buf
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function formatUlid(bytes) {
|
|
145
|
-
if (bytes.length !== 16) return ""
|
|
146
|
-
|
|
147
|
-
const timestamp = toTimestamp(bytes)
|
|
148
|
-
const timePart = encodeUlidTime(timestamp)
|
|
149
|
-
const randomPart = toBase32(bytes.subarray(6, 16))
|
|
150
|
-
|
|
151
|
-
return `${timePart}${randomPart}`
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function encodeUlidTime(time) {
|
|
155
|
-
let value = BigInt(time)
|
|
156
|
-
const result = Array.from({ length: 10 })
|
|
157
|
-
|
|
158
|
-
for (let i = 9; i >= 0; i--) {
|
|
159
|
-
result[i] = ALPHABET_BASE32_CROCKFORD[Number(value & 31n)]
|
|
160
|
-
value >>= 5n
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return result.join("")
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function toSafeTime(time) {
|
|
167
|
-
if (!Number.isFinite(time)) return 0
|
|
168
|
-
|
|
169
|
-
return Math.max(0, Math.trunc(time))
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Generate a nanoid-style random string.
|
|
174
|
-
*
|
|
175
|
-
* FUN_FACT: Original nanoid implementation uses base64url alphabet
|
|
176
|
-
* with non-standard custom order where charater form common words found
|
|
177
|
-
* in source code (like use, random, strict) to make gzip/brotli more efficient.
|
|
178
|
-
* It's qt lil opt from the times where web developers
|
|
179
|
-
* were competing to have the smallest possible bundle size.
|
|
180
|
-
*/
|
|
181
|
-
export function nanoid(size = 21, alphabet = ALPHABET_BASE64_URL) {
|
|
182
|
-
if (size <= 0 || alphabet.length === 0) return ""
|
|
183
|
-
|
|
184
|
-
const length = alphabet.length
|
|
185
|
-
const mask = (2 << Math.floor(Math.log2(length - 1))) - 1
|
|
186
|
-
const step = Math.ceil((1.6 * mask * size) / length)
|
|
187
|
-
|
|
188
|
-
let id = ""
|
|
189
|
-
while (id.length < size) {
|
|
190
|
-
const bytes = new Uint8Array(step)
|
|
191
|
-
crypto.getRandomValues(bytes)
|
|
192
|
-
|
|
193
|
-
for (let i = 0; i < step && id.length < size; i++) {
|
|
194
|
-
const index = bytes[i] & mask
|
|
195
|
-
if (index < length) id += alphabet[index]
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
return id
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function toBase32(bytes, alphabet = ALPHABET_BASE32_CROCKFORD) {
|
|
202
|
-
if (bytes.length === 0) return ""
|
|
203
|
-
|
|
204
|
-
let result = ""
|
|
205
|
-
let buffer = 0
|
|
206
|
-
let bits = 0
|
|
207
|
-
|
|
208
|
-
for (const byte of bytes) {
|
|
209
|
-
buffer = (buffer << 8) | byte
|
|
210
|
-
bits += 8
|
|
211
|
-
|
|
212
|
-
while (bits >= 5) {
|
|
213
|
-
bits -= 5
|
|
214
|
-
const index = (buffer >> bits) & 31
|
|
215
|
-
result += alphabet[index]
|
|
216
|
-
buffer &= (1 << bits) - 1
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (bits > 0) {
|
|
221
|
-
const index = (buffer << (5 - bits)) & 31
|
|
222
|
-
result += alphabet[index]
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return result
|
|
226
|
-
}
|
package/dist/Values.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export function isPlainObject(value) {
|
|
4
|
-
if (value === null || typeof value !== "object") {
|
|
5
|
-
return false
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
// Check for built-in types and web APIs
|
|
9
|
-
if (
|
|
10
|
-
ArrayBuffer.isView(value) ||
|
|
11
|
-
value instanceof ArrayBuffer ||
|
|
12
|
-
value instanceof Blob ||
|
|
13
|
-
value instanceof FormData ||
|
|
14
|
-
value instanceof URLSearchParams ||
|
|
15
|
-
value instanceof ReadableStream ||
|
|
16
|
-
value instanceof Date ||
|
|
17
|
-
value instanceof Map ||
|
|
18
|
-
value instanceof Set ||
|
|
19
|
-
value instanceof RegExp ||
|
|
20
|
-
value instanceof Error ||
|
|
21
|
-
value instanceof Promise ||
|
|
22
|
-
Array.isArray(value)
|
|
23
|
-
) {
|
|
24
|
-
return false
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Check if it's a plain object (Object.prototype or null prototype)
|
|
28
|
-
const proto = Object.getPrototypeOf(value)
|
|
29
|
-
return proto === null || proto === Object.prototype
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Type helper that returns `true` if type T has any method properties,
|
|
34
|
-
* otherwise returns `never`.
|
|
35
|
-
*
|
|
36
|
-
* Used internally by IsPlainObject to distinguish plain objects from
|
|
37
|
-
* class instances or objects with methods.
|
|
38
|
-
*/
|
|
39
|
-
|
|
40
|
-
export const firstValue = (record) => {
|
|
41
|
-
for (const key in record) {
|
|
42
|
-
return record[key]
|
|
43
|
-
}
|
|
44
|
-
return undefined
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export const concatBytes = (a, b) => {
|
|
48
|
-
const result = new Uint8Array(a.byteLength + b.byteLength)
|
|
49
|
-
result.set(a)
|
|
50
|
-
result.set(b, a.byteLength)
|
|
51
|
-
return result
|
|
52
|
-
}
|