@gramota/issuer 0.2.0 → 0.3.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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/issuer.d.ts +23 -3
- package/dist/issuer.d.ts.map +1 -1
- package/dist/issuer.js +69 -4
- package/dist/issuer.js.map +1 -1
- package/dist/types.d.ts +49 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Issuer, type IssuerCredentialsApi } from "./issuer.js";
|
|
2
|
-
export { IssuerError, type IssuerConfig, type IssuerErrorCode, type IssueOptions, type IssueResult, } from "./types.js";
|
|
2
|
+
export { IssuerError, type BatchIssueEntry, type BatchIssueOptions, type IssuerConfig, type IssuerErrorCode, type IssueOptions, type IssueResult, } from "./types.js";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EACL,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EACL,WAAW,EACX,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA6B,MAAM,aAAa,CAAC;AAChE,OAAO,EACL,WAAW,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA6B,MAAM,aAAa,CAAC;AAChE,OAAO,EACL,WAAW,GAOZ,MAAM,YAAY,CAAC"}
|
package/dist/issuer.d.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { type JsonWebKey } from "@gramota/jose";
|
|
2
|
-
import { type IssueOptions, type IssueResult, type IssuerConfig } from "./types.js";
|
|
2
|
+
import { type BatchIssueOptions, type IssueOptions, type IssueResult, type IssuerConfig } from "./types.js";
|
|
3
3
|
/** Stripe-style sub-API for credential operations.
|
|
4
4
|
* `issuer.credentials.X(...)`. */
|
|
5
5
|
export interface IssuerCredentialsApi {
|
|
6
6
|
/** Issue a single SD-JWT-VC credential bound to a holder. */
|
|
7
7
|
issue(options: IssueOptions): Promise<IssueResult>;
|
|
8
|
+
/** Issue N credentials in a batch, one per holder-key entry — the
|
|
9
|
+
* OID4VCI Draft 14/15 batch flow. The EU reference wallet asks for
|
|
10
|
+
* `numberOfCredentials = 10` so it can use a fresh credential per
|
|
11
|
+
* presentation (one-time use, unlinkable). Each entry gets its own
|
|
12
|
+
* `cnf.jwk`, fresh disclosure salts, and a distinct credentialId. */
|
|
13
|
+
issueBatch(options: BatchIssueOptions): Promise<readonly IssueResult[]>;
|
|
8
14
|
}
|
|
9
15
|
/**
|
|
10
16
|
* The issuer role per IETF SD-JWT-VC §3.
|
|
@@ -33,8 +39,8 @@ export declare class Issuer {
|
|
|
33
39
|
private readonly kid;
|
|
34
40
|
private readonly typ;
|
|
35
41
|
private readonly hashAlg;
|
|
36
|
-
/** Credential operations. `issuer.credentials.{issue}(...)`.
|
|
37
|
-
* `holder.credentials.*` for stylistic symmetry across the SDK. */
|
|
42
|
+
/** Credential operations. `issuer.credentials.{issue,issueBatch}(...)`.
|
|
43
|
+
* Mirrors `holder.credentials.*` for stylistic symmetry across the SDK. */
|
|
38
44
|
readonly credentials: IssuerCredentialsApi;
|
|
39
45
|
constructor(config: IssuerConfig);
|
|
40
46
|
/** Issue a single SD-JWT-VC credential bound to a holder.
|
|
@@ -42,6 +48,20 @@ export declare class Issuer {
|
|
|
42
48
|
* Equivalent to `issuer.credentials.issue(options)`. Both shapes are
|
|
43
49
|
* stable; pick whichever reads better at the call site. */
|
|
44
50
|
issue(options: IssueOptions): Promise<IssueResult>;
|
|
51
|
+
/** Issue N credentials in a batch — OID4VCI Draft 14/15 batch flow.
|
|
52
|
+
*
|
|
53
|
+
* Equivalent to `issuer.credentials.issueBatch(options)`. Each entry in
|
|
54
|
+
* `options.credentials` produces one independent credential bound to
|
|
55
|
+
* that entry's `holderKey`, with fresh disclosure salts (so two
|
|
56
|
+
* credentials over the same claims are unlinkable on the wire) and a
|
|
57
|
+
* distinct credentialId. Shared options (subject, vct, expiry, …)
|
|
58
|
+
* apply to every credential.
|
|
59
|
+
*
|
|
60
|
+
* The EU reference wallet uses this to mint pools of one-time-use
|
|
61
|
+
* credentials so each presentation reveals a fresh token rather than
|
|
62
|
+
* a long-lived one. */
|
|
63
|
+
issueBatch(options: BatchIssueOptions): Promise<readonly IssueResult[]>;
|
|
64
|
+
private issueBatchImpl;
|
|
45
65
|
private issueImpl;
|
|
46
66
|
/** The issuer's public JWK — useful to publish at /.well-known/jwks.json. */
|
|
47
67
|
get publicKey(): JsonWebKey;
|
package/dist/issuer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issuer.d.ts","sourceRoot":"","sources":["../src/issuer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,UAAU,EAAe,MAAM,eAAe,CAAC;AACvE,OAAO,
|
|
1
|
+
{"version":3,"file":"issuer.d.ts","sourceRoot":"","sources":["../src/issuer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,UAAU,EAAe,MAAM,eAAe,CAAC;AACvE,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AAKpB;mCACmC;AACnC,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACnD;;;;yEAIqE;IACrE,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAAC;CACzE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,MAAM;IACjB;4EACwE;IACxE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,sCAAsC;IACtC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAE9C;+EAC2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;gBAE/B,MAAM,EAAE,YAAY;IAkBhC;;;+DAG2D;IACrD,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAIxD;;;;;;;;;;;2BAWuB;IACjB,UAAU,CACd,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC;YAIpB,cAAc;YAiCd,SAAS;IAsDvB,6EAA6E;IAC7E,IAAI,SAAS,IAAI,UAAU,CAE1B;IAED,4DAA4D;IAC5D,IAAI,QAAQ,IAAI,MAAM,CAErB;CACF"}
|
package/dist/issuer.js
CHANGED
|
@@ -31,8 +31,8 @@ export class Issuer {
|
|
|
31
31
|
kid;
|
|
32
32
|
typ;
|
|
33
33
|
hashAlg;
|
|
34
|
-
/** Credential operations. `issuer.credentials.{issue}(...)`.
|
|
35
|
-
* `holder.credentials.*` for stylistic symmetry across the SDK. */
|
|
34
|
+
/** Credential operations. `issuer.credentials.{issue,issueBatch}(...)`.
|
|
35
|
+
* Mirrors `holder.credentials.*` for stylistic symmetry across the SDK. */
|
|
36
36
|
credentials;
|
|
37
37
|
constructor(config) {
|
|
38
38
|
if (typeof config.issuerId !== "string" || config.issuerId.length === 0) {
|
|
@@ -43,10 +43,11 @@ export class Issuer {
|
|
|
43
43
|
this.kid = config.kid;
|
|
44
44
|
this.typ = config.typ;
|
|
45
45
|
this.hashAlg = config.hashAlg;
|
|
46
|
-
// Build the namespaced sub-API. `issuer.credentials.issue`
|
|
47
|
-
// `issuer.issue` both resolve here — single
|
|
46
|
+
// Build the namespaced sub-API. `issuer.credentials.{issue,issueBatch}`
|
|
47
|
+
// and `issuer.{issue,issueBatch}` both resolve here — single impl per op.
|
|
48
48
|
this.credentials = {
|
|
49
49
|
issue: (options) => this.issueImpl(options),
|
|
50
|
+
issueBatch: (options) => this.issueBatchImpl(options),
|
|
50
51
|
};
|
|
51
52
|
}
|
|
52
53
|
/** Issue a single SD-JWT-VC credential bound to a holder.
|
|
@@ -56,6 +57,44 @@ export class Issuer {
|
|
|
56
57
|
async issue(options) {
|
|
57
58
|
return this.issueImpl(options);
|
|
58
59
|
}
|
|
60
|
+
/** Issue N credentials in a batch — OID4VCI Draft 14/15 batch flow.
|
|
61
|
+
*
|
|
62
|
+
* Equivalent to `issuer.credentials.issueBatch(options)`. Each entry in
|
|
63
|
+
* `options.credentials` produces one independent credential bound to
|
|
64
|
+
* that entry's `holderKey`, with fresh disclosure salts (so two
|
|
65
|
+
* credentials over the same claims are unlinkable on the wire) and a
|
|
66
|
+
* distinct credentialId. Shared options (subject, vct, expiry, …)
|
|
67
|
+
* apply to every credential.
|
|
68
|
+
*
|
|
69
|
+
* The EU reference wallet uses this to mint pools of one-time-use
|
|
70
|
+
* credentials so each presentation reveals a fresh token rather than
|
|
71
|
+
* a long-lived one. */
|
|
72
|
+
async issueBatch(options) {
|
|
73
|
+
return this.issueBatchImpl(options);
|
|
74
|
+
}
|
|
75
|
+
async issueBatchImpl(options) {
|
|
76
|
+
if (!Array.isArray(options.credentials) || options.credentials.length === 0) {
|
|
77
|
+
throw new IssuerError("issuer.batch_empty", "issueBatch: credentials must be a non-empty array");
|
|
78
|
+
}
|
|
79
|
+
// Pin `issuedAt` once so every credential in the batch reports the same
|
|
80
|
+
// iat. Without this, two credentials issued in the same logical batch
|
|
81
|
+
// could differ by a second — fine for spec, awkward for audit logs.
|
|
82
|
+
const sharedIssuedAt = options.issuedAt ?? Math.floor(Date.now() / 1000);
|
|
83
|
+
// Validate shared shape once via a representative `IssueOptions` (with
|
|
84
|
+
// a placeholder holderKey from the first entry) so errors like
|
|
85
|
+
// `disclosable_missing` and `expiry_conflict` surface once with a
|
|
86
|
+
// clean stack, not N times wrapped in batch noise.
|
|
87
|
+
const head = options.credentials[0];
|
|
88
|
+
validate(toIssueOptions(options, head, sharedIssuedAt));
|
|
89
|
+
// Issue each credential. We do this sequentially rather than via
|
|
90
|
+
// Promise.all to keep error reporting deterministic — a failure on
|
|
91
|
+
// entry 5 reports as "entry 5" and we stop, rather than racing.
|
|
92
|
+
const results = [];
|
|
93
|
+
for (const entry of options.credentials) {
|
|
94
|
+
results.push(await this.issueImpl(toIssueOptions(options, entry, sharedIssuedAt)));
|
|
95
|
+
}
|
|
96
|
+
return results;
|
|
97
|
+
}
|
|
59
98
|
async issueImpl(options) {
|
|
60
99
|
validate(options);
|
|
61
100
|
const issuedAt = options.issuedAt ?? Math.floor(Date.now() / 1000);
|
|
@@ -141,6 +180,32 @@ function normalizeIssuerSigner(config) {
|
|
|
141
180
|
}
|
|
142
181
|
throw new TypeError("Issuer: pass either { privateKey, publicKey, alg } (raw shorthand) or { signer } (production)");
|
|
143
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Merge shared batch options with one per-credential entry into the
|
|
185
|
+
* `IssueOptions` shape that `issueImpl` consumes. Pure function — no
|
|
186
|
+
* side effects — so it's safe to call once per entry in a tight loop.
|
|
187
|
+
*
|
|
188
|
+
* Conditional spreads honour `exactOptionalPropertyTypes`: a property is
|
|
189
|
+
* either set (with a defined value) or absent, never `undefined`.
|
|
190
|
+
*/
|
|
191
|
+
function toIssueOptions(shared, entry, sharedIssuedAt) {
|
|
192
|
+
return {
|
|
193
|
+
subject: shared.subject,
|
|
194
|
+
vct: shared.vct,
|
|
195
|
+
holderKey: entry.holderKey,
|
|
196
|
+
issuedAt: sharedIssuedAt,
|
|
197
|
+
...(shared.selectivelyDisclosable !== undefined
|
|
198
|
+
? { selectivelyDisclosable: shared.selectivelyDisclosable }
|
|
199
|
+
: {}),
|
|
200
|
+
...(shared.expiresIn !== undefined ? { expiresIn: shared.expiresIn } : {}),
|
|
201
|
+
...(shared.expiresAt !== undefined ? { expiresAt: shared.expiresAt } : {}),
|
|
202
|
+
...(shared.notBefore !== undefined ? { notBefore: shared.notBefore } : {}),
|
|
203
|
+
...(entry.credentialId !== undefined
|
|
204
|
+
? { credentialId: entry.credentialId }
|
|
205
|
+
: {}),
|
|
206
|
+
...(entry.status !== undefined ? { status: entry.status } : {}),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
144
209
|
// ---------------------------------------------------------------------------
|
|
145
210
|
// validation
|
|
146
211
|
// ---------------------------------------------------------------------------
|
package/dist/issuer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issuer.js","sourceRoot":"","sources":["../src/issuer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAgB,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAgC,MAAM,eAAe,CAAC;AACvE,OAAO,EACL,WAAW,
|
|
1
|
+
{"version":3,"file":"issuer.js","sourceRoot":"","sources":["../src/issuer.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -73,8 +73,56 @@ export interface IssueResult {
|
|
|
73
73
|
/** Computed expiry (if `expiresIn` or `expiresAt` was set). */
|
|
74
74
|
expiresAt: number | undefined;
|
|
75
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Per-credential binding for `issueBatch`. Everything that varies *across*
|
|
78
|
+
* credentials in the batch goes here; everything shared (subject, vct,
|
|
79
|
+
* expiry, …) sits at the top level of {@link BatchIssueOptions}.
|
|
80
|
+
*/
|
|
81
|
+
export interface BatchIssueEntry {
|
|
82
|
+
/** Holder's PUBLIC JWK — bound into this credential's `cnf.jwk`. Each
|
|
83
|
+
* entry must have a distinct holder key for one-time-use unlinkability. */
|
|
84
|
+
holderKey: JsonWebKey;
|
|
85
|
+
/** Override the generated credential ID (default: random UUID v4 per entry). */
|
|
86
|
+
credentialId?: string;
|
|
87
|
+
/** Per-credential `status` claim — typical use is to allocate a distinct
|
|
88
|
+
* Token Status List index for each one-time credential so they can be
|
|
89
|
+
* revoked independently. */
|
|
90
|
+
status?: Readonly<Record<string, unknown>>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Options for `issuer.issueBatch()` (OID4VCI Draft 14/15 batch issuance).
|
|
94
|
+
*
|
|
95
|
+
* Shared across the batch: subject, vct, expiry, notBefore, issuedAt,
|
|
96
|
+
* selectivelyDisclosable.
|
|
97
|
+
*
|
|
98
|
+
* Per-credential: `credentials[i]` (holderKey, optional credentialId,
|
|
99
|
+
* optional status).
|
|
100
|
+
*/
|
|
101
|
+
export interface BatchIssueOptions {
|
|
102
|
+
/** Claims shared by every credential in the batch. Same semantics as
|
|
103
|
+
* {@link IssueOptions.subject}. */
|
|
104
|
+
subject: Readonly<Record<string, unknown>>;
|
|
105
|
+
/** SD-JWT-VC type identifier — shared across the batch. */
|
|
106
|
+
vct: string;
|
|
107
|
+
/** Names of `subject` keys to make selectively disclosable. Validated
|
|
108
|
+
* once against `subject`; applies to every credential. Each credential
|
|
109
|
+
* gets fresh random salts (so two credentials over the same data are
|
|
110
|
+
* unlinkable on the wire). */
|
|
111
|
+
selectivelyDisclosable?: readonly string[];
|
|
112
|
+
/** Shared `expiresIn`. Mutually exclusive with `expiresAt`. */
|
|
113
|
+
expiresIn?: number;
|
|
114
|
+
/** Shared absolute `expiresAt`. Mutually exclusive with `expiresIn`. */
|
|
115
|
+
expiresAt?: number;
|
|
116
|
+
/** Shared `nbf`. */
|
|
117
|
+
notBefore?: number;
|
|
118
|
+
/** Shared `iat`. Defaults to `floor(Date.now()/1000)` evaluated *once*
|
|
119
|
+
* for the whole batch (so every credential reports the same iat). */
|
|
120
|
+
issuedAt?: number;
|
|
121
|
+
/** One entry per credential to issue. Length ≥ 1. */
|
|
122
|
+
credentials: readonly BatchIssueEntry[];
|
|
123
|
+
}
|
|
76
124
|
/** Stable codes for `IssuerError`. */
|
|
77
|
-
export type IssuerErrorCode = "issuer.subject_invalid" | "issuer.holder_key_required" | "issuer.vct_required" | "issuer.expiry_conflict" | "issuer.expiry_invalid" | "issuer.disclosable_missing" | "issuer.reserved_claim_in_subject";
|
|
125
|
+
export type IssuerErrorCode = "issuer.subject_invalid" | "issuer.holder_key_required" | "issuer.vct_required" | "issuer.expiry_conflict" | "issuer.expiry_invalid" | "issuer.disclosable_missing" | "issuer.reserved_claim_in_subject" | "issuer.batch_empty";
|
|
78
126
|
export declare class IssuerError extends Error {
|
|
79
127
|
readonly name = "IssuerError";
|
|
80
128
|
readonly code: IssuerErrorCode;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEhE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,iBAAiB,GACzB;IACE,qDAAqD;IACrD,UAAU,EAAE,UAAU,CAAC;IACvB,uDAAuD;IACvD,SAAS,EAAE,UAAU,CAAC;IACtB,2DAA2D;IAC3D,GAAG,EAAE,YAAY,CAAC;CACnB,GACD;IACE,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEN,2EAA2E;AAC3E,MAAM,MAAM,YAAY,GAAG,iBAAiB,GAAG;IAC7C,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qEAAqE;IACrE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B;;yDAEqD;IACrD,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3C;2EACuE;IACvE,sBAAsB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;mEAC+D;IAC/D,SAAS,EAAE,UAAU,CAAC;IACtB;;0DAEsD;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ;sBACkB;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3C,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,kCAAkC;AAClC,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;IACxC,+DAA+D;IAC/D,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED,sCAAsC;AACtC,MAAM,MAAM,eAAe,GACvB,wBAAwB,GACxB,4BAA4B,GAC5B,qBAAqB,GACrB,wBAAwB,GACxB,uBAAuB,GACvB,4BAA4B,GAC5B,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA+IA,MAAM,OAAO,WAAY,SAAQ,KAAK;IAClB,IAAI,GAAG,aAAa,CAAC;IAC9B,IAAI,CAAkB;IAC/B,YACE,IAAqB,EACrB,OAAe,EACf,OAA6B;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,OAAO,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YAChC,IAA4B,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QACtD,CAAC;IACH,CAAC;CACF"}
|