@atproto/syntax 0.4.1 → 0.4.3
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/CHANGELOG.md +18 -0
- package/LICENSE.txt +1 -1
- package/dist/at-identifier.d.ts +6 -0
- package/dist/at-identifier.d.ts.map +1 -0
- package/dist/at-identifier.js +28 -0
- package/dist/at-identifier.js.map +1 -0
- package/dist/aturi.d.ts +8 -6
- package/dist/aturi.d.ts.map +1 -1
- package/dist/aturi.js +41 -83
- package/dist/aturi.js.map +1 -1
- package/dist/aturi_validation.d.ts +6 -2
- package/dist/aturi_validation.d.ts.map +1 -1
- package/dist/aturi_validation.js +66 -60
- package/dist/aturi_validation.js.map +1 -1
- package/dist/datetime.d.ts +11 -4
- package/dist/datetime.d.ts.map +1 -1
- package/dist/datetime.js +22 -25
- package/dist/datetime.js.map +1 -1
- package/dist/did.d.ts +4 -2
- package/dist/did.d.ts.map +1 -1
- package/dist/did.js +24 -19
- package/dist/did.js.map +1 -1
- package/dist/handle.d.ts +7 -6
- package/dist/handle.d.ts.map +1 -1
- package/dist/handle.js +32 -35
- package/dist/handle.js.map +1 -1
- package/dist/index.d.ts +10 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -21
- package/dist/index.js.map +1 -1
- package/dist/language.d.ts +18 -0
- package/dist/language.d.ts.map +1 -0
- package/dist/language.js +30 -0
- package/dist/language.js.map +1 -0
- package/dist/nsid.d.ts +6 -5
- package/dist/nsid.d.ts.map +1 -1
- package/dist/nsid.js +6 -11
- package/dist/nsid.js.map +1 -1
- package/dist/recordkey.d.ts +3 -2
- package/dist/recordkey.d.ts.map +1 -1
- package/dist/recordkey.js +33 -22
- package/dist/recordkey.js.map +1 -1
- package/dist/tid.d.ts +3 -2
- package/dist/tid.d.ts.map +1 -1
- package/dist/tid.js +10 -10
- package/dist/tid.js.map +1 -1
- package/dist/uri.d.ts +3 -0
- package/dist/uri.d.ts.map +1 -0
- package/dist/uri.js +7 -0
- package/dist/uri.js.map +1 -0
- package/package.json +7 -4
- package/src/at-identifier.ts +33 -0
- package/src/aturi.ts +59 -46
- package/src/aturi_validation.ts +78 -51
- package/src/datetime.ts +26 -14
- package/src/did.ts +28 -15
- package/src/handle.ts +29 -26
- package/src/index.ts +10 -7
- package/src/language.ts +39 -0
- package/src/nsid.ts +14 -8
- package/src/recordkey.ts +42 -17
- package/src/tid.ts +9 -5
- package/src/uri.ts +5 -0
- package/tests/aturi.test.ts +3 -2
- package/tests/datetime.test.ts +1 -0
- package/tests/did.test.ts +1 -0
- package/tests/handle.test.ts +1 -0
- package/tests/language.test.ts +88 -0
- package/tests/nsid.test.ts +1 -0
- package/tests/recordkey.test.ts +1 -0
- package/tests/tid.test.ts +1 -0
- package/tsconfig.build.json +6 -2
- package/tsconfig.build.tsbuildinfo +1 -1
- package/tsconfig.tests.json +6 -4
- package/vitest.config.ts +5 -0
- package/jest.config.js +0 -7
- package/tsconfig.tests.tsbuildinfo +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @atproto/syntax
|
|
2
2
|
|
|
3
|
+
## 0.4.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#4571](https://github.com/bluesky-social/atproto/pull/4571) [`99963d0`](https://github.com/bluesky-social/atproto/commit/99963d002a9e030e79aed5fba700e0a68f31e101) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add new `isValidAtUri` utility
|
|
8
|
+
|
|
9
|
+
- [#4571](https://github.com/bluesky-social/atproto/pull/4571) [`99963d0`](https://github.com/bluesky-social/atproto/commit/99963d002a9e030e79aed5fba700e0a68f31e101) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add `isValidUri` utility
|
|
10
|
+
|
|
11
|
+
- [#4571](https://github.com/bluesky-social/atproto/pull/4571) [`99963d0`](https://github.com/bluesky-social/atproto/commit/99963d002a9e030e79aed5fba700e0a68f31e101) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Improve typing of type assertion utilities
|
|
12
|
+
|
|
13
|
+
- [#4571](https://github.com/bluesky-social/atproto/pull/4571) [`99963d0`](https://github.com/bluesky-social/atproto/commit/99963d002a9e030e79aed5fba700e0a68f31e101) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add BCP47 language validation and parsing utilities
|
|
14
|
+
|
|
15
|
+
## 0.4.2
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [#4389](https://github.com/bluesky-social/atproto/pull/4389) [`bcae2b7`](https://github.com/bluesky-social/atproto/commit/bcae2b77b68da6dc2ec202651c8bf41fd5769f69) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Improve typing of various string formats
|
|
20
|
+
|
|
3
21
|
## 0.4.1
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/LICENSE.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Dual MIT/Apache-2.0 License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2022-
|
|
3
|
+
Copyright (c) 2022-2026 Bluesky Social PBC, and Contributors
|
|
4
4
|
|
|
5
5
|
Except as otherwise noted in individual files, this software is licensed under the MIT license (<http://opensource.org/licenses/MIT>), or the Apache License, Version 2.0 (<http://www.apache.org/licenses/LICENSE-2.0>).
|
|
6
6
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DidString } from './did.js';
|
|
2
|
+
import { HandleString } from './handle.js';
|
|
3
|
+
export type AtIdentifierString = DidString | HandleString;
|
|
4
|
+
export declare function ensureValidAtIdentifier(input: string): asserts input is AtIdentifierString;
|
|
5
|
+
export declare function isValidAtIdentifier<I extends string>(input: I): input is I & AtIdentifierString;
|
|
6
|
+
//# sourceMappingURL=at-identifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"at-identifier.d.ts","sourceRoot":"","sources":["../src/at-identifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAmC,MAAM,UAAU,CAAA;AACrE,OAAO,EACL,YAAY,EAIb,MAAM,aAAa,CAAA;AAEpB,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,YAAY,CAAA;AAEzD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,KAAK,IAAI,kBAAkB,CAUrC;AAED,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAClD,KAAK,EAAE,CAAC,GACP,KAAK,IAAI,CAAC,GAAG,kBAAkB,CAMjC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ensureValidAtIdentifier = ensureValidAtIdentifier;
|
|
4
|
+
exports.isValidAtIdentifier = isValidAtIdentifier;
|
|
5
|
+
const did_js_1 = require("./did.js");
|
|
6
|
+
const handle_js_1 = require("./handle.js");
|
|
7
|
+
function ensureValidAtIdentifier(input) {
|
|
8
|
+
try {
|
|
9
|
+
if (input.startsWith('did:')) {
|
|
10
|
+
(0, did_js_1.ensureValidDidRegex)(input);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
(0, handle_js_1.ensureValidHandleRegex)(input);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
catch (cause) {
|
|
17
|
+
throw new handle_js_1.InvalidHandleError('Invalid DID or handle', { cause });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function isValidAtIdentifier(input) {
|
|
21
|
+
if (input.startsWith('did:')) {
|
|
22
|
+
return (0, did_js_1.isValidDid)(input);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return (0, handle_js_1.isValidHandle)(input);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=at-identifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"at-identifier.js","sourceRoot":"","sources":["../src/at-identifier.ts"],"names":[],"mappings":";;AAUA,0DAYC;AAED,kDAQC;AAhCD,qCAAqE;AACrE,2CAKoB;AAIpB,SAAgB,uBAAuB,CACrC,KAAa;IAEb,IAAI,CAAC;QACH,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,IAAA,4BAAmB,EAAC,KAAK,CAAC,CAAA;QAC5B,CAAC;aAAM,CAAC;YACN,IAAA,kCAAsB,EAAC,KAAK,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,8BAAkB,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IAClE,CAAC;AACH,CAAC;AAED,SAAgB,mBAAmB,CACjC,KAAQ;IAER,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAA,mBAAU,EAAC,KAAK,CAAC,CAAA;IAC1B,CAAC;SAAM,CAAC;QACN,OAAO,IAAA,yBAAa,EAAC,KAAK,CAAC,CAAA;IAC7B,CAAC;AACH,CAAC","sourcesContent":["import { DidString, ensureValidDidRegex, isValidDid } from './did.js'\nimport {\n HandleString,\n InvalidHandleError,\n ensureValidHandleRegex,\n isValidHandle,\n} from './handle.js'\n\nexport type AtIdentifierString = DidString | HandleString\n\nexport function ensureValidAtIdentifier(\n input: string,\n): asserts input is AtIdentifierString {\n try {\n if (input.startsWith('did:')) {\n ensureValidDidRegex(input)\n } else {\n ensureValidHandleRegex(input)\n }\n } catch (cause) {\n throw new InvalidHandleError('Invalid DID or handle', { cause })\n }\n}\n\nexport function isValidAtIdentifier<I extends string>(\n input: I,\n): input is I & AtIdentifierString {\n if (input.startsWith('did:')) {\n return isValidDid(input)\n } else {\n return isValidHandle(input)\n }\n}\n"]}
|
package/dist/aturi.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import { AtIdentifierString } from './at-identifier.js';
|
|
2
|
+
import { AtUriString } from './aturi_validation.js';
|
|
3
|
+
export * from './aturi_validation.js';
|
|
2
4
|
export declare const ATP_URI_REGEX: RegExp;
|
|
3
5
|
export declare class AtUri {
|
|
4
6
|
hash: string;
|
|
5
|
-
host:
|
|
7
|
+
host: AtIdentifierString;
|
|
6
8
|
pathname: string;
|
|
7
9
|
searchParams: URLSearchParams;
|
|
8
|
-
constructor(uri: string, base?: string);
|
|
10
|
+
constructor(uri: string, base?: string | AtUri);
|
|
9
11
|
static make(handleOrDid: string, collection?: string, rkey?: string): AtUri;
|
|
10
12
|
get protocol(): string;
|
|
11
|
-
get origin(): string
|
|
13
|
+
get origin(): `at://did:${string}:${string}` | `at://${string}.${string}`;
|
|
12
14
|
get hostname(): string;
|
|
13
15
|
set hostname(v: string);
|
|
14
16
|
get search(): string;
|
|
@@ -17,7 +19,7 @@ export declare class AtUri {
|
|
|
17
19
|
set collection(v: string);
|
|
18
20
|
get rkey(): string;
|
|
19
21
|
set rkey(v: string);
|
|
20
|
-
get href():
|
|
21
|
-
toString():
|
|
22
|
+
get href(): AtUriString;
|
|
23
|
+
toString(): AtUriString;
|
|
22
24
|
}
|
|
23
25
|
//# sourceMappingURL=aturi.d.ts.map
|
package/dist/aturi.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aturi.d.ts","sourceRoot":"","sources":["../src/aturi.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"aturi.d.ts","sourceRoot":"","sources":["../src/aturi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA2B,MAAM,oBAAoB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAGnD,cAAc,uBAAuB,CAAA;AAErC,eAAO,MAAM,aAAa,QAEyE,CAAA;AAInG,qBAAa,KAAK;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,kBAAkB,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,eAAe,CAAA;gBAEjB,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK;IAgB9C,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;IAOnE,IAAI,QAAQ,WAEX;IAED,IAAI,MAAM,gEAET;IAED,IAAI,QAAQ,IAII,MAAM,CAFrB;IAED,IAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,EAGrB;IAED,IAAI,MAAM,IAII,MAAM,CAFnB;IAED,IAAI,MAAM,CAAC,CAAC,EAAE,MAAM,EAEnB;IAED,IAAI,UAAU,IAII,MAAM,CAFvB;IAED,IAAI,UAAU,CAAC,CAAC,EAAE,MAAM,EAKvB;IAED,IAAI,IAAI,IAII,MAAM,CAFjB;IAED,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,EAKjB;IAED,IAAI,IAAI,gBAEP;IAED,QAAQ,IAAI,WAAW;CAexB"}
|
package/dist/aturi.js
CHANGED
|
@@ -1,73 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
3
|
exports.AtUri = exports.ATP_URI_REGEX = void 0;
|
|
18
|
-
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const at_identifier_js_1 = require("./at-identifier.js");
|
|
6
|
+
const nsid_js_1 = require("./nsid.js");
|
|
7
|
+
tslib_1.__exportStar(require("./aturi_validation.js"), exports);
|
|
19
8
|
exports.ATP_URI_REGEX =
|
|
20
9
|
// proto- --did-------------- --name---------------- --path---- --query-- --hash--
|
|
21
10
|
/^(at:\/\/)?((?:did:[a-z0-9:%-]+)|(?:[a-z0-9][a-z0-9.:-]*))(\/[^?#\s]*)?(\?[^#\s]+)?(#[^\s]+)?$/i;
|
|
22
11
|
// --path----- --query-- --hash--
|
|
23
12
|
const RELATIVE_REGEX = /^(\/[^?#\s]*)?(\?[^#\s]+)?(#[^\s]+)?$/i;
|
|
24
13
|
class AtUri {
|
|
14
|
+
hash;
|
|
15
|
+
host;
|
|
16
|
+
pathname;
|
|
17
|
+
searchParams;
|
|
25
18
|
constructor(uri, base) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
enumerable: true,
|
|
34
|
-
configurable: true,
|
|
35
|
-
writable: true,
|
|
36
|
-
value: void 0
|
|
37
|
-
});
|
|
38
|
-
Object.defineProperty(this, "pathname", {
|
|
39
|
-
enumerable: true,
|
|
40
|
-
configurable: true,
|
|
41
|
-
writable: true,
|
|
42
|
-
value: void 0
|
|
43
|
-
});
|
|
44
|
-
Object.defineProperty(this, "searchParams", {
|
|
45
|
-
enumerable: true,
|
|
46
|
-
configurable: true,
|
|
47
|
-
writable: true,
|
|
48
|
-
value: void 0
|
|
49
|
-
});
|
|
50
|
-
let parsed;
|
|
51
|
-
if (base) {
|
|
52
|
-
parsed = parse(base);
|
|
53
|
-
if (!parsed) {
|
|
54
|
-
throw new Error(`Invalid at uri: ${base}`);
|
|
55
|
-
}
|
|
56
|
-
const relativep = parseRelative(uri);
|
|
57
|
-
if (!relativep) {
|
|
58
|
-
throw new Error(`Invalid path: ${uri}`);
|
|
59
|
-
}
|
|
60
|
-
Object.assign(parsed, relativep);
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
parsed = parse(uri);
|
|
64
|
-
if (!parsed) {
|
|
65
|
-
throw new Error(`Invalid at uri: ${uri}`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
this.hash = parsed.hash;
|
|
19
|
+
const parsed = base !== undefined
|
|
20
|
+
? typeof base === 'string'
|
|
21
|
+
? Object.assign(parse(base), parseRelative(uri))
|
|
22
|
+
: Object.assign({ host: base.host }, parseRelative(uri))
|
|
23
|
+
: parse(uri);
|
|
24
|
+
(0, at_identifier_js_1.ensureValidAtIdentifier)(parsed.host);
|
|
25
|
+
this.hash = parsed.hash ?? '';
|
|
69
26
|
this.host = parsed.host;
|
|
70
|
-
this.pathname = parsed.pathname;
|
|
27
|
+
this.pathname = parsed.pathname ?? '';
|
|
71
28
|
this.searchParams = parsed.searchParams;
|
|
72
29
|
}
|
|
73
30
|
static make(handleOrDid, collection, rkey) {
|
|
@@ -88,6 +45,7 @@ class AtUri {
|
|
|
88
45
|
return this.host;
|
|
89
46
|
}
|
|
90
47
|
set hostname(v) {
|
|
48
|
+
(0, at_identifier_js_1.ensureValidAtIdentifier)(v);
|
|
91
49
|
this.host = v;
|
|
92
50
|
}
|
|
93
51
|
get search() {
|
|
@@ -100,6 +58,7 @@ class AtUri {
|
|
|
100
58
|
return this.pathname.split('/').filter(Boolean)[0] || '';
|
|
101
59
|
}
|
|
102
60
|
set collection(v) {
|
|
61
|
+
(0, nsid_js_1.ensureValidNsid)(v);
|
|
103
62
|
const parts = this.pathname.split('/').filter(Boolean);
|
|
104
63
|
parts[0] = v;
|
|
105
64
|
this.pathname = parts.join('/');
|
|
@@ -109,8 +68,7 @@ class AtUri {
|
|
|
109
68
|
}
|
|
110
69
|
set rkey(v) {
|
|
111
70
|
const parts = this.pathname.split('/').filter(Boolean);
|
|
112
|
-
|
|
113
|
-
parts[0] = 'undefined';
|
|
71
|
+
parts[0] ||= 'undefined';
|
|
114
72
|
parts[1] = v;
|
|
115
73
|
this.pathname = parts.join('/');
|
|
116
74
|
}
|
|
@@ -122,9 +80,9 @@ class AtUri {
|
|
|
122
80
|
if (!path.startsWith('/')) {
|
|
123
81
|
path = `/${path}`;
|
|
124
82
|
}
|
|
125
|
-
let qs =
|
|
126
|
-
if (
|
|
127
|
-
qs = `?${
|
|
83
|
+
let qs = '';
|
|
84
|
+
if (this.searchParams.size) {
|
|
85
|
+
qs = `?${this.searchParams.toString()}`;
|
|
128
86
|
}
|
|
129
87
|
let hash = this.hash;
|
|
130
88
|
if (hash && !hash.startsWith('#')) {
|
|
@@ -135,26 +93,26 @@ class AtUri {
|
|
|
135
93
|
}
|
|
136
94
|
exports.AtUri = AtUri;
|
|
137
95
|
function parse(str) {
|
|
138
|
-
const match = exports.ATP_URI_REGEX
|
|
139
|
-
if (match) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
96
|
+
const match = str.match(exports.ATP_URI_REGEX);
|
|
97
|
+
if (!match) {
|
|
98
|
+
throw new Error(`Invalid AT uri: ${str}`);
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
host: match[2],
|
|
102
|
+
hash: match[5],
|
|
103
|
+
pathname: match[3],
|
|
104
|
+
searchParams: new URLSearchParams(match[4]),
|
|
105
|
+
};
|
|
148
106
|
}
|
|
149
107
|
function parseRelative(str) {
|
|
150
|
-
const match =
|
|
151
|
-
if (match) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
108
|
+
const match = str.match(RELATIVE_REGEX);
|
|
109
|
+
if (!match) {
|
|
110
|
+
throw new Error(`Invalid path: ${str}`);
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
hash: match[3],
|
|
114
|
+
pathname: match[1],
|
|
115
|
+
searchParams: new URLSearchParams(match[2]),
|
|
116
|
+
};
|
|
159
117
|
}
|
|
160
118
|
//# sourceMappingURL=aturi.js.map
|
package/dist/aturi.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aturi.js","sourceRoot":"","sources":["../src/aturi.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"aturi.js","sourceRoot":"","sources":["../src/aturi.ts"],"names":[],"mappings":"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","sourcesContent":["import { AtIdentifierString, ensureValidAtIdentifier } from './at-identifier.js'\nimport { AtUriString } from './aturi_validation.js'\nimport { ensureValidNsid } from './nsid.js'\n\nexport * from './aturi_validation.js'\n\nexport const ATP_URI_REGEX =\n // proto- --did-------------- --name---------------- --path---- --query-- --hash--\n /^(at:\\/\\/)?((?:did:[a-z0-9:%-]+)|(?:[a-z0-9][a-z0-9.:-]*))(\\/[^?#\\s]*)?(\\?[^#\\s]+)?(#[^\\s]+)?$/i\n// --path----- --query-- --hash--\nconst RELATIVE_REGEX = /^(\\/[^?#\\s]*)?(\\?[^#\\s]+)?(#[^\\s]+)?$/i\n\nexport class AtUri {\n hash: string\n host: AtIdentifierString\n pathname: string\n searchParams: URLSearchParams\n\n constructor(uri: string, base?: string | AtUri) {\n const parsed =\n base !== undefined\n ? typeof base === 'string'\n ? Object.assign(parse(base), parseRelative(uri))\n : Object.assign({ host: base.host }, parseRelative(uri))\n : parse(uri)\n\n ensureValidAtIdentifier(parsed.host)\n\n this.hash = parsed.hash ?? ''\n this.host = parsed.host\n this.pathname = parsed.pathname ?? ''\n this.searchParams = parsed.searchParams\n }\n\n static make(handleOrDid: string, collection?: string, rkey?: string) {\n let str = handleOrDid\n if (collection) str += '/' + collection\n if (rkey) str += '/' + rkey\n return new AtUri(str)\n }\n\n get protocol() {\n return 'at:'\n }\n\n get origin() {\n return `at://${this.host}` as const\n }\n\n get hostname() {\n return this.host\n }\n\n set hostname(v: string) {\n ensureValidAtIdentifier(v)\n this.host = v\n }\n\n get search() {\n return this.searchParams.toString()\n }\n\n set search(v: string) {\n this.searchParams = new URLSearchParams(v)\n }\n\n get collection() {\n return this.pathname.split('/').filter(Boolean)[0] || ''\n }\n\n set collection(v: string) {\n ensureValidNsid(v)\n const parts = this.pathname.split('/').filter(Boolean)\n parts[0] = v\n this.pathname = parts.join('/')\n }\n\n get rkey() {\n return this.pathname.split('/').filter(Boolean)[1] || ''\n }\n\n set rkey(v: string) {\n const parts = this.pathname.split('/').filter(Boolean)\n parts[0] ||= 'undefined'\n parts[1] = v\n this.pathname = parts.join('/')\n }\n\n get href() {\n return this.toString()\n }\n\n toString(): AtUriString {\n let path = this.pathname || '/'\n if (!path.startsWith('/')) {\n path = `/${path}`\n }\n let qs = ''\n if (this.searchParams.size) {\n qs = `?${this.searchParams.toString()}`\n }\n let hash = this.hash\n if (hash && !hash.startsWith('#')) {\n hash = `#${hash}`\n }\n return `at://${this.host}${path}${qs}${hash}` as AtUriString\n }\n}\n\nfunction parse(str: string) {\n const match = str.match(ATP_URI_REGEX) as null | {\n 0: string\n 1: string | undefined // proto\n 2: string // host\n 3: string | undefined // path\n 4: string | undefined // query\n 5: string | undefined // hash\n }\n\n if (!match) {\n throw new Error(`Invalid AT uri: ${str}`)\n }\n\n return {\n host: match[2],\n hash: match[5],\n pathname: match[3],\n searchParams: new URLSearchParams(match[4]),\n }\n}\n\nfunction parseRelative(str: string) {\n const match = str.match(RELATIVE_REGEX) as null | {\n 0: string\n 1: string | undefined // path\n 2: string | undefined // query\n 3: string | undefined // hash\n }\n\n if (!match) {\n throw new Error(`Invalid path: ${str}`)\n }\n\n return {\n hash: match[3],\n pathname: match[1],\n searchParams: new URLSearchParams(match[2]),\n }\n}\n"]}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { AtIdentifierString } from './at-identifier.js';
|
|
2
|
+
import { NsidString } from './nsid.js';
|
|
3
|
+
export type AtUriString = `at://${AtIdentifierString}` | `at://${AtIdentifierString}/${NsidString}` | `at://${AtIdentifierString}/${NsidString}/${string}`;
|
|
4
|
+
export declare function ensureValidAtUri<I extends string>(input: I): asserts input is I & AtUriString;
|
|
5
|
+
export declare function ensureValidAtUriRegex<I extends string>(input: I): asserts input is I & AtUriString;
|
|
6
|
+
export declare function isValidAtUri<I extends string>(input: I): input is I & AtUriString;
|
|
3
7
|
//# sourceMappingURL=aturi_validation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aturi_validation.d.ts","sourceRoot":"","sources":["../src/aturi_validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"aturi_validation.d.ts","sourceRoot":"","sources":["../src/aturi_validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA2B,MAAM,oBAAoB,CAAA;AAGhF,OAAO,EAAE,UAAU,EAAe,MAAM,WAAW,CAAA;AAEnD,MAAM,MAAM,WAAW,GACnB,QAAQ,kBAAkB,EAAE,GAC5B,QAAQ,kBAAkB,IAAI,UAAU,EAAE,GAC1C,QAAQ,kBAAkB,IAAI,UAAU,IAAI,MAAM,EAAE,CAAA;AAgBxD,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,EAC/C,KAAK,EAAE,CAAC,GACP,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,WAAW,CAiFlC;AAED,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,EACpD,KAAK,EAAE,CAAC,GACP,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,WAAW,CA4BlC;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAC3C,KAAK,EAAE,CAAC,GACP,KAAK,IAAI,CAAC,GAAG,WAAW,CAQ1B"}
|
package/dist/aturi_validation.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
3
|
+
exports.ensureValidAtUri = ensureValidAtUri;
|
|
4
|
+
exports.ensureValidAtUriRegex = ensureValidAtUriRegex;
|
|
5
|
+
exports.isValidAtUri = isValidAtUri;
|
|
6
|
+
const at_identifier_js_1 = require("./at-identifier.js");
|
|
7
|
+
const did_js_1 = require("./did.js");
|
|
8
|
+
const handle_js_1 = require("./handle.js");
|
|
9
|
+
const nsid_js_1 = require("./nsid.js");
|
|
7
10
|
// Human-readable constraints on ATURI:
|
|
8
11
|
// - following regular URLs, a 8KByte hard total length limit
|
|
9
12
|
// - follows ATURI docs on website
|
|
@@ -17,96 +20,99 @@ const nsid_1 = require("./nsid");
|
|
|
17
20
|
// [a-zA-Z0-9._~:@!$&'\(\)*+,;=-]
|
|
18
21
|
// - rkey must have at least one char
|
|
19
22
|
// - regardless of path component, a fragment can follow as "#" and then a JSON pointer (RFC-6901)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
function ensureValidAtUri(input) {
|
|
24
|
+
const fragmentIndex = input.indexOf('#');
|
|
25
|
+
if (fragmentIndex !== -1) {
|
|
26
|
+
if (input.charCodeAt(fragmentIndex + 1) !== 47) {
|
|
27
|
+
throw new Error('ATURI fragment must be non-empty and start with slash');
|
|
28
|
+
}
|
|
29
|
+
if (input.includes('#', fragmentIndex + 1)) {
|
|
30
|
+
throw new Error('ATURI can have at most one "#", separating fragment out');
|
|
31
|
+
}
|
|
32
|
+
// NOTE: enforcing *some* checks here for sanity. Eg, at least no whitespace
|
|
33
|
+
const fragment = input.slice(fragmentIndex + 1);
|
|
34
|
+
if (!/^\/[a-zA-Z0-9._~:@!$&')(*+,;=%[\]/-]*$/.test(fragment)) {
|
|
35
|
+
throw new Error('Disallowed characters in ATURI fragment (ASCII)');
|
|
36
|
+
}
|
|
31
37
|
}
|
|
32
|
-
const
|
|
33
|
-
if (
|
|
38
|
+
const uri = fragmentIndex === -1 ? input : input.slice(0, fragmentIndex);
|
|
39
|
+
if (uri.length > 8 * 1024) {
|
|
40
|
+
throw new Error('ATURI is far too long');
|
|
41
|
+
}
|
|
42
|
+
if (!uri.startsWith('at://')) {
|
|
34
43
|
throw new Error('ATURI must start with "at://"');
|
|
35
44
|
}
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
// check that all chars are boring ASCII
|
|
46
|
+
if (!/^[a-zA-Z0-9._~:@!$&')(*+,;=%/-]*$/.test(uri)) {
|
|
47
|
+
throw new Error('Disallowed characters in ATURI (ASCII)');
|
|
38
48
|
}
|
|
49
|
+
const authorityEnd = uri.indexOf('/', 5);
|
|
50
|
+
const authority = authorityEnd === -1 ? uri.slice(5) : uri.slice(5, authorityEnd);
|
|
39
51
|
try {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
+
(0, at_identifier_js_1.ensureValidAtIdentifier)(authority);
|
|
53
|
+
}
|
|
54
|
+
catch (cause) {
|
|
55
|
+
throw new Error('ATURI authority must be a valid handle or DID', { cause });
|
|
56
|
+
}
|
|
57
|
+
const collectionStart = authorityEnd === -1 ? -1 : authorityEnd + 1;
|
|
58
|
+
const collectionEnd = collectionStart === -1 ? -1 : uri.indexOf('/', collectionStart);
|
|
59
|
+
if (collectionStart !== -1) {
|
|
60
|
+
const collection = collectionEnd === -1
|
|
61
|
+
? uri.slice(collectionStart)
|
|
62
|
+
: uri.slice(collectionStart, collectionEnd);
|
|
63
|
+
if (collection.length === 0) {
|
|
52
64
|
throw new Error('ATURI can not have a slash after authority without a path segment');
|
|
53
65
|
}
|
|
54
|
-
if (!(0,
|
|
66
|
+
if (!(0, nsid_js_1.isValidNsid)(collection)) {
|
|
55
67
|
throw new Error('ATURI requires first path segment (if supplied) to be valid NSID');
|
|
56
68
|
}
|
|
57
69
|
}
|
|
58
|
-
|
|
59
|
-
|
|
70
|
+
const recordKeyStart = collectionEnd === -1 ? -1 : collectionEnd + 1;
|
|
71
|
+
const recordKeyEnd = recordKeyStart === -1 ? -1 : uri.indexOf('/', recordKeyStart);
|
|
72
|
+
if (recordKeyStart !== -1) {
|
|
73
|
+
if (recordKeyStart === uri.length) {
|
|
60
74
|
throw new Error('ATURI can not have a slash after collection, unless record key is provided');
|
|
61
75
|
}
|
|
62
76
|
// would validate rkey here, but there are basically no constraints!
|
|
63
77
|
}
|
|
64
|
-
if (
|
|
78
|
+
if (recordKeyEnd !== -1) {
|
|
65
79
|
throw new Error('ATURI path can have at most two parts, and no trailing slash');
|
|
66
80
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
if (fragmentPart != null) {
|
|
71
|
-
if (fragmentPart.length === 0 || fragmentPart[0] !== '/') {
|
|
72
|
-
throw new Error('ATURI fragment must be non-empty and start with slash');
|
|
73
|
-
}
|
|
74
|
-
// NOTE: enforcing *some* checks here for sanity. Eg, at least no whitespace
|
|
75
|
-
if (!/^\/[a-zA-Z0-9._~:@!$&')(*+,;=%[\]/-]*$/.test(fragmentPart)) {
|
|
76
|
-
throw new Error('Disallowed characters in ATURI fragment (ASCII)');
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (uri.length > 8 * 1024) {
|
|
80
|
-
throw new Error('ATURI is far too long');
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
exports.ensureValidAtUri = ensureValidAtUri;
|
|
84
|
-
const ensureValidAtUriRegex = (uri) => {
|
|
81
|
+
}
|
|
82
|
+
function ensureValidAtUriRegex(input) {
|
|
85
83
|
// simple regex to enforce most constraints via just regex and length.
|
|
86
84
|
// hand wrote this regex based on above constraints. whew!
|
|
87
85
|
const aturiRegex = /^at:\/\/(?<authority>[a-zA-Z0-9._:%-]+)(\/(?<collection>[a-zA-Z0-9-.]+)(\/(?<rkey>[a-zA-Z0-9._~:@!$&%')(*+,;=-]+))?)?(#(?<fragment>\/[a-zA-Z0-9._~:@!$&%')(*+,;=\-[\]/\\]*))?$/;
|
|
88
|
-
const rm =
|
|
86
|
+
const rm = input.match(aturiRegex);
|
|
89
87
|
if (!rm || !rm.groups) {
|
|
90
88
|
throw new Error("ATURI didn't validate via regex");
|
|
91
89
|
}
|
|
92
90
|
const groups = rm.groups;
|
|
93
91
|
try {
|
|
94
|
-
(0,
|
|
92
|
+
(0, handle_js_1.ensureValidHandleRegex)(groups.authority);
|
|
95
93
|
}
|
|
96
94
|
catch {
|
|
97
95
|
try {
|
|
98
|
-
(0,
|
|
96
|
+
(0, did_js_1.ensureValidDidRegex)(groups.authority);
|
|
99
97
|
}
|
|
100
98
|
catch {
|
|
101
99
|
throw new Error('ATURI authority must be a valid handle or DID');
|
|
102
100
|
}
|
|
103
101
|
}
|
|
104
|
-
if (groups.collection && !(0,
|
|
102
|
+
if (groups.collection && !(0, nsid_js_1.isValidNsid)(groups.collection)) {
|
|
105
103
|
throw new Error('ATURI collection path segment must be a valid NSID');
|
|
106
104
|
}
|
|
107
|
-
if (
|
|
105
|
+
if (input.length > 8 * 1024) {
|
|
108
106
|
throw new Error('ATURI is far too long');
|
|
109
107
|
}
|
|
110
|
-
}
|
|
111
|
-
|
|
108
|
+
}
|
|
109
|
+
function isValidAtUri(input) {
|
|
110
|
+
try {
|
|
111
|
+
ensureValidAtUriRegex(input);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
112
118
|
//# sourceMappingURL=aturi_validation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aturi_validation.js","sourceRoot":"","sources":["../src/aturi_validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"aturi_validation.js","sourceRoot":"","sources":["../src/aturi_validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { AtIdentifierString, ensureValidAtIdentifier } from './at-identifier.js'\nimport { ensureValidDidRegex } from './did.js'\nimport { ensureValidHandleRegex } from './handle.js'\nimport { NsidString, isValidNsid } from './nsid.js'\n\nexport type AtUriString =\n | `at://${AtIdentifierString}`\n | `at://${AtIdentifierString}/${NsidString}`\n | `at://${AtIdentifierString}/${NsidString}/${string}`\n\n// Human-readable constraints on ATURI:\n// - following regular URLs, a 8KByte hard total length limit\n// - follows ATURI docs on website\n// - all ASCII characters, no whitespace. non-ASCII could be URL-encoded\n// - starts \"at://\"\n// - \"authority\" is a valid DID or a valid handle\n// - optionally, follow \"authority\" with \"/\" and valid NSID as start of path\n// - optionally, if NSID given, follow that with \"/\" and rkey\n// - rkey path component can include URL-encoded (\"percent encoded\"), or:\n// ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\" / \":\" / \"@\" / \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\" / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n// [a-zA-Z0-9._~:@!$&'\\(\\)*+,;=-]\n// - rkey must have at least one char\n// - regardless of path component, a fragment can follow as \"#\" and then a JSON pointer (RFC-6901)\n\nexport function ensureValidAtUri<I extends string>(\n input: I,\n): asserts input is I & AtUriString {\n const fragmentIndex = input.indexOf('#')\n if (fragmentIndex !== -1) {\n if (input.charCodeAt(fragmentIndex + 1) !== 47) {\n throw new Error('ATURI fragment must be non-empty and start with slash')\n }\n if (input.includes('#', fragmentIndex + 1)) {\n throw new Error('ATURI can have at most one \"#\", separating fragment out')\n }\n\n // NOTE: enforcing *some* checks here for sanity. Eg, at least no whitespace\n const fragment = input.slice(fragmentIndex + 1)\n if (!/^\\/[a-zA-Z0-9._~:@!$&')(*+,;=%[\\]/-]*$/.test(fragment)) {\n throw new Error('Disallowed characters in ATURI fragment (ASCII)')\n }\n }\n\n const uri = fragmentIndex === -1 ? input : input.slice(0, fragmentIndex)\n\n if (uri.length > 8 * 1024) {\n throw new Error('ATURI is far too long')\n }\n\n if (!uri.startsWith('at://')) {\n throw new Error('ATURI must start with \"at://\"')\n }\n\n // check that all chars are boring ASCII\n if (!/^[a-zA-Z0-9._~:@!$&')(*+,;=%/-]*$/.test(uri)) {\n throw new Error('Disallowed characters in ATURI (ASCII)')\n }\n\n const authorityEnd = uri.indexOf('/', 5)\n const authority =\n authorityEnd === -1 ? uri.slice(5) : uri.slice(5, authorityEnd)\n try {\n ensureValidAtIdentifier(authority)\n } catch (cause) {\n throw new Error('ATURI authority must be a valid handle or DID', { cause })\n }\n\n const collectionStart = authorityEnd === -1 ? -1 : authorityEnd + 1\n const collectionEnd =\n collectionStart === -1 ? -1 : uri.indexOf('/', collectionStart)\n\n if (collectionStart !== -1) {\n const collection =\n collectionEnd === -1\n ? uri.slice(collectionStart)\n : uri.slice(collectionStart, collectionEnd)\n\n if (collection.length === 0) {\n throw new Error(\n 'ATURI can not have a slash after authority without a path segment',\n )\n }\n if (!isValidNsid(collection)) {\n throw new Error(\n 'ATURI requires first path segment (if supplied) to be valid NSID',\n )\n }\n }\n\n const recordKeyStart = collectionEnd === -1 ? -1 : collectionEnd + 1\n const recordKeyEnd =\n recordKeyStart === -1 ? -1 : uri.indexOf('/', recordKeyStart)\n\n if (recordKeyStart !== -1) {\n if (recordKeyStart === uri.length) {\n throw new Error(\n 'ATURI can not have a slash after collection, unless record key is provided',\n )\n }\n // would validate rkey here, but there are basically no constraints!\n }\n\n if (recordKeyEnd !== -1) {\n throw new Error(\n 'ATURI path can have at most two parts, and no trailing slash',\n )\n }\n}\n\nexport function ensureValidAtUriRegex<I extends string>(\n input: I,\n): asserts input is I & AtUriString {\n // simple regex to enforce most constraints via just regex and length.\n // hand wrote this regex based on above constraints. whew!\n const aturiRegex =\n /^at:\\/\\/(?<authority>[a-zA-Z0-9._:%-]+)(\\/(?<collection>[a-zA-Z0-9-.]+)(\\/(?<rkey>[a-zA-Z0-9._~:@!$&%')(*+,;=-]+))?)?(#(?<fragment>\\/[a-zA-Z0-9._~:@!$&%')(*+,;=\\-[\\]/\\\\]*))?$/\n const rm = input.match(aturiRegex)\n if (!rm || !rm.groups) {\n throw new Error(\"ATURI didn't validate via regex\")\n }\n const groups = rm.groups\n\n try {\n ensureValidHandleRegex(groups.authority)\n } catch {\n try {\n ensureValidDidRegex(groups.authority)\n } catch {\n throw new Error('ATURI authority must be a valid handle or DID')\n }\n }\n\n if (groups.collection && !isValidNsid(groups.collection)) {\n throw new Error('ATURI collection path segment must be a valid NSID')\n }\n\n if (input.length > 8 * 1024) {\n throw new Error('ATURI is far too long')\n }\n}\n\nexport function isValidAtUri<I extends string>(\n input: I,\n): input is I & AtUriString {\n try {\n ensureValidAtUriRegex(input)\n } catch {\n return false\n }\n\n return true\n}\n"]}
|
package/dist/datetime.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/** An ISO 8601 formatted datetime string (YYYY-MM-DDTHH:mm:ss.sssZ) */
|
|
2
|
+
export type DatetimeString = `${string}-${string}-${string}T${string}:${string}:${string}${'Z' | `+${string}` | `-${string}`}`;
|
|
3
|
+
declare global {
|
|
4
|
+
interface Date {
|
|
5
|
+
toISOString(): `${string}-${string}-${string}T${string}:${string}:${string}Z`;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export declare function ensureValidDatetime<I extends string>(input: I): asserts input is I & DatetimeString;
|
|
9
|
+
export declare function isValidDatetime<I extends string>(input: I): input is I & DatetimeString;
|
|
10
|
+
export declare function normalizeDatetime(dtStr: string): DatetimeString;
|
|
11
|
+
export declare const normalizeDatetimeAlways: (dtStr: string) => DatetimeString;
|
|
5
12
|
export declare class InvalidDatetimeError extends Error {
|
|
6
13
|
}
|
|
7
14
|
//# sourceMappingURL=datetime.d.ts.map
|
package/dist/datetime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datetime.d.ts","sourceRoot":"","sources":["../src/datetime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"datetime.d.ts","sourceRoot":"","sources":["../src/datetime.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,MAAM,MAAM,cAAc,GACxB,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,EAAE,GAAG,IAAI,MAAM,EAAE,EAAE,CAAA;AAGnG,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,IAAI;QACZ,WAAW,IAAI,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,CAAA;KAC9E;CACF;AAKD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAClD,KAAK,EAAE,CAAC,GACP,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,cAAc,CA4BrC;AAID,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAC9C,KAAK,EAAE,CAAC,GACP,KAAK,IAAI,CAAC,GAAG,cAAc,CAQ7B;AAYD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAkC/D;AAMD,eAAO,MAAM,uBAAuB,GAAI,OAAO,MAAM,KAAG,cASvD,CAAA;AAID,qBAAa,oBAAqB,SAAQ,KAAK;CAAG"}
|