@atproto/syntax 0.4.1 → 0.4.2

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 (54) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/at-identifier.d.ts +5 -0
  3. package/dist/at-identifier.d.ts.map +1 -0
  4. package/dist/at-identifier.js +19 -0
  5. package/dist/at-identifier.js.map +1 -0
  6. package/dist/aturi.d.ts +8 -6
  7. package/dist/aturi.d.ts.map +1 -1
  8. package/dist/aturi.js +36 -45
  9. package/dist/aturi.js.map +1 -1
  10. package/dist/aturi_validation.d.ts +5 -2
  11. package/dist/aturi_validation.d.ts.map +1 -1
  12. package/dist/aturi_validation.js +53 -57
  13. package/dist/aturi_validation.js.map +1 -1
  14. package/dist/datetime.d.ts +11 -4
  15. package/dist/datetime.d.ts.map +1 -1
  16. package/dist/datetime.js +16 -16
  17. package/dist/datetime.js.map +1 -1
  18. package/dist/did.d.ts +3 -2
  19. package/dist/did.d.ts.map +1 -1
  20. package/dist/did.js +8 -8
  21. package/dist/did.js.map +1 -1
  22. package/dist/handle.d.ts +7 -6
  23. package/dist/handle.d.ts.map +1 -1
  24. package/dist/handle.js +28 -31
  25. package/dist/handle.js.map +1 -1
  26. package/dist/index.d.ts +8 -7
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +8 -7
  29. package/dist/index.js.map +1 -1
  30. package/dist/nsid.d.ts +6 -5
  31. package/dist/nsid.d.ts.map +1 -1
  32. package/dist/nsid.js +1 -1
  33. package/dist/nsid.js.map +1 -1
  34. package/dist/recordkey.d.ts +3 -2
  35. package/dist/recordkey.d.ts.map +1 -1
  36. package/dist/recordkey.js +33 -22
  37. package/dist/recordkey.js.map +1 -1
  38. package/dist/tid.d.ts +3 -2
  39. package/dist/tid.d.ts.map +1 -1
  40. package/dist/tid.js +7 -7
  41. package/dist/tid.js.map +1 -1
  42. package/package.json +1 -1
  43. package/src/at-identifier.ts +22 -0
  44. package/src/aturi.ts +59 -46
  45. package/src/aturi_validation.ts +60 -49
  46. package/src/datetime.ts +17 -4
  47. package/src/did.ts +5 -2
  48. package/src/handle.ts +23 -22
  49. package/src/index.ts +8 -7
  50. package/src/nsid.ts +8 -6
  51. package/src/recordkey.ts +40 -17
  52. package/src/tid.ts +4 -2
  53. package/tsconfig.build.json +1 -0
  54. package/tsconfig.build.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @atproto/syntax
2
2
 
3
+ ## 0.4.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#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
8
+
3
9
  ## 0.4.1
4
10
 
5
11
  ### Patch Changes
@@ -0,0 +1,5 @@
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
+ //# 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,EAAuB,MAAM,UAAU,CAAA;AACzD,OAAO,EACL,YAAY,EAGb,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"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureValidAtIdentifier = ensureValidAtIdentifier;
4
+ const did_js_1 = require("./did.js");
5
+ const handle_js_1 = require("./handle.js");
6
+ function ensureValidAtIdentifier(input) {
7
+ try {
8
+ if (input.startsWith('did:')) {
9
+ (0, did_js_1.ensureValidDidRegex)(input);
10
+ }
11
+ else {
12
+ (0, handle_js_1.ensureValidHandleRegex)(input);
13
+ }
14
+ }
15
+ catch (cause) {
16
+ throw new handle_js_1.InvalidHandleError('Invalid DID or handle', { cause });
17
+ }
18
+ }
19
+ //# sourceMappingURL=at-identifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"at-identifier.js","sourceRoot":"","sources":["../src/at-identifier.ts"],"names":[],"mappings":";;AASA,0DAYC;AArBD,qCAAyD;AACzD,2CAIoB;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","sourcesContent":["import { DidString, ensureValidDidRegex } from './did.js'\nimport {\n HandleString,\n InvalidHandleError,\n ensureValidHandleRegex,\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"]}
package/dist/aturi.d.ts CHANGED
@@ -1,14 +1,16 @@
1
- export * from './aturi_validation';
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: string;
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(): string;
21
- toString(): string;
22
+ get href(): AtUriString;
23
+ toString(): AtUriString;
22
24
  }
23
25
  //# sourceMappingURL=aturi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aturi.d.ts","sourceRoot":"","sources":["../src/aturi.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAElC,eAAO,MAAM,aAAa,QAEyE,CAAA;AAInG,qBAAa,KAAK;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,eAAe,CAAA;gBAEjB,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;IAyBtC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;IAOnE,IAAI,QAAQ,WAEX;IAED,IAAI,MAAM,WAET;IAED,IAAI,QAAQ,IAII,MAAM,CAFrB;IAED,IAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,EAErB;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,EAIvB;IAED,IAAI,IAAI,IAII,MAAM,CAFjB;IAED,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,EAKjB;IAED,IAAI,IAAI,WAEP;IAED,QAAQ;CAeT"}
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
@@ -15,7 +15,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.AtUri = exports.ATP_URI_REGEX = void 0;
18
- __exportStar(require("./aturi_validation"), exports);
18
+ const at_identifier_js_1 = require("./at-identifier.js");
19
+ const nsid_js_1 = require("./nsid.js");
20
+ __exportStar(require("./aturi_validation.js"), exports);
19
21
  exports.ATP_URI_REGEX =
20
22
  // proto- --did-------------- --name---------------- --path---- --query-- --hash--
21
23
  /^(at:\/\/)?((?:did:[a-z0-9:%-]+)|(?:[a-z0-9][a-z0-9.:-]*))(\/[^?#\s]*)?(\?[^#\s]+)?(#[^\s]+)?$/i;
@@ -47,27 +49,15 @@ class AtUri {
47
49
  writable: true,
48
50
  value: void 0
49
51
  });
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;
52
+ const parsed = base !== undefined
53
+ ? typeof base === 'string'
54
+ ? Object.assign(parse(base), parseRelative(uri))
55
+ : Object.assign({ host: base.host }, parseRelative(uri))
56
+ : parse(uri);
57
+ (0, at_identifier_js_1.ensureValidAtIdentifier)(parsed.host);
58
+ this.hash = parsed.hash ?? '';
69
59
  this.host = parsed.host;
70
- this.pathname = parsed.pathname;
60
+ this.pathname = parsed.pathname ?? '';
71
61
  this.searchParams = parsed.searchParams;
72
62
  }
73
63
  static make(handleOrDid, collection, rkey) {
@@ -88,6 +78,7 @@ class AtUri {
88
78
  return this.host;
89
79
  }
90
80
  set hostname(v) {
81
+ (0, at_identifier_js_1.ensureValidAtIdentifier)(v);
91
82
  this.host = v;
92
83
  }
93
84
  get search() {
@@ -100,6 +91,7 @@ class AtUri {
100
91
  return this.pathname.split('/').filter(Boolean)[0] || '';
101
92
  }
102
93
  set collection(v) {
94
+ (0, nsid_js_1.ensureValidNsid)(v);
103
95
  const parts = this.pathname.split('/').filter(Boolean);
104
96
  parts[0] = v;
105
97
  this.pathname = parts.join('/');
@@ -109,8 +101,7 @@ class AtUri {
109
101
  }
110
102
  set rkey(v) {
111
103
  const parts = this.pathname.split('/').filter(Boolean);
112
- if (!parts[0])
113
- parts[0] = 'undefined';
104
+ parts[0] || (parts[0] = 'undefined');
114
105
  parts[1] = v;
115
106
  this.pathname = parts.join('/');
116
107
  }
@@ -122,9 +113,9 @@ class AtUri {
122
113
  if (!path.startsWith('/')) {
123
114
  path = `/${path}`;
124
115
  }
125
- let qs = this.searchParams.toString();
126
- if (qs && !qs.startsWith('?')) {
127
- qs = `?${qs}`;
116
+ let qs = '';
117
+ if (this.searchParams.size) {
118
+ qs = `?${this.searchParams.toString()}`;
128
119
  }
129
120
  let hash = this.hash;
130
121
  if (hash && !hash.startsWith('#')) {
@@ -135,26 +126,26 @@ class AtUri {
135
126
  }
136
127
  exports.AtUri = AtUri;
137
128
  function parse(str) {
138
- const match = exports.ATP_URI_REGEX.exec(str);
139
- if (match) {
140
- return {
141
- hash: match[5] || '',
142
- host: match[2] || '',
143
- pathname: match[3] || '',
144
- searchParams: new URLSearchParams(match[4] || ''),
145
- };
146
- }
147
- return undefined;
129
+ const match = str.match(exports.ATP_URI_REGEX);
130
+ if (!match) {
131
+ throw new Error(`Invalid AT uri: ${str}`);
132
+ }
133
+ return {
134
+ host: match[2],
135
+ hash: match[5],
136
+ pathname: match[3],
137
+ searchParams: new URLSearchParams(match[4]),
138
+ };
148
139
  }
149
140
  function parseRelative(str) {
150
- const match = RELATIVE_REGEX.exec(str);
151
- if (match) {
152
- return {
153
- hash: match[3] || '',
154
- pathname: match[1] || '',
155
- searchParams: new URLSearchParams(match[2] || ''),
156
- };
157
- }
158
- return undefined;
141
+ const match = str.match(RELATIVE_REGEX);
142
+ if (!match) {
143
+ throw new Error(`Invalid path: ${str}`);
144
+ }
145
+ return {
146
+ hash: match[3],
147
+ pathname: match[1],
148
+ searchParams: new URLSearchParams(match[2]),
149
+ };
159
150
  }
160
151
  //# 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":"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"}
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,6 @@
1
- export declare const ensureValidAtUri: (uri: string) => void;
2
- export declare const ensureValidAtUriRegex: (uri: string) => void;
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(input: string): asserts input is AtUriString;
5
+ export declare function ensureValidAtUriRegex(uri: string): asserts uri is AtUriString;
3
6
  //# sourceMappingURL=aturi_validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aturi_validation.d.ts","sourceRoot":"","sources":["../src/aturi_validation.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,SA6E3C,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,KAAK,MAAM,KAAG,IA4BnD,CAAA"}
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,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,WAAW,CAiF5E;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,WAAW,CA4B7E"}
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ensureValidAtUriRegex = exports.ensureValidAtUri = void 0;
4
- const did_1 = require("./did");
5
- const handle_1 = require("./handle");
6
- const nsid_1 = require("./nsid");
3
+ exports.ensureValidAtUri = ensureValidAtUri;
4
+ exports.ensureValidAtUriRegex = ensureValidAtUriRegex;
5
+ const at_identifier_js_1 = require("./at-identifier.js");
6
+ const did_js_1 = require("./did.js");
7
+ const handle_js_1 = require("./handle.js");
8
+ const nsid_js_1 = require("./nsid.js");
7
9
  // Human-readable constraints on ATURI:
8
10
  // - following regular URLs, a 8KByte hard total length limit
9
11
  // - follows ATURI docs on website
@@ -17,71 +19,66 @@ const nsid_1 = require("./nsid");
17
19
  // [a-zA-Z0-9._~:@!$&'\(\)*+,;=-]
18
20
  // - rkey must have at least one char
19
21
  // - regardless of path component, a fragment can follow as "#" and then a JSON pointer (RFC-6901)
20
- const ensureValidAtUri = (uri) => {
21
- // JSON pointer is pretty different from rest of URI, so split that out first
22
- const uriParts = uri.split('#');
23
- if (uriParts.length > 2) {
24
- throw new Error('ATURI can have at most one "#", separating fragment out');
22
+ function ensureValidAtUri(input) {
23
+ const fragmentIndex = input.indexOf('#');
24
+ if (fragmentIndex !== -1) {
25
+ if (input.charCodeAt(fragmentIndex + 1) !== 47) {
26
+ throw new Error('ATURI fragment must be non-empty and start with slash');
27
+ }
28
+ if (input.includes('#', fragmentIndex + 1)) {
29
+ throw new Error('ATURI can have at most one "#", separating fragment out');
30
+ }
31
+ // NOTE: enforcing *some* checks here for sanity. Eg, at least no whitespace
32
+ const fragment = input.slice(fragmentIndex + 1);
33
+ if (!/^\/[a-zA-Z0-9._~:@!$&')(*+,;=%[\]/-]*$/.test(fragment)) {
34
+ throw new Error('Disallowed characters in ATURI fragment (ASCII)');
35
+ }
25
36
  }
26
- const fragmentPart = uriParts[1] || null;
27
- uri = uriParts[0];
28
- // check that all chars are boring ASCII
29
- if (!/^[a-zA-Z0-9._~:@!$&')(*+,;=%/-]*$/.test(uri)) {
30
- throw new Error('Disallowed characters in ATURI (ASCII)');
37
+ const uri = fragmentIndex === -1 ? input : input.slice(0, fragmentIndex);
38
+ if (uri.length > 8 * 1024) {
39
+ throw new Error('ATURI is far too long');
31
40
  }
32
- const parts = uri.split('/');
33
- if (parts.length >= 3 && (parts[0] !== 'at:' || parts[1].length !== 0)) {
41
+ if (!uri.startsWith('at://')) {
34
42
  throw new Error('ATURI must start with "at://"');
35
43
  }
36
- if (parts.length < 3) {
37
- throw new Error('ATURI requires at least method and authority sections');
44
+ // check that all chars are boring ASCII
45
+ if (!/^[a-zA-Z0-9._~:@!$&')(*+,;=%/-]*$/.test(uri)) {
46
+ throw new Error('Disallowed characters in ATURI (ASCII)');
38
47
  }
48
+ const authorityEnd = uri.indexOf('/', 5);
49
+ const authority = authorityEnd === -1 ? uri.slice(5) : uri.slice(5, authorityEnd);
39
50
  try {
40
- if (parts[2].startsWith('did:')) {
41
- (0, did_1.ensureValidDid)(parts[2]);
42
- }
43
- else {
44
- (0, handle_1.ensureValidHandle)(parts[2]);
45
- }
46
- }
47
- catch {
48
- throw new Error('ATURI authority must be a valid handle or DID');
49
- }
50
- if (parts.length >= 4) {
51
- if (parts[3].length === 0) {
51
+ (0, at_identifier_js_1.ensureValidAtIdentifier)(authority);
52
+ }
53
+ catch (cause) {
54
+ throw new Error('ATURI authority must be a valid handle or DID', { cause });
55
+ }
56
+ const collectionStart = authorityEnd === -1 ? -1 : authorityEnd + 1;
57
+ const collectionEnd = collectionStart === -1 ? -1 : uri.indexOf('/', collectionStart);
58
+ if (collectionStart !== -1) {
59
+ const collection = collectionEnd === -1
60
+ ? uri.slice(collectionStart)
61
+ : uri.slice(collectionStart, collectionEnd);
62
+ if (collection.length === 0) {
52
63
  throw new Error('ATURI can not have a slash after authority without a path segment');
53
64
  }
54
- if (!(0, nsid_1.isValidNsid)(parts[3])) {
65
+ if (!(0, nsid_js_1.isValidNsid)(collection)) {
55
66
  throw new Error('ATURI requires first path segment (if supplied) to be valid NSID');
56
67
  }
57
68
  }
58
- if (parts.length >= 5) {
59
- if (parts[4].length === 0) {
69
+ const recordKeyStart = collectionEnd === -1 ? -1 : collectionEnd + 1;
70
+ const recordKeyEnd = recordKeyStart === -1 ? -1 : uri.indexOf('/', recordKeyStart);
71
+ if (recordKeyStart !== -1) {
72
+ if (recordKeyStart === uri.length) {
60
73
  throw new Error('ATURI can not have a slash after collection, unless record key is provided');
61
74
  }
62
75
  // would validate rkey here, but there are basically no constraints!
63
76
  }
64
- if (parts.length >= 6) {
77
+ if (recordKeyEnd !== -1) {
65
78
  throw new Error('ATURI path can have at most two parts, and no trailing slash');
66
79
  }
67
- if (uriParts.length >= 2 && fragmentPart == null) {
68
- throw new Error('ATURI fragment must be non-empty and start with slash');
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) => {
80
+ }
81
+ function ensureValidAtUriRegex(uri) {
85
82
  // simple regex to enforce most constraints via just regex and length.
86
83
  // hand wrote this regex based on above constraints. whew!
87
84
  const aturiRegex = /^at:\/\/(?<authority>[a-zA-Z0-9._:%-]+)(\/(?<collection>[a-zA-Z0-9-.]+)(\/(?<rkey>[a-zA-Z0-9._~:@!$&%')(*+,;=-]+))?)?(#(?<fragment>\/[a-zA-Z0-9._~:@!$&%')(*+,;=\-[\]/\\]*))?$/;
@@ -91,22 +88,21 @@ const ensureValidAtUriRegex = (uri) => {
91
88
  }
92
89
  const groups = rm.groups;
93
90
  try {
94
- (0, handle_1.ensureValidHandleRegex)(groups.authority);
91
+ (0, handle_js_1.ensureValidHandleRegex)(groups.authority);
95
92
  }
96
93
  catch {
97
94
  try {
98
- (0, did_1.ensureValidDidRegex)(groups.authority);
95
+ (0, did_js_1.ensureValidDidRegex)(groups.authority);
99
96
  }
100
97
  catch {
101
98
  throw new Error('ATURI authority must be a valid handle or DID');
102
99
  }
103
100
  }
104
- if (groups.collection && !(0, nsid_1.isValidNsid)(groups.collection)) {
101
+ if (groups.collection && !(0, nsid_js_1.isValidNsid)(groups.collection)) {
105
102
  throw new Error('ATURI collection path segment must be a valid NSID');
106
103
  }
107
104
  if (uri.length > 8 * 1024) {
108
105
  throw new Error('ATURI is far too long');
109
106
  }
110
- };
111
- exports.ensureValidAtUriRegex = ensureValidAtUriRegex;
107
+ }
112
108
  //# sourceMappingURL=aturi_validation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"aturi_validation.js","sourceRoot":"","sources":["../src/aturi_validation.ts"],"names":[],"mappings":"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"}
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(input: string): asserts input is 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(uri: string): asserts uri is 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 = uri.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 (uri.length > 8 * 1024) {\n throw new Error('ATURI is far too long')\n }\n}\n"]}
@@ -1,7 +1,14 @@
1
- export declare const ensureValidDatetime: (dtStr: string) => void;
2
- export declare const isValidDatetime: (dtStr: string) => boolean;
3
- export declare const normalizeDatetime: (dtStr: string) => string;
4
- export declare const normalizeDatetimeAlways: (dtStr: string) => string;
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(dtStr: string): asserts dtStr is DatetimeString;
9
+ export declare function isValidDatetime(dtStr: string): dtStr is 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
@@ -1 +1 @@
1
- {"version":3,"file":"datetime.d.ts","sourceRoot":"","sources":["../src/datetime.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,KAAG,IA4BnD,CAAA;AAID,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,KAAG,OAW/C,CAAA;AAYD,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,KAAG,MAkCjD,CAAA;AAMD,eAAO,MAAM,uBAAuB,GAAI,OAAO,MAAM,KAAG,MASvD,CAAA;AAID,qBAAa,oBAAqB,SAAQ,KAAK;CAAG"}
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,CACjC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,KAAK,IAAI,cAAc,CA4BjC;AAID,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,cAAc,CAWtE;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"}
package/dist/datetime.js CHANGED
@@ -1,10 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InvalidDatetimeError = exports.normalizeDatetimeAlways = exports.normalizeDatetime = exports.isValidDatetime = exports.ensureValidDatetime = void 0;
3
+ exports.InvalidDatetimeError = exports.normalizeDatetimeAlways = void 0;
4
+ exports.ensureValidDatetime = ensureValidDatetime;
5
+ exports.isValidDatetime = isValidDatetime;
6
+ exports.normalizeDatetime = normalizeDatetime;
4
7
  /* Validates datetime string against atproto Lexicon 'datetime' format.
5
8
  * Syntax is described at: https://atproto.com/specs/lexicon#datetime
6
9
  */
7
- const ensureValidDatetime = (dtStr) => {
10
+ function ensureValidDatetime(dtStr) {
8
11
  const date = new Date(dtStr);
9
12
  // must parse as ISO 8601; this also verifies semantics like month is not 13 or 00
10
13
  if (isNaN(date.getTime())) {
@@ -26,13 +29,12 @@ const ensureValidDatetime = (dtStr) => {
26
29
  if (dtStr.startsWith('000')) {
27
30
  throw new InvalidDatetimeError('datetime so close to year zero not allowed');
28
31
  }
29
- };
30
- exports.ensureValidDatetime = ensureValidDatetime;
32
+ }
31
33
  /* Same logic as ensureValidDatetime(), but returns a boolean instead of throwing an exception.
32
34
  */
33
- const isValidDatetime = (dtStr) => {
35
+ function isValidDatetime(dtStr) {
34
36
  try {
35
- (0, exports.ensureValidDatetime)(dtStr);
37
+ ensureValidDatetime(dtStr);
36
38
  }
37
39
  catch (err) {
38
40
  if (err instanceof InvalidDatetimeError) {
@@ -41,8 +43,7 @@ const isValidDatetime = (dtStr) => {
41
43
  throw err;
42
44
  }
43
45
  return true;
44
- };
45
- exports.isValidDatetime = isValidDatetime;
46
+ }
46
47
  /* Takes a flexible datetime string and normalizes representation.
47
48
  *
48
49
  * This function will work with any valid atproto datetime (eg, anything which isValidDatetime() is true for). It *additionally* is more flexible about accepting datetimes that don't comply to RFC 3339, or are missing timezone information, and normalizing them to a valid datetime.
@@ -53,10 +54,10 @@ exports.isValidDatetime = isValidDatetime;
53
54
  *
54
55
  * Expected output format: YYYY-MM-DDTHH:mm:ss.sssZ
55
56
  */
56
- const normalizeDatetime = (dtStr) => {
57
- if ((0, exports.isValidDatetime)(dtStr)) {
57
+ function normalizeDatetime(dtStr) {
58
+ if (isValidDatetime(dtStr)) {
58
59
  const outStr = new Date(dtStr).toISOString();
59
- if ((0, exports.isValidDatetime)(outStr)) {
60
+ if (isValidDatetime(outStr)) {
60
61
  return outStr;
61
62
  }
62
63
  }
@@ -65,7 +66,7 @@ const normalizeDatetime = (dtStr) => {
65
66
  const date = new Date(dtStr + 'Z');
66
67
  if (!isNaN(date.getTime())) {
67
68
  const tzStr = date.toISOString();
68
- if ((0, exports.isValidDatetime)(tzStr)) {
69
+ if (isValidDatetime(tzStr)) {
69
70
  return tzStr;
70
71
  }
71
72
  }
@@ -76,21 +77,20 @@ const normalizeDatetime = (dtStr) => {
76
77
  throw new InvalidDatetimeError('datetime did not parse as any timestamp format');
77
78
  }
78
79
  const isoStr = date.toISOString();
79
- if ((0, exports.isValidDatetime)(isoStr)) {
80
+ if (isValidDatetime(isoStr)) {
80
81
  return isoStr;
81
82
  }
82
83
  else {
83
84
  throw new InvalidDatetimeError('datetime normalized to invalid timestamp string');
84
85
  }
85
- };
86
- exports.normalizeDatetime = normalizeDatetime;
86
+ }
87
87
  /* Variant of normalizeDatetime() which always returns a valid datetime strings.
88
88
  *
89
89
  * If a InvalidDatetimeError is encountered, returns the UNIX epoch time as a UTC datetime (1970-01-01T00:00:00.000Z).
90
90
  */
91
91
  const normalizeDatetimeAlways = (dtStr) => {
92
92
  try {
93
- return (0, exports.normalizeDatetime)(dtStr);
93
+ return normalizeDatetime(dtStr);
94
94
  }
95
95
  catch (err) {
96
96
  if (err instanceof InvalidDatetimeError) {
@@ -1 +1 @@
1
- {"version":3,"file":"datetime.js","sourceRoot":"","sources":["../src/datetime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"datetime.js","sourceRoot":"","sources":["../src/datetime.ts"],"names":[],"mappings":"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","sourcesContent":["/** An ISO 8601 formatted datetime string (YYYY-MM-DDTHH:mm:ss.sssZ) */\nexport type DatetimeString =\n `${string}-${string}-${string}T${string}:${string}:${string}${'Z' | `+${string}` | `-${string}`}`\n\n// Allow date.toISOString() to be used where datetime format is expected\ndeclare global {\n interface Date {\n toISOString(): `${string}-${string}-${string}T${string}:${string}:${string}Z`\n }\n}\n\n/* Validates datetime string against atproto Lexicon 'datetime' format.\n * Syntax is described at: https://atproto.com/specs/lexicon#datetime\n */\nexport function ensureValidDatetime(\n dtStr: string,\n): asserts dtStr is DatetimeString {\n const date = new Date(dtStr)\n // must parse as ISO 8601; this also verifies semantics like month is not 13 or 00\n if (isNaN(date.getTime())) {\n throw new InvalidDatetimeError('datetime did not parse as ISO 8601')\n }\n if (date.toISOString().startsWith('-')) {\n throw new InvalidDatetimeError('datetime normalized to a negative time')\n }\n // regex and other checks for RFC-3339\n if (\n !/^[0-9]{4}-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-6][0-9]:[0-6][0-9](.[0-9]{1,20})?(Z|([+-][0-2][0-9]:[0-5][0-9]))$/.test(\n dtStr,\n )\n ) {\n throw new InvalidDatetimeError(\"datetime didn't validate via regex\")\n }\n if (dtStr.length > 64) {\n throw new InvalidDatetimeError('datetime is too long (64 chars max)')\n }\n if (dtStr.endsWith('-00:00')) {\n throw new InvalidDatetimeError(\n 'datetime can not use \"-00:00\" for UTC timezone',\n )\n }\n if (dtStr.startsWith('000')) {\n throw new InvalidDatetimeError('datetime so close to year zero not allowed')\n }\n}\n\n/* Same logic as ensureValidDatetime(), but returns a boolean instead of throwing an exception.\n */\nexport function isValidDatetime(dtStr: string): dtStr is DatetimeString {\n try {\n ensureValidDatetime(dtStr)\n } catch (err) {\n if (err instanceof InvalidDatetimeError) {\n return false\n }\n throw err\n }\n\n return true\n}\n\n/* Takes a flexible datetime string and normalizes representation.\n *\n * This function will work with any valid atproto datetime (eg, anything which isValidDatetime() is true for). It *additionally* is more flexible about accepting datetimes that don't comply to RFC 3339, or are missing timezone information, and normalizing them to a valid datetime.\n *\n * One use-case is a consistent, sortable string. Another is to work with older invalid createdAt datetimes.\n *\n * Successful output will be a valid atproto datetime with millisecond precision (3 sub-second digits) and UTC timezone with trailing 'Z' syntax. Throws `InvalidDatetimeError` if the input string could not be parsed as a datetime, even with permissive parsing.\n *\n * Expected output format: YYYY-MM-DDTHH:mm:ss.sssZ\n */\nexport function normalizeDatetime(dtStr: string): DatetimeString {\n if (isValidDatetime(dtStr)) {\n const outStr = new Date(dtStr).toISOString()\n if (isValidDatetime(outStr)) {\n return outStr\n }\n }\n\n // check if this permissive datetime is missing a timezone\n if (!/.*(([+-]\\d\\d:?\\d\\d)|[a-zA-Z])$/.test(dtStr)) {\n const date = new Date(dtStr + 'Z')\n if (!isNaN(date.getTime())) {\n const tzStr = date.toISOString()\n if (isValidDatetime(tzStr)) {\n return tzStr\n }\n }\n }\n\n // finally try parsing as simple datetime\n const date = new Date(dtStr)\n if (isNaN(date.getTime())) {\n throw new InvalidDatetimeError(\n 'datetime did not parse as any timestamp format',\n )\n }\n const isoStr = date.toISOString()\n if (isValidDatetime(isoStr)) {\n return isoStr\n } else {\n throw new InvalidDatetimeError(\n 'datetime normalized to invalid timestamp string',\n )\n }\n}\n\n/* Variant of normalizeDatetime() which always returns a valid datetime strings.\n *\n * If a InvalidDatetimeError is encountered, returns the UNIX epoch time as a UTC datetime (1970-01-01T00:00:00.000Z).\n */\nexport const normalizeDatetimeAlways = (dtStr: string): DatetimeString => {\n try {\n return normalizeDatetime(dtStr)\n } catch (err) {\n if (err instanceof InvalidDatetimeError) {\n return new Date(0).toISOString()\n }\n throw err\n }\n}\n\n/* Indicates a datetime string did not pass full atproto Lexicon datetime string format checks.\n */\nexport class InvalidDatetimeError extends Error {}\n"]}
package/dist/did.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- export declare const ensureValidDid: (did: string) => void;
2
- export declare const ensureValidDidRegex: (did: string) => void;
1
+ export type DidString<M extends string = string> = `did:${M}:${string}`;
2
+ export declare function ensureValidDid(did: string): asserts did is DidString;
3
+ export declare function ensureValidDidRegex(did: string): asserts did is DidString;
3
4
  export declare class InvalidDidError extends Error {
4
5
  }
5
6
  //# sourceMappingURL=did.d.ts.map