@typed/id 0.11.0 → 0.12.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/.nvmrc +1 -0
- package/biome.json +36 -0
- package/dist/DateTimes.d.ts +25 -0
- package/dist/DateTimes.js +20 -0
- package/dist/DateTimes.js.map +1 -0
- package/dist/GetRandomValues.d.ts +11 -0
- package/dist/GetRandomValues.js +17 -0
- package/dist/GetRandomValues.js.map +1 -0
- package/dist/{dts/NanoId.d.ts → NanoId.d.ts} +5 -30
- package/dist/NanoId.js +27 -0
- package/dist/NanoId.js.map +1 -0
- package/dist/Ulid.d.ts +31 -0
- package/dist/Ulid.js +39 -0
- package/dist/Ulid.js.map +1 -0
- package/dist/{dts/Uuid.d.ts → Uuid.d.ts} +5 -31
- package/dist/{esm/Uuid.js → Uuid.js} +13 -31
- package/dist/Uuid.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/package.json +34 -58
- package/readme.md +86 -0
- package/src/DateTimes.ts +37 -0
- package/src/GetRandomValues.ts +28 -77
- package/src/NanoId.ts +16 -40
- package/src/Ulid.ts +82 -0
- package/src/Uuid.ts +34 -57
- package/src/id.test.ts +50 -0
- package/src/index.ts +5 -16
- package/tsconfig.json +26 -0
- package/GetRandomValues/package.json +0 -6
- package/LICENSE +0 -21
- package/NanoId/package.json +0 -6
- package/README.md +0 -5
- package/Schema/package.json +0 -6
- package/Uuid/package.json +0 -6
- package/dist/cjs/GetRandomValues.js +0 -65
- package/dist/cjs/GetRandomValues.js.map +0 -1
- package/dist/cjs/NanoId.js +0 -53
- package/dist/cjs/NanoId.js.map +0 -1
- package/dist/cjs/Schema.js +0 -31
- package/dist/cjs/Schema.js.map +0 -1
- package/dist/cjs/Uuid.js +0 -55
- package/dist/cjs/Uuid.js.map +0 -1
- package/dist/cjs/index.js +0 -39
- package/dist/cjs/index.js.map +0 -1
- package/dist/dts/GetRandomValues.d.ts +0 -38
- package/dist/dts/GetRandomValues.d.ts.map +0 -1
- package/dist/dts/NanoId.d.ts.map +0 -1
- package/dist/dts/Schema.d.ts +0 -15
- package/dist/dts/Schema.d.ts.map +0 -1
- package/dist/dts/Uuid.d.ts.map +0 -1
- package/dist/dts/index.d.ts +0 -16
- package/dist/dts/index.d.ts.map +0 -1
- package/dist/esm/GetRandomValues.js +0 -57
- package/dist/esm/GetRandomValues.js.map +0 -1
- package/dist/esm/NanoId.js +0 -45
- package/dist/esm/NanoId.js.map +0 -1
- package/dist/esm/Schema.js +0 -16
- package/dist/esm/Schema.js.map +0 -1
- package/dist/esm/Uuid.js.map +0 -1
- package/dist/esm/index.js +0 -16
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/package.json +0 -4
- package/src/Schema.ts +0 -29
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
22
|
package/biome.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"organizeImports": {
|
|
3
|
+
"enabled": true
|
|
4
|
+
},
|
|
5
|
+
"linter": {
|
|
6
|
+
"enabled": true,
|
|
7
|
+
"rules": {
|
|
8
|
+
"recommended": true,
|
|
9
|
+
"suspicious": {
|
|
10
|
+
"noExplicitAny": "off",
|
|
11
|
+
"noAssignInExpressions": "off",
|
|
12
|
+
"noShadowRestrictedNames": "off"
|
|
13
|
+
},
|
|
14
|
+
"style": {
|
|
15
|
+
"noParameterAssign": "off",
|
|
16
|
+
"noUselessElse": "off"
|
|
17
|
+
},
|
|
18
|
+
"complexity": {
|
|
19
|
+
"noBannedTypes": "off"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"formatter": {
|
|
24
|
+
"enabled": true,
|
|
25
|
+
"indentStyle": "space",
|
|
26
|
+
"indentWidth": 2,
|
|
27
|
+
"lineWidth": 100
|
|
28
|
+
},
|
|
29
|
+
"javascript": {
|
|
30
|
+
"formatter": {
|
|
31
|
+
"quoteStyle": "single",
|
|
32
|
+
"trailingCommas": "all",
|
|
33
|
+
"semicolons": "asNeeded"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Effect, Layer } from 'effect';
|
|
2
|
+
declare const DateTimes_base: import("effect/Context").TagClass<DateTimes, "DateTimes", {
|
|
3
|
+
readonly now: Effect.Effect<number>;
|
|
4
|
+
readonly date: Effect.Effect<Date>;
|
|
5
|
+
}> & Effect.Tag.Proxy<DateTimes, {
|
|
6
|
+
readonly now: Effect.Effect<number>;
|
|
7
|
+
readonly date: Effect.Effect<Date>;
|
|
8
|
+
}> & {
|
|
9
|
+
use: <X>(body: (_: {
|
|
10
|
+
readonly now: Effect.Effect<number>;
|
|
11
|
+
readonly date: Effect.Effect<Date>;
|
|
12
|
+
}) => X) => [X] extends [Effect.Effect<infer A, infer E, infer R>] ? Effect.Effect<A, E, DateTimes | R> : [X] extends [PromiseLike<infer A_1>] ? Effect.Effect<A_1, import("effect/Cause").UnknownException, DateTimes> : Effect.Effect<X, never, DateTimes>;
|
|
13
|
+
};
|
|
14
|
+
export declare class DateTimes extends DateTimes_base {
|
|
15
|
+
static readonly make: (now: Effect.Effect<number>) => Effect.Effect<{
|
|
16
|
+
now: Effect.Effect<number, never, never>;
|
|
17
|
+
date: Effect.Effect<Date, never, never>;
|
|
18
|
+
}, never, never>;
|
|
19
|
+
static readonly Default: Effect.Effect<{
|
|
20
|
+
now: Effect.Effect<number, never, never>;
|
|
21
|
+
date: Effect.Effect<Date, never, never>;
|
|
22
|
+
}, never, never>;
|
|
23
|
+
static readonly Fixed: (base: Date) => Layer.Layer<DateTimes, never, never>;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Effect, Layer } from 'effect';
|
|
2
|
+
export class DateTimes extends Effect.Tag('DateTimes')() {
|
|
3
|
+
static make = (now) => Effect.succeed({
|
|
4
|
+
now,
|
|
5
|
+
date: now.pipe(Effect.map((millis) => new Date(millis))),
|
|
6
|
+
});
|
|
7
|
+
static Default = this.make(Effect.clockWith((clock) => clock.currentTimeMillis));
|
|
8
|
+
static Fixed = (base) => Layer.effect(DateTimes, Effect.gen(function* () {
|
|
9
|
+
const clock = yield* Effect.clock;
|
|
10
|
+
const startMillis = yield* clock.currentTimeMillis;
|
|
11
|
+
const now = clock.currentTimeMillis.pipe(Effect.map((millis) =>
|
|
12
|
+
// Use BigInt to avoid floating point precision issues which can break deterministic testing
|
|
13
|
+
Number(BigInt(base.getTime()) + BigInt(millis) - BigInt(startMillis))));
|
|
14
|
+
return {
|
|
15
|
+
now,
|
|
16
|
+
date: now.pipe(Effect.map((millis) => new Date(millis))),
|
|
17
|
+
};
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=DateTimes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DateTimes.js","sourceRoot":"","sources":["../src/DateTimes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAqB,MAAM,QAAQ,CAAA;AAEzD,MAAM,OAAO,SAAU,SAAQ,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,EAMnD;IACD,MAAM,CAAU,IAAI,GAAG,CAAC,GAA0B,EAAE,EAAE,CACpD,MAAM,CAAC,OAAO,CAAC;QACb,GAAG;QACH,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;KACzD,CAAC,CAAA;IAEJ,MAAM,CAAU,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAA;IAEzF,MAAM,CAAU,KAAK,GAAG,CAAC,IAAU,EAAE,EAAE,CACrC,KAAK,CAAC,MAAM,CACV,SAAS,EACT,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAA;QACjC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAA;QAClD,MAAM,GAAG,GAAG,KAAK,CAAC,iBAAiB,CAAC,IAAI,CACtC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACpB,4FAA4F;QAC5F,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CACtE,CACF,CAAA;QAED,OAAO;YACL,GAAG;YACH,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;SACzD,CAAA;IACH,CAAC,CAAC,CACH,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as Context from 'effect/Context';
|
|
2
|
+
import * as Effect from 'effect/Effect';
|
|
3
|
+
import * as Layer from 'effect/Layer';
|
|
4
|
+
declare const GetRandomValues_base: Context.TagClass<GetRandomValues, "GetRandomValues", (length: number) => Effect.Effect<Uint8Array>>;
|
|
5
|
+
export declare class GetRandomValues extends GetRandomValues_base {
|
|
6
|
+
static readonly layer: (f: (length: number) => Effect.Effect<Uint8Array>) => Layer.Layer<GetRandomValues, never, never>;
|
|
7
|
+
static readonly apply: (length: number) => Effect.Effect<Uint8Array<ArrayBufferLike>, never, GetRandomValues>;
|
|
8
|
+
static readonly PseudoRandom: Layer.Layer<GetRandomValues, never, never>;
|
|
9
|
+
static readonly CryptoRandom: Layer.Layer<GetRandomValues, never, never>;
|
|
10
|
+
}
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as Context from 'effect/Context';
|
|
2
|
+
import * as Effect from 'effect/Effect';
|
|
3
|
+
import * as Layer from 'effect/Layer';
|
|
4
|
+
import * as Random from 'effect/Random';
|
|
5
|
+
export class GetRandomValues extends Context.Tag('GetRandomValues')() {
|
|
6
|
+
static layer = (f) => Layer.succeed(GetRandomValues, f);
|
|
7
|
+
static apply = (length) => Effect.flatMap(GetRandomValues, (f) => f(length));
|
|
8
|
+
static PseudoRandom = this.layer((length) => Effect.gen(function* () {
|
|
9
|
+
const view = new Uint8Array(length);
|
|
10
|
+
for (let i = 0; i < length; ++i) {
|
|
11
|
+
view[i] = yield* Random.nextInt;
|
|
12
|
+
}
|
|
13
|
+
return view;
|
|
14
|
+
}));
|
|
15
|
+
static CryptoRandom = this.layer((length) => Effect.sync(() => crypto.getRandomValues(new Uint8Array(length))));
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=GetRandomValues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GetRandomValues.js","sourceRoot":"","sources":["../src/GetRandomValues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,MAAM,OAAO,eAAgB,SAAQ,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAGhE;IACD,MAAM,CAAU,KAAK,GAAG,CAAC,CAAgD,EAAE,EAAE,CAC3E,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAA;IAEnC,MAAM,CAAU,KAAK,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAE7F,MAAM,CAAU,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CACnD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAA;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAA;QACjC,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CACH,CAAA;IAED,MAAM,CAAU,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CACnD,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAClE,CAAA"}
|
|
@@ -1,24 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
|
|
4
|
-
import * as Brand from "effect/Brand";
|
|
5
|
-
import * as Effect from "effect/Effect";
|
|
6
|
-
import { GetRandomValues } from "./GetRandomValues.js";
|
|
7
|
-
/**
|
|
8
|
-
* @since 1.0.0
|
|
9
|
-
*/
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
import * as Effect from 'effect/Effect';
|
|
3
|
+
import { GetRandomValues } from './GetRandomValues.js';
|
|
10
4
|
export declare const isNanoId: (id: string) => id is NanoId;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
*/
|
|
14
|
-
export type NanoId = string & Brand.Brand<"@typed/id/NanoId">;
|
|
15
|
-
/**
|
|
16
|
-
* @since 1.0.0
|
|
17
|
-
*/
|
|
18
|
-
export declare const NanoId: Brand.Brand.Constructor<NanoId>;
|
|
19
|
-
/**
|
|
20
|
-
* @since 1.0.0
|
|
21
|
-
*/
|
|
5
|
+
export declare const NanoId: Schema.brand<typeof Schema.String, "@typed/id/NanoId">;
|
|
6
|
+
export type NanoId = Schema.Schema.Type<typeof NanoId>;
|
|
22
7
|
export type NanoIdSeed = readonly [
|
|
23
8
|
zero: number,
|
|
24
9
|
one: number,
|
|
@@ -42,16 +27,6 @@ export type NanoIdSeed = readonly [
|
|
|
42
27
|
nineteen: number,
|
|
43
28
|
twenty: number
|
|
44
29
|
];
|
|
45
|
-
/**
|
|
46
|
-
* @since 1.0.0
|
|
47
|
-
*/
|
|
48
30
|
export declare const nanoId: (seed: NanoIdSeed) => NanoId;
|
|
49
|
-
/**
|
|
50
|
-
* @since 1.0.0
|
|
51
|
-
*/
|
|
52
31
|
export declare const makeNanoIdSeed: Effect.Effect<NanoIdSeed, never, GetRandomValues>;
|
|
53
|
-
/**
|
|
54
|
-
* @since 1.0.0
|
|
55
|
-
*/
|
|
56
32
|
export declare const makeNanoId: Effect.Effect<NanoId, never, GetRandomValues>;
|
|
57
|
-
//# sourceMappingURL=NanoId.d.ts.map
|
package/dist/NanoId.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
import * as Effect from 'effect/Effect';
|
|
3
|
+
import { GetRandomValues } from './GetRandomValues.js';
|
|
4
|
+
const nanoIdPattern = /[0-9a-zA-Z_-]/;
|
|
5
|
+
export const isNanoId = (id) => nanoIdPattern.test(id);
|
|
6
|
+
export const NanoId = Schema.String.pipe(Schema.brand('@typed/id/NanoId'));
|
|
7
|
+
const numToCharacter = (byte) => {
|
|
8
|
+
byte &= 63;
|
|
9
|
+
if (byte < 36) {
|
|
10
|
+
// `0-9a-z`
|
|
11
|
+
return byte.toString(36);
|
|
12
|
+
}
|
|
13
|
+
else if (byte < 62) {
|
|
14
|
+
// `A-Z`
|
|
15
|
+
return (byte - 26).toString(36).toUpperCase();
|
|
16
|
+
}
|
|
17
|
+
else if (byte > 62) {
|
|
18
|
+
return '-';
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
return '_';
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
export const nanoId = (seed) => NanoId.make(seed.reduce((id, x) => id + numToCharacter(x), ''));
|
|
25
|
+
export const makeNanoIdSeed = GetRandomValues.apply(21);
|
|
26
|
+
export const makeNanoId = Effect.map(makeNanoIdSeed, nanoId);
|
|
27
|
+
//# sourceMappingURL=NanoId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NanoId.js","sourceRoot":"","sources":["../src/NanoId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEtD,MAAM,aAAa,GAAG,eAAe,CAAA;AAErC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAgB,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AAE5E,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAA;AA2B1E,MAAM,cAAc,GAAG,CAAC,IAAY,EAAU,EAAE;IAC9C,IAAI,IAAI,EAAE,CAAA;IACV,IAAI,IAAI,GAAG,EAAE,EAAE,CAAC;QACd,WAAW;QACX,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IAC1B,CAAC;SAAM,IAAI,IAAI,GAAG,EAAE,EAAE,CAAC;QACrB,QAAQ;QACR,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;IAC/C,CAAC;SAAM,IAAI,IAAI,GAAG,EAAE,EAAE,CAAC;QACrB,OAAO,GAAG,CAAA;IACZ,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,CAAA;IACZ,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,IAAgB,EAAU,EAAE,CACjD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AAEjE,MAAM,CAAC,MAAM,cAAc,GACzB,eAAe,CAAC,KAAK,CAAC,EAAE,CAAQ,CAAA;AAElC,MAAM,CAAC,MAAM,UAAU,GAAkD,MAAM,CAAC,GAAG,CACjF,cAAc,EACd,MAAM,CACP,CAAA"}
|
package/dist/Ulid.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import { GetRandomValues } from './GetRandomValues.js';
|
|
3
|
+
import { Schema } from 'effect';
|
|
4
|
+
import { DateTimes } from './DateTimes.js';
|
|
5
|
+
export declare const isUlid: (value: string) => value is Ulid;
|
|
6
|
+
export declare const Ulid: Schema.brand<typeof Schema.ULID, "@typed/id/ULID">;
|
|
7
|
+
export type Ulid = Schema.Schema.Type<typeof Ulid>;
|
|
8
|
+
export type UlidSeed = {
|
|
9
|
+
readonly seed: readonly [
|
|
10
|
+
zero: number,
|
|
11
|
+
one: number,
|
|
12
|
+
two: number,
|
|
13
|
+
three: number,
|
|
14
|
+
four: number,
|
|
15
|
+
five: number,
|
|
16
|
+
six: number,
|
|
17
|
+
seven: number,
|
|
18
|
+
eight: number,
|
|
19
|
+
nine: number,
|
|
20
|
+
ten: number,
|
|
21
|
+
eleven: number,
|
|
22
|
+
twelve: number,
|
|
23
|
+
thirteen: number,
|
|
24
|
+
fourteen: number,
|
|
25
|
+
fifteen: number
|
|
26
|
+
];
|
|
27
|
+
readonly now: number;
|
|
28
|
+
};
|
|
29
|
+
export declare const makeUlidSeed: Effect.Effect<UlidSeed, never, GetRandomValues | DateTimes>;
|
|
30
|
+
export declare const makeUlid: Effect.Effect<Ulid, never, GetRandomValues | DateTimes>;
|
|
31
|
+
export declare function ulid(seed: UlidSeed['seed'], now: UlidSeed['now']): Ulid;
|
package/dist/Ulid.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import { GetRandomValues } from './GetRandomValues.js';
|
|
3
|
+
import { Schema } from 'effect';
|
|
4
|
+
import { DateTimes } from './DateTimes.js';
|
|
5
|
+
export const isUlid = Schema.is(Schema.ULID);
|
|
6
|
+
export const Ulid = Schema.ULID.pipe(Schema.brand('@typed/id/ULID'));
|
|
7
|
+
// Crockford's Base32
|
|
8
|
+
const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
|
9
|
+
const ENCODING_LEN = ENCODING.length;
|
|
10
|
+
const TIME_MAX = 2 ** 48 - 1;
|
|
11
|
+
const TIME_LEN = 10;
|
|
12
|
+
const RANDOM_LEN = 16;
|
|
13
|
+
export const makeUlidSeed = DateTimes.now.pipe(Effect.bindTo('now'), Effect.bind('seed', () => GetRandomValues.apply(16)));
|
|
14
|
+
export const makeUlid = Effect.map(makeUlidSeed, ({ seed, now }) => ulid(seed, now));
|
|
15
|
+
function encodeTime(now, len) {
|
|
16
|
+
let str = '';
|
|
17
|
+
for (let i = len - 1; i >= 0; i--) {
|
|
18
|
+
const mod = now % ENCODING_LEN;
|
|
19
|
+
str = ENCODING.charAt(mod) + str;
|
|
20
|
+
now = (now - mod) / ENCODING_LEN;
|
|
21
|
+
}
|
|
22
|
+
return str;
|
|
23
|
+
}
|
|
24
|
+
function encodeRandom(seed) {
|
|
25
|
+
let str = '';
|
|
26
|
+
for (let i = 0; i < RANDOM_LEN; i++) {
|
|
27
|
+
str = str + ENCODING.charAt(seed[i] % ENCODING_LEN);
|
|
28
|
+
}
|
|
29
|
+
return str;
|
|
30
|
+
}
|
|
31
|
+
export function ulid(seed, now) {
|
|
32
|
+
if (now > TIME_MAX) {
|
|
33
|
+
throw new Error('Cannot generate ULID due to timestamp overflow');
|
|
34
|
+
}
|
|
35
|
+
const time = encodeTime(now, TIME_LEN);
|
|
36
|
+
const random = encodeRandom(seed);
|
|
37
|
+
return Ulid.make(time + random);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=Ulid.js.map
|
package/dist/Ulid.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Ulid.js","sourceRoot":"","sources":["../src/Ulid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,MAAM,CAAC,MAAM,MAAM,GAAqC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAQ,CAAA;AAErF,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAA;AAyBpE,qBAAqB;AACrB,MAAM,QAAQ,GAAG,kCAAkC,CAAA;AACnD,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAA;AACpC,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAC5B,MAAM,QAAQ,GAAG,EAAE,CAAA;AACnB,MAAM,UAAU,GAAG,EAAE,CAAA;AAErB,MAAM,CAAC,MAAM,YAAY,GACvB,SAAS,CAAC,GAAG,CAAC,IAAI,CAChB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EACpB,MAAM,CAAC,IAAI,CACT,MAAM,EACN,GAAG,EAAE,CACH,eAAe,CAAC,KAAK,CAAC,EAAE,CAAmE,CAC9F,CACF,CAAA;AAEH,MAAM,CAAC,MAAM,QAAQ,GAA4D,MAAM,CAAC,GAAG,CACzF,YAAY,EACZ,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CACnC,CAAA;AAED,SAAS,UAAU,CAAC,GAAW,EAAE,GAAW;IAC1C,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,KAAK,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,GAAG,GAAG,YAAY,CAAA;QAC9B,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;QAChC,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,YAAY,CAAA;IAClC,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,YAAY,CAAC,IAAsB;IAC1C,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,GAAG,GAAG,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAA;IACrD,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAsB,EAAE,GAAoB;IAC/D,IAAI,GAAG,GAAG,QAAQ,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAA;IACnE,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IACtC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;IAEjC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,CAAA;AACjC,CAAC"}
|
|
@@ -1,25 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import * as Brand from "effect/Brand";
|
|
5
|
-
import * as Effect from "effect/Effect";
|
|
6
|
-
import { GetRandomValues } from "./GetRandomValues.js";
|
|
7
|
-
/**
|
|
8
|
-
* Returns `true` if a string is a UUID.
|
|
9
|
-
* @since 1.0.0
|
|
10
|
-
*/
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import { GetRandomValues } from './GetRandomValues.js';
|
|
3
|
+
import { Schema } from 'effect';
|
|
11
4
|
export declare const isUuid: (value: string) => value is Uuid;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
export type Uuid = string & Brand.Brand<"@typed/id/UUID">;
|
|
16
|
-
/**
|
|
17
|
-
* @since 1.0.0
|
|
18
|
-
*/
|
|
19
|
-
export declare const Uuid: Brand.Brand.Constructor<Uuid>;
|
|
20
|
-
/**
|
|
21
|
-
* @since 1.0.0
|
|
22
|
-
*/
|
|
5
|
+
export declare const Uuid: Schema.brand<typeof Schema.UUID, "@typed/id/UUID">;
|
|
6
|
+
export type Uuid = Schema.Schema.Type<typeof Uuid>;
|
|
23
7
|
export type UuidSeed = readonly [
|
|
24
8
|
zero: number,
|
|
25
9
|
one: number,
|
|
@@ -38,16 +22,6 @@ export type UuidSeed = readonly [
|
|
|
38
22
|
fourteen: number,
|
|
39
23
|
fifteen: number
|
|
40
24
|
];
|
|
41
|
-
/**
|
|
42
|
-
* @since 1.0.0
|
|
43
|
-
*/
|
|
44
25
|
export declare const makeUuidSeed: Effect.Effect<UuidSeed, never, GetRandomValues>;
|
|
45
|
-
/**
|
|
46
|
-
* @since 1.0.0
|
|
47
|
-
*/
|
|
48
26
|
export declare const makeUuid: Effect.Effect<Uuid, never, GetRandomValues>;
|
|
49
|
-
/**
|
|
50
|
-
* @since 1.0.0
|
|
51
|
-
*/
|
|
52
27
|
export declare function uuid4(seed: UuidSeed): Uuid;
|
|
53
|
-
//# sourceMappingURL=Uuid.d.ts.map
|
|
@@ -1,26 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8
|
-
/**
|
|
9
|
-
* Returns `true` if a string is a UUID.
|
|
10
|
-
* @since 1.0.0
|
|
11
|
-
*/
|
|
12
|
-
export const isUuid = (value) => uuidPattern.test(value);
|
|
13
|
-
/**
|
|
14
|
-
* @since 1.0.0
|
|
15
|
-
*/
|
|
16
|
-
export const Uuid = Brand.refined(isUuid, (input) => Brand.error(`Expected a UUID but received ${input}.`));
|
|
17
|
-
/**
|
|
18
|
-
* @since 1.0.0
|
|
19
|
-
*/
|
|
20
|
-
export const makeUuidSeed = GetRandomValues(32);
|
|
21
|
-
/**
|
|
22
|
-
* @since 1.0.0
|
|
23
|
-
*/
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import { GetRandomValues } from './GetRandomValues.js';
|
|
3
|
+
import { Schema } from 'effect';
|
|
4
|
+
export const isUuid = Schema.is(Schema.UUID);
|
|
5
|
+
export const Uuid = Schema.UUID.pipe(Schema.brand('@typed/id/UUID'));
|
|
6
|
+
export const makeUuidSeed = GetRandomValues.apply(32);
|
|
24
7
|
export const makeUuid = Effect.map(makeUuidSeed, uuid4);
|
|
25
8
|
/**
|
|
26
9
|
* Convert array of 16 byte values to UUID string format of the form:
|
|
@@ -30,29 +13,28 @@ const byteToHex = [];
|
|
|
30
13
|
for (let i = 0; i < 256; ++i) {
|
|
31
14
|
byteToHex.push((i + 0x100).toString(16).slice(1));
|
|
32
15
|
}
|
|
33
|
-
/**
|
|
34
|
-
* @since 1.0.0
|
|
35
|
-
*/
|
|
36
16
|
export function uuid4(seed) {
|
|
37
17
|
// Note: Be careful editing this code! It's been tuned for performance
|
|
38
18
|
// and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
|
|
39
19
|
//
|
|
40
20
|
// Note to future-self: No, you can't remove the `toLowerCase()` call.
|
|
41
21
|
// REF: https://github.com/uuidjs/uuid/pull/677#issuecomment-1757351351
|
|
42
|
-
return (
|
|
22
|
+
return (
|
|
23
|
+
// biome-ignore lint/style/useTemplate: <explanation>
|
|
24
|
+
byteToHex[seed[0]] +
|
|
43
25
|
byteToHex[seed[1]] +
|
|
44
26
|
byteToHex[seed[2]] +
|
|
45
27
|
byteToHex[seed[3]] +
|
|
46
|
-
|
|
28
|
+
'-' +
|
|
47
29
|
byteToHex[seed[4]] +
|
|
48
30
|
byteToHex[seed[5]] +
|
|
49
|
-
|
|
31
|
+
'-' +
|
|
50
32
|
byteToHex[seed[6]] +
|
|
51
33
|
byteToHex[seed[7]] +
|
|
52
|
-
|
|
34
|
+
'-' +
|
|
53
35
|
byteToHex[seed[8]] +
|
|
54
36
|
byteToHex[seed[9]] +
|
|
55
|
-
|
|
37
|
+
'-' +
|
|
56
38
|
byteToHex[seed[10]] +
|
|
57
39
|
byteToHex[seed[11]] +
|
|
58
40
|
byteToHex[seed[12]] +
|
package/dist/Uuid.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Uuid.js","sourceRoot":"","sources":["../src/Uuid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,MAAM,CAAC,MAAM,MAAM,GAAqC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAQ,CAAA;AAErF,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAA;AAsBpE,MAAM,CAAC,MAAM,YAAY,GAAoD,eAAe,CAAC,KAAK,CAChG,EAAE,CACI,CAAA;AAER,MAAM,CAAC,MAAM,QAAQ,GAAgD,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,CAAA;AAEpG;;;GAGG;AACH,MAAM,SAAS,GAAkB,EAAE,CAAA;AAEnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC;IAC7B,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AACnD,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,IAAc;IAClC,uEAAuE;IACvE,oFAAoF;IACpF,EAAE;IACF,sEAAsE;IACtE,uEAAuE;IACvE,OACE;IACE,qDAAqD;IACrD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,GAAG;QACH,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,GAAG;QACH,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,GAAG;QACH,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,GAAG;QACH,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnB,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnB,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnB,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnB,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnB,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CACpB,CAAC,WAAW,EACd,CAAA;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,66 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typed/id",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"description": "Common ID format generation for Effect",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"effect",
|
|
10
|
+
"ID",
|
|
11
|
+
"UUID",
|
|
12
|
+
"NanoId",
|
|
13
|
+
"ULID",
|
|
14
|
+
"typescript"
|
|
15
|
+
],
|
|
16
|
+
"author": "Tylor Steinberger <tlsteinberger167@gmail.com>",
|
|
5
17
|
"license": "MIT",
|
|
6
|
-
"repository": {
|
|
7
|
-
"type": "git",
|
|
8
|
-
"url": "https://github.com/tylors/typed.git"
|
|
9
|
-
},
|
|
10
|
-
"sideEffects": [],
|
|
11
|
-
"author": "Typed contributors",
|
|
12
|
-
"homepage": "https://github.com/tylors/typed",
|
|
13
18
|
"dependencies": {
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
19
|
+
"effect": "^3.11.9"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"effect": "^3.11.9"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@biomejs/biome": "^1.9.4",
|
|
26
|
+
"@effect/vitest": "^0.16.0",
|
|
27
|
+
"@types/node": "^22.10.2",
|
|
28
|
+
"typescript": "^5.4.2",
|
|
29
|
+
"vitest": "^2.1.8"
|
|
18
30
|
},
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
"types": "./dist/dts/index.d.ts",
|
|
22
|
-
"exports": {
|
|
23
|
-
"./package.json": "./package.json",
|
|
24
|
-
".": {
|
|
25
|
-
"types": "./dist/dts/index.d.ts",
|
|
26
|
-
"import": "./dist/esm/index.js",
|
|
27
|
-
"default": "./dist/cjs/index.js"
|
|
28
|
-
},
|
|
29
|
-
"./GetRandomValues": {
|
|
30
|
-
"types": "./dist/dts/GetRandomValues.d.ts",
|
|
31
|
-
"import": "./dist/esm/GetRandomValues.js",
|
|
32
|
-
"default": "./dist/cjs/GetRandomValues.js"
|
|
33
|
-
},
|
|
34
|
-
"./NanoId": {
|
|
35
|
-
"types": "./dist/dts/NanoId.d.ts",
|
|
36
|
-
"import": "./dist/esm/NanoId.js",
|
|
37
|
-
"default": "./dist/cjs/NanoId.js"
|
|
38
|
-
},
|
|
39
|
-
"./Schema": {
|
|
40
|
-
"types": "./dist/dts/Schema.d.ts",
|
|
41
|
-
"import": "./dist/esm/Schema.js",
|
|
42
|
-
"default": "./dist/cjs/Schema.js"
|
|
43
|
-
},
|
|
44
|
-
"./Uuid": {
|
|
45
|
-
"types": "./dist/dts/Uuid.d.ts",
|
|
46
|
-
"import": "./dist/esm/Uuid.js",
|
|
47
|
-
"default": "./dist/cjs/Uuid.js"
|
|
48
|
-
}
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
49
33
|
},
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
],
|
|
58
|
-
"Schema": [
|
|
59
|
-
"./dist/dts/Schema.d.ts"
|
|
60
|
-
],
|
|
61
|
-
"Uuid": [
|
|
62
|
-
"./dist/dts/Uuid.d.ts"
|
|
63
|
-
]
|
|
64
|
-
}
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc",
|
|
36
|
+
"dev": "tsc --watch",
|
|
37
|
+
"lint": "biome lint --write",
|
|
38
|
+
"test:watch": "vitest --typecheck",
|
|
39
|
+
"test": "vitest run --typecheck",
|
|
40
|
+
"typecheck": "tsc --noEmit"
|
|
65
41
|
}
|
|
66
42
|
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# @typed/id
|
|
2
|
+
|
|
3
|
+
A TypeScript library providing common ID format generation using [Effect](https://effect.website/). This package includes implementations for UUID, NanoID, and ULID generation with a focus on type safety and functional programming principles.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @typed/id effect
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @typed/id effect
|
|
11
|
+
# or
|
|
12
|
+
yarn add @typed/id effect
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- 🎯 Type-safe ID generation
|
|
18
|
+
- 🔧 Built on top of Effect
|
|
19
|
+
- 🎨 Multiple ID format support:
|
|
20
|
+
- UUID (v4)
|
|
21
|
+
- NanoID
|
|
22
|
+
- ULID
|
|
23
|
+
- ⚡ Efficient and secure random value generation
|
|
24
|
+
- 📦 Zero dependencies (except Effect)
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { Effect } from 'effect'
|
|
30
|
+
import {
|
|
31
|
+
DateTimes,
|
|
32
|
+
GetRandomValues,
|
|
33
|
+
makeUuid,
|
|
34
|
+
makeNanoId,
|
|
35
|
+
makeUlid
|
|
36
|
+
} from '@typed/id'
|
|
37
|
+
|
|
38
|
+
// Generate a UUID
|
|
39
|
+
await makeUuid.pipe(
|
|
40
|
+
Effect.provide(GetRandomValues.CryptoRandom),
|
|
41
|
+
// Effect.provide(GetRandomValues.PseudoRandom),
|
|
42
|
+
Effect.flatMap(Effect.log),
|
|
43
|
+
Effect.runPromise
|
|
44
|
+
)
|
|
45
|
+
// Output: "550e8400-e29b-41d4-a716-446655440000"
|
|
46
|
+
|
|
47
|
+
// Generate a NanoID
|
|
48
|
+
await makeNanoId.pipe(
|
|
49
|
+
Effect.provide(GetRandomValues.CryptoRandom),
|
|
50
|
+
// Effect.provide(GetRandomValues.PseudoRandom),
|
|
51
|
+
Effect.flatMap(Effect.log),
|
|
52
|
+
Effect.runPromise
|
|
53
|
+
)
|
|
54
|
+
// Output: "V1StGXR8_Z5jdHi6B-myT"
|
|
55
|
+
|
|
56
|
+
// Generate a ULID
|
|
57
|
+
await makeUlid.pipe(
|
|
58
|
+
Effect.provide([
|
|
59
|
+
GetRandomValues.CryptoRandom,
|
|
60
|
+
// GetRandomValues.PseudoRandom,
|
|
61
|
+
DateTimes.Default
|
|
62
|
+
// DateTimes.Fixed(new Date(0))
|
|
63
|
+
]),
|
|
64
|
+
Effect.flatMap(Effect.log),
|
|
65
|
+
Effect.runPromise
|
|
66
|
+
)
|
|
67
|
+
// Output: "01ARZ3NDEKTSV4RRFFQ69G5FAV"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## API
|
|
71
|
+
|
|
72
|
+
### UUID
|
|
73
|
+
|
|
74
|
+
- `makeUuid`: Generates a v4 UUID
|
|
75
|
+
|
|
76
|
+
### NanoID
|
|
77
|
+
|
|
78
|
+
- `makeNanoId`: Generates a NanoID with a default length of 21 characters
|
|
79
|
+
|
|
80
|
+
### ULID
|
|
81
|
+
|
|
82
|
+
- `makeUlid`: Generates a ULID (Universally Unique Lexicographically Sortable Identifier)
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
MIT
|
package/src/DateTimes.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Effect, Layer, Option, TestClock } from 'effect'
|
|
2
|
+
|
|
3
|
+
export class DateTimes extends Effect.Tag('DateTimes')<
|
|
4
|
+
DateTimes,
|
|
5
|
+
{
|
|
6
|
+
readonly now: Effect.Effect<number>
|
|
7
|
+
readonly date: Effect.Effect<Date>
|
|
8
|
+
}
|
|
9
|
+
>() {
|
|
10
|
+
static readonly make = (now: Effect.Effect<number>) =>
|
|
11
|
+
Effect.succeed({
|
|
12
|
+
now,
|
|
13
|
+
date: now.pipe(Effect.map((millis) => new Date(millis))),
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
static readonly Default = this.make(Effect.clockWith((clock) => clock.currentTimeMillis))
|
|
17
|
+
|
|
18
|
+
static readonly Fixed = (base: Date) =>
|
|
19
|
+
Layer.effect(
|
|
20
|
+
DateTimes,
|
|
21
|
+
Effect.gen(function* () {
|
|
22
|
+
const clock = yield* Effect.clock
|
|
23
|
+
const startMillis = yield* clock.currentTimeMillis
|
|
24
|
+
const now = clock.currentTimeMillis.pipe(
|
|
25
|
+
Effect.map((millis) =>
|
|
26
|
+
// Use BigInt to avoid floating point precision issues which can break deterministic testing
|
|
27
|
+
Number(BigInt(base.getTime()) + BigInt(millis) - BigInt(startMillis)),
|
|
28
|
+
),
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
now,
|
|
33
|
+
date: now.pipe(Effect.map((millis) => new Date(millis))),
|
|
34
|
+
}
|
|
35
|
+
}),
|
|
36
|
+
)
|
|
37
|
+
}
|