@nxgt/janus 0.1.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.
Files changed (112) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +554 -0
  3. package/dist/auth/config.d.ts +201 -0
  4. package/dist/auth/config.d.ts.map +1 -0
  5. package/dist/auth/context.d.ts +87 -0
  6. package/dist/auth/context.d.ts.map +1 -0
  7. package/dist/auth/hashers.d.ts +35 -0
  8. package/dist/auth/hashers.d.ts.map +1 -0
  9. package/dist/auth/index.d.ts +9 -0
  10. package/dist/auth/index.d.ts.map +1 -0
  11. package/dist/auth/janus.d.ts +38 -0
  12. package/dist/auth/janus.d.ts.map +1 -0
  13. package/dist/auth/outage.d.ts +61 -0
  14. package/dist/auth/outage.d.ts.map +1 -0
  15. package/dist/auth/port/assert-stores.d.ts +16 -0
  16. package/dist/auth/port/assert-stores.d.ts.map +1 -0
  17. package/dist/auth/port/memory.d.ts +25 -0
  18. package/dist/auth/port/memory.d.ts.map +1 -0
  19. package/dist/auth/port/types.d.ts +393 -0
  20. package/dist/auth/port/types.d.ts.map +1 -0
  21. package/dist/auth/secrets.d.ts +17 -0
  22. package/dist/auth/secrets.d.ts.map +1 -0
  23. package/dist/auth/sessions.d.ts +31 -0
  24. package/dist/auth/sessions.d.ts.map +1 -0
  25. package/dist/auth/standard-schema.d.ts +41 -0
  26. package/dist/auth/standard-schema.d.ts.map +1 -0
  27. package/dist/auth/types.d.ts +353 -0
  28. package/dist/auth/types.d.ts.map +1 -0
  29. package/dist/auth/users.d.ts +9 -0
  30. package/dist/auth/users.d.ts.map +1 -0
  31. package/dist/chunks/index-658b6mr2.js +269 -0
  32. package/dist/chunks/index-658b6mr2.js.map +11 -0
  33. package/dist/chunks/index-6dytvy3h.js +93 -0
  34. package/dist/chunks/index-6dytvy3h.js.map +11 -0
  35. package/dist/chunks/index-6p56fpbe.js +147 -0
  36. package/dist/chunks/index-6p56fpbe.js.map +12 -0
  37. package/dist/chunks/index-fgb3t64y.js +77 -0
  38. package/dist/chunks/index-fgb3t64y.js.map +10 -0
  39. package/dist/conformance/assert.d.ts +36 -0
  40. package/dist/conformance/assert.d.ts.map +1 -0
  41. package/dist/conformance/cases/outage.d.ts +3 -0
  42. package/dist/conformance/cases/outage.d.ts.map +1 -0
  43. package/dist/conformance/cases/sessions.d.ts +3 -0
  44. package/dist/conformance/cases/sessions.d.ts.map +1 -0
  45. package/dist/conformance/cases/tokens.d.ts +3 -0
  46. package/dist/conformance/cases/tokens.d.ts.map +1 -0
  47. package/dist/conformance/cases/users.d.ts +3 -0
  48. package/dist/conformance/cases/users.d.ts.map +1 -0
  49. package/dist/conformance/describe.d.ts +74 -0
  50. package/dist/conformance/describe.d.ts.map +1 -0
  51. package/dist/conformance/fixtures.d.ts +11 -0
  52. package/dist/conformance/fixtures.d.ts.map +1 -0
  53. package/dist/conformance/index.d.ts +33 -0
  54. package/dist/conformance/index.d.ts.map +1 -0
  55. package/dist/conformance/index.js +1113 -0
  56. package/dist/conformance/index.js.map +18 -0
  57. package/dist/conformance/reference.d.ts +13 -0
  58. package/dist/conformance/reference.d.ts.map +1 -0
  59. package/dist/conformance/relations.d.ts +67 -0
  60. package/dist/conformance/relations.d.ts.map +1 -0
  61. package/dist/conformance/types.d.ts +71 -0
  62. package/dist/conformance/types.d.ts.map +1 -0
  63. package/dist/errors/janus-error.d.ts +259 -0
  64. package/dist/errors/janus-error.d.ts.map +1 -0
  65. package/dist/ids/id.d.ts +55 -0
  66. package/dist/ids/id.d.ts.map +1 -0
  67. package/dist/index.d.ts +30 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +962 -0
  70. package/dist/index.js.map +19 -0
  71. package/dist/pagination/cursor-page.d.ts +53 -0
  72. package/dist/pagination/cursor-page.d.ts.map +1 -0
  73. package/dist/permissions/engine.d.ts +46 -0
  74. package/dist/permissions/engine.d.ts.map +1 -0
  75. package/dist/permissions/index.d.ts +24 -0
  76. package/dist/permissions/index.d.ts.map +1 -0
  77. package/dist/permissions/index.js +685 -0
  78. package/dist/permissions/index.js.map +15 -0
  79. package/dist/permissions/input.d.ts +29 -0
  80. package/dist/permissions/input.d.ts.map +1 -0
  81. package/dist/permissions/model.d.ts +368 -0
  82. package/dist/permissions/model.d.ts.map +1 -0
  83. package/dist/permissions/port/memory.d.ts +17 -0
  84. package/dist/permissions/port/memory.d.ts.map +1 -0
  85. package/dist/permissions/port/types.d.ts +84 -0
  86. package/dist/permissions/port/types.d.ts.map +1 -0
  87. package/dist/permissions/resolve.d.ts +59 -0
  88. package/dist/permissions/resolve.d.ts.map +1 -0
  89. package/dist/permissions/reverse.d.ts +53 -0
  90. package/dist/permissions/reverse.d.ts.map +1 -0
  91. package/dist/permissions/walk.d.ts +29 -0
  92. package/dist/permissions/walk.d.ts.map +1 -0
  93. package/dist/subjects/notation.d.ts +35 -0
  94. package/dist/subjects/notation.d.ts.map +1 -0
  95. package/dist/subjects/subject.d.ts +75 -0
  96. package/dist/subjects/subject.d.ts.map +1 -0
  97. package/dist/time/clock.d.ts +31 -0
  98. package/dist/time/clock.d.ts.map +1 -0
  99. package/dist/time/duration.d.ts +23 -0
  100. package/dist/time/duration.d.ts.map +1 -0
  101. package/docs/README.md +17 -0
  102. package/docs/guide/adapters.md +296 -0
  103. package/docs/guide/email-flows.md +146 -0
  104. package/docs/guide/errors.md +146 -0
  105. package/docs/guide/passwords.md +136 -0
  106. package/docs/guide/permissions.md +347 -0
  107. package/docs/guide/sessions.md +211 -0
  108. package/docs/guide/users.md +277 -0
  109. package/docs/guide/vocabulary.md +163 -0
  110. package/docs/roadmap.md +93 -0
  111. package/docs/troubleshooting.md +648 -0
  112. package/package.json +70 -0
@@ -0,0 +1,259 @@
1
+ /**
2
+ * What this package refuses, as a string a caller can switch on.
3
+ *
4
+ * Every code is a **refusal at call time, on a value that could have come from
5
+ * a request** — which is the rule that decides whether something belongs here
6
+ * or stays a bare `TypeError`. A refusal that can only come from how the
7
+ * application was wired (`janus()` with no schema, a lifespan that is
8
+ * not a duration, a store missing a method) throws a plain `TypeError`
9
+ * instead: no request handler should ever answer one, so no handler needs to
10
+ * tell it apart from the others.
11
+ *
12
+ * The codes are `SCREAMING_SNAKE`, and that is not an exception to this
13
+ * repository's camelCase rule — they are data values, not API identifiers, the
14
+ * same shape `code` has in `@nxgt/mongo` and `@nxgt/redis`. Every *key* in
15
+ * this package is camelCase.
16
+ */
17
+ export type JanusErrorCode =
18
+ /**
19
+ * The store could not answer — a refused connection, a timeout, a primary
20
+ * stepping down, a deserialisation failure, a bug in the adapter.
21
+ *
22
+ * **Never a negative answer.** A handler answers 503 and lets the visitor
23
+ * retry. Mapping this to a 404, to `null` or to `false` turns an outage
24
+ * into a silent lockout: everybody who has an account is told they do not.
25
+ * That failure has been measured twice in this organisation, two days
26
+ * apart, and it is the reason this package's port is specified rather than
27
+ * merely documented.
28
+ */
29
+ 'STORE_FAILED'
30
+ /**
31
+ * The store answered, and there is no such record.
32
+ *
33
+ * Raised by the `get*` calls, never by the `find*` calls — those return
34
+ * `null`, which is a value the caller decides what to do with.
35
+ */
36
+ | 'NOT_FOUND'
37
+ /**
38
+ * The login — an e-mail, a username — is already held by another user of
39
+ * the same type.
40
+ *
41
+ * Raised by the **store's own unique constraint** and surfaced here, never
42
+ * decided by reading first: two concurrent sign-ups both pass a read, and
43
+ * only a constraint refuses one of them. Carries `login` and `userType`.
44
+ */
45
+ | 'LOGIN_TAKEN'
46
+ /**
47
+ * The record changed since it was read: the version it was expected to
48
+ * hold is no longer the version it holds, and **nothing was written**.
49
+ * Read it again and retry. Carries `expectedVersion` and `actualVersion`.
50
+ */
51
+ | 'VERSION_CONFLICT'
52
+ /**
53
+ * The fields failed the user type's schema. Carries `issues`, whose paths
54
+ * are the fields' own, so a handler can answer 400 field by field.
55
+ */
56
+ | 'USER_INVALID'
57
+ /**
58
+ * The password is shorter than the policy's minimum. Reports the policy,
59
+ * never the password.
60
+ */
61
+ | 'PASSWORD_TOO_SHORT'
62
+ /**
63
+ * The login and the password do not match: no such login, no password set,
64
+ * or the wrong one — **one code for the three**, so a response cannot tell
65
+ * which accounts exist. `reason` tells them apart for your logs and your
66
+ * rate limiter, and never belongs in a response body.
67
+ */
68
+ | 'CREDENTIALS_INVALID'
69
+ /**
70
+ * A stored hash whose prefix names no wired verifier — typically an import
71
+ * from a system whose format this core cannot read. Reports the prefix,
72
+ * never the hash.
73
+ */
74
+ | 'HASH_UNSUPPORTED'
75
+ /**
76
+ * The user is inactive: the record and its password are kept, and every
77
+ * sign-in is refused. Only told to somebody who gave the right password.
78
+ */
79
+ | 'USER_INACTIVE'
80
+ /** No token holds that secret. */
81
+ | 'TOKEN_UNKNOWN'
82
+ /**
83
+ * The token was already spent. Told apart from `TOKEN_UNKNOWN` for the
84
+ * message only — both are refusals, and the outcome is the same.
85
+ */
86
+ | 'TOKEN_SPENT'
87
+ /**
88
+ * The token existed and its expiry has passed. It is spent all the same,
89
+ * so it cannot be retried.
90
+ */
91
+ | 'TOKEN_EXPIRED'
92
+ /**
93
+ * The token was sent to an e-mail the user no longer has. Confirming it
94
+ * would verify an address nobody holds any more, so it is spent and refused.
95
+ */
96
+ | 'TOKEN_STALE'
97
+ /** A cursor this store did not mint, or one written for another ordering.
98
+ * Never a silent first page: a caller paging a list would loop for ever. */
99
+ | 'INVALID_CURSOR'
100
+ /**
101
+ * The wired store does not implement the optional capability this call
102
+ * needs. Names the method and the slot, so the sentence says which store to
103
+ * change or which call to stop making.
104
+ */
105
+ | 'UNSUPPORTED'
106
+ /**
107
+ * A permission check walked deeper than `maxDepth` relations without an
108
+ * answer. **Not a refusal**: an evaluation that stopped half-way has not
109
+ * decided anything, and answering `false` would hide a model that is too
110
+ * deep behind denials nobody can explain. A cycle in the data is not this —
111
+ * it is cut, silently. Carries `permission` and `maxDepth`.
112
+ */
113
+ | 'PERMISSION_DEPTH';
114
+ /** One thing that was wrong with a user's fields, at one path. */
115
+ export interface Issue {
116
+ /** The path inside the fields, as the schema reported it: `['address', 'city']`. */
117
+ readonly path: readonly (string | number)[];
118
+ readonly message: string;
119
+ }
120
+ /**
121
+ * Why a sign-in was refused, for your logs and rate limiter.
122
+ *
123
+ * **Never put it in a response body.** `unknownLogin` is an account
124
+ * enumeration oracle.
125
+ */
126
+ export type CredentialRefusal = 'unknownLogin' | 'noPassword' | 'wrongPassword';
127
+ /**
128
+ * What an error may carry beside its code.
129
+ *
130
+ * **No field here ever holds a secret.** Not a password, not a hash, not a
131
+ * session token, not a token secret, not a token's hash, and not a connection
132
+ * URI — a connection string holds a password, and the specs assert its absence
133
+ * from every message. A `login` may appear, because the caller just sent it.
134
+ */
135
+ export interface JanusErrorOptions {
136
+ readonly userId?: string;
137
+ readonly userType?: string;
138
+ /** The login a conflict names: an address, never a secret. */
139
+ readonly login?: string;
140
+ readonly reason?: CredentialRefusal;
141
+ /** The prefix of a hash whose format is unknown. Never the hash. */
142
+ readonly hashPrefix?: string;
143
+ readonly expectedVersion?: number;
144
+ readonly actualVersion?: number;
145
+ readonly issues?: readonly Issue[];
146
+ /** The minimum the policy requires. Never the password that failed it. */
147
+ readonly minLength?: number;
148
+ /** The port method being called: `insertUser`, `consumeToken`. */
149
+ readonly operation?: string;
150
+ /** Which store slot: the sentence should say which store to change. */
151
+ readonly slot?: 'users' | 'sessions' | 'tokens' | 'relations';
152
+ /** The permission being checked, in the notation: `record:r1#view`. */
153
+ readonly permission?: string;
154
+ /** The depth a check may walk. */
155
+ readonly maxDepth?: number;
156
+ readonly cause?: unknown;
157
+ }
158
+ /**
159
+ * The base of everything this package throws at call time.
160
+ *
161
+ * It extends `Error` and not `TypeError`, and the rule behind that is
162
+ * `nxgt-data`'s: *extend whichever class the refusals it replaces already
163
+ * threw, so no consumer's `catch` stops working*. These replace nothing — the
164
+ * package is new — and `DataError`, `RedisError` and `S3Error` all extend
165
+ * `Error`, so nobody has to order their `catch` blocks.
166
+ *
167
+ * **There is exactly one definition of this class**, and that matters more here
168
+ * than it looks: an adapter in another package throws `StoreFailure` and this
169
+ * package tests it with `instanceof`. Two copies and the product is wrong about
170
+ * what an outage is. `build.ts` shares the module across entry points with
171
+ * `splitting: true`, and `scripts/verify-artifacts.ts` fails the build if any
172
+ * class name appears in two entry bundles of the packed tarball.
173
+ */
174
+ export declare class JanusError extends Error {
175
+ name: string;
176
+ readonly code: JanusErrorCode;
177
+ readonly userId: string | undefined;
178
+ readonly userType: string | undefined;
179
+ readonly login: string | undefined;
180
+ readonly reason: CredentialRefusal | undefined;
181
+ readonly hashPrefix: string | undefined;
182
+ readonly expectedVersion: number | undefined;
183
+ readonly actualVersion: number | undefined;
184
+ readonly issues: readonly Issue[] | undefined;
185
+ readonly minLength: number | undefined;
186
+ readonly operation: string | undefined;
187
+ readonly slot: 'users' | 'sessions' | 'tokens' | 'relations' | undefined;
188
+ readonly permission: string | undefined;
189
+ readonly maxDepth: number | undefined;
190
+ constructor(message: string, options?: JanusErrorOptions);
191
+ }
192
+ /**
193
+ * The store could not answer.
194
+ *
195
+ * **This is the class an adapter throws**, and it is exported for that reason:
196
+ * an adapter defines no error class of its own, so `instanceof` holds across
197
+ * the two packages. Any other throw from a store is treated as a failure too —
198
+ * throwing this one is how an adapter says so precisely, and sets `cause`.
199
+ */
200
+ export declare class StoreFailure extends JanusError {
201
+ name: string;
202
+ readonly code: "STORE_FAILED";
203
+ }
204
+ /**
205
+ * A uniqueness or a version constraint the store refused.
206
+ *
207
+ * Also thrown by an adapter, and also for the `instanceof` reason. `on` says
208
+ * which constraint, because the two are answered differently: a login
209
+ * collision is the caller's to fix, a version conflict is a retry.
210
+ */
211
+ export declare class StoreConflict extends JanusError {
212
+ name: string;
213
+ readonly code: JanusErrorCode;
214
+ readonly on: 'login' | 'version';
215
+ constructor(on: 'login' | 'version', message: string, options?: JanusErrorOptions);
216
+ }
217
+ /** There is no such record, and the store said so. */
218
+ export declare class NotFoundError extends JanusError {
219
+ name: string;
220
+ readonly code: "NOT_FOUND";
221
+ }
222
+ /** The fields failed the user type's schema. */
223
+ export declare class UserInvalidError extends JanusError {
224
+ name: string;
225
+ readonly code: "USER_INVALID";
226
+ }
227
+ /** A password too short, credentials that do not match, or a hash format nobody reads. */
228
+ export declare class CredentialError extends JanusError {
229
+ name: string;
230
+ readonly code: JanusErrorCode;
231
+ constructor(code: Extract<JanusErrorCode, 'PASSWORD_TOO_SHORT' | 'CREDENTIALS_INVALID' | 'HASH_UNSUPPORTED'>, message: string, options?: JanusErrorOptions);
232
+ }
233
+ /** The user is inactive, and the password given was the right one. */
234
+ export declare class UserInactiveError extends JanusError {
235
+ name: string;
236
+ readonly code: "USER_INACTIVE";
237
+ }
238
+ /** A one-time token that is unknown, already spent, lapsed, or sent to an e-mail the user no longer has. */
239
+ export declare class TokenError extends JanusError {
240
+ name: string;
241
+ readonly code: JanusErrorCode;
242
+ constructor(code: Extract<JanusErrorCode, 'TOKEN_UNKNOWN' | 'TOKEN_SPENT' | 'TOKEN_EXPIRED' | 'TOKEN_STALE'>, message: string, options?: JanusErrorOptions);
243
+ }
244
+ /** A cursor this store did not mint, or one for another ordering. */
245
+ export declare class InvalidCursorError extends JanusError {
246
+ name: string;
247
+ readonly code: "INVALID_CURSOR";
248
+ }
249
+ /** The wired store does not implement the optional capability asked for. */
250
+ export declare class UnsupportedError extends JanusError {
251
+ name: string;
252
+ readonly code: "UNSUPPORTED";
253
+ }
254
+ /** A permission check walked deeper than `maxDepth` without an answer. */
255
+ export declare class PermissionDepthError extends JanusError {
256
+ name: string;
257
+ readonly code: "PERMISSION_DEPTH";
258
+ }
259
+ //# sourceMappingURL=janus-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"janus-error.d.ts","sourceRoot":"","sources":["../../src/errors/janus-error.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * An id — of a user, a session: a UUIDv7, lowercase, hyphenated.
3
+ *
4
+ * **The core mints it, not the store**, and that decision pays for itself three
5
+ * times over:
6
+ *
7
+ * - A UUIDv7 leads with a 48-bit millisecond timestamp, so ids sort in
8
+ * creation order as strings. The pagination cursor is therefore *the last
9
+ * id* — one index on the id, and the ordering is already total. A
10
+ * store-minted id would need a `createdAt` index plus the id as a tiebreak,
11
+ * because a timestamp alone is not a total order, and an opaque cursor per
12
+ * adapter.
13
+ * - `insertUser` becomes **idempotent under retry**: the id is decided
14
+ * before the call, so a retry after a timeout writes the same row rather
15
+ * than a second user.
16
+ * - Every adapter reports the same shape, so moving an application from one
17
+ * adapter to another is a copy rather than a rewrite of every stored
18
+ * reference.
19
+ *
20
+ * The price, stated plainly: an adapter cannot reuse an existing numeric primary
21
+ * key. It gets a `uuid` column, or a 36-character string, and the monotonic
22
+ * prefix gives it the index locality a UUIDv4 destroys.
23
+ */
24
+ export type Id = string;
25
+ /**
26
+ * A fresh id.
27
+ *
28
+ * Strictly increasing: within one millisecond it uses the sequence, and if that
29
+ * overflows — more than 4096 ids in a millisecond, which no real
30
+ * application reaches — it borrows the next millisecond rather than repeating
31
+ * one. Across processes the 62 random bits of the tail are what keep two machines
32
+ * apart.
33
+ */
34
+ export declare function mintId(now?: number): Id;
35
+ /**
36
+ * Whether this string is an id this package could have minted.
37
+ *
38
+ * Used by an adapter to answer `null` for a malformed id **without reaching the
39
+ * store**: an id arrives off a URL, and one of the wrong shape is "no such
40
+ * user", not an outage and not a query. Rejecting it here also keeps a
41
+ * hand-written id out of a store that would then hold something the cursor
42
+ * cannot order.
43
+ */
44
+ export declare function isId(value: string): boolean;
45
+ /**
46
+ * When this id was minted, from the id itself.
47
+ *
48
+ * Offered because the timestamp is *in* the id, so a `createdAt` column is a
49
+ * convenience rather than the truth — and an adapter that loses one can still
50
+ * answer. It is not a substitute for `createdAt`: the sequence may have borrowed
51
+ * a millisecond, and a clock that stepped backwards is held rather than
52
+ * followed, so this is accurate to the millisecond and no further.
53
+ */
54
+ export declare function mintedAt(id: Id): Date;
55
+ //# sourceMappingURL=id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/ids/id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,MAAM,EAAE,GAAG,MAAM,CAAC;AAoBxB;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,GAAG,GAAE,MAAmB,GAAG,EAAE,CA4CnD;AAKD;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,CAGrC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * `@nxgt/janus` — embeddable, type-safe authentication and permissions, over a
3
+ * store you provide.
4
+ *
5
+ * This entry point is `janus()` — users, sessions, sign-up, sign-in, e-mail
6
+ * verification and password reset — and what it shares with the permissions
7
+ * module: the subject vocabulary, the error family, pagination, time, and
8
+ * ids. Permissions are `@nxgt/janus/permissions`. Their vocabulary lives here,
9
+ * because users need it too — `subjectOf` is the join between the two, and it
10
+ * is a function rather than a convention on purpose.
11
+ *
12
+ * ## The one rule this package is built around
13
+ *
14
+ * **An outage is never an absence.** A store that cannot answer throws; a store
15
+ * that answered and found nothing returns `null`. A caller that maps a failure
16
+ * to `null` or `false` has turned an outage into a silent lockout — everybody
17
+ * who has an account is told they do not. That sentence is inherited from the
18
+ * Ory layer this package is an alternative to, where it had to be learned twice
19
+ * in two days, and here it is a term of the port rather than a line of prose:
20
+ * `@nxgt/janus/conformance` fails an adapter that breaks it.
21
+ */
22
+ export * from './auth/index';
23
+ export { CredentialError, type CredentialRefusal, InvalidCursorError, type Issue, JanusError, type JanusErrorCode, type JanusErrorOptions, NotFoundError, PermissionDepthError, StoreConflict, StoreFailure, TokenError, UnsupportedError, UserInactiveError, UserInvalidError, } from './errors/janus-error';
24
+ export { type Id, isId, mintedAt, mintId, } from './ids/id';
25
+ export { type CursorPage, DEFAULT_PAGE_SIZE, invalidCursor, MAX_PAGE_SIZE, pageLimit, } from './pagination/cursor-page';
26
+ export { formatEntity, formatSubject, formatTuple, parseSubject, parseTuple, } from './subjects/notation';
27
+ export { type Entity, isSubjectSet, type RelationTuple, type Subject, type SubjectId, type SubjectSet, subjectOf, } from './subjects/subject';
28
+ export { type Clock, fixedClock, systemClock } from './time/clock';
29
+ export { type Duration, parseDuration } from './time/duration';
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,cAAc,cAAc,CAAC;AAC7B,OAAO,EACN,eAAe,EACf,KAAK,iBAAiB,EACtB,kBAAkB,EAClB,KAAK,KAAK,EACV,UAAU,EACV,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,KAAK,EAAE,EACP,IAAI,EACJ,QAAQ,EACR,MAAM,GACN,MAAM,UAAU,CAAC;AAClB,OAAO,EACN,KAAK,UAAU,EACf,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,SAAS,GACT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,YAAY,EACZ,aAAa,EACb,WAAW,EACX,YAAY,EACZ,UAAU,GACV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,KAAK,MAAM,EACX,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,UAAU,EACf,SAAS,GACT,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,KAAK,QAAQ,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}