shelving 1.202.0 → 1.204.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/api/provider/APIProvider.d.ts +1 -1
  2. package/api/provider/APIProvider.js +1 -1
  3. package/api/provider/ClientAPIProvider.d.ts +8 -8
  4. package/api/provider/ClientAPIProvider.js +12 -12
  5. package/api/provider/DebugAPIProvider.d.ts +1 -1
  6. package/api/provider/DebugAPIProvider.js +2 -2
  7. package/api/provider/JSONAPIProvider.d.ts +1 -1
  8. package/api/provider/JSONAPIProvider.js +3 -3
  9. package/api/provider/MockAPIProvider.d.ts +1 -1
  10. package/api/provider/MockAPIProvider.js +3 -3
  11. package/api/provider/ThroughAPIProvider.d.ts +1 -1
  12. package/api/provider/ThroughAPIProvider.js +2 -2
  13. package/api/provider/ValidationAPIProvider.d.ts +1 -1
  14. package/api/provider/ValidationAPIProvider.js +2 -2
  15. package/api/provider/XMLAPIProvider.d.ts +1 -1
  16. package/api/provider/XMLAPIProvider.js +3 -3
  17. package/db/provider/PostgreSQLProvider.d.ts +3 -2
  18. package/db/provider/SQLProvider.d.ts +4 -3
  19. package/db/provider/SQLProvider.js +1 -1
  20. package/db/provider/SQLiteProvider.d.ts +3 -2
  21. package/extract/DirectoryExtractor.d.ts +42 -0
  22. package/extract/DirectoryExtractor.js +127 -0
  23. package/extract/Extractor.d.ts +24 -0
  24. package/extract/Extractor.js +30 -0
  25. package/extract/FileExtractor.d.ts +22 -0
  26. package/extract/FileExtractor.js +34 -0
  27. package/extract/MarkdownExtractor.d.ts +17 -0
  28. package/extract/MarkdownExtractor.js +33 -0
  29. package/extract/TypescriptExtractor.d.ts +12 -0
  30. package/extract/TypescriptExtractor.js +255 -0
  31. package/extract/index.d.ts +5 -0
  32. package/extract/index.js +5 -0
  33. package/firestore/client/FirestoreClientProvider.js +4 -4
  34. package/firestore/lite/FirestoreLiteProvider.js +4 -4
  35. package/firestore/server/FirestoreServerProvider.js +4 -4
  36. package/markup/rule/blockquote.js +4 -4
  37. package/markup/rule/code.js +2 -2
  38. package/markup/rule/fenced.js +4 -4
  39. package/markup/rule/heading.js +4 -4
  40. package/markup/rule/inline.js +4 -4
  41. package/markup/rule/linebreak.js +2 -2
  42. package/markup/rule/link.js +3 -3
  43. package/markup/rule/ordered.js +4 -4
  44. package/markup/rule/paragraph.js +4 -4
  45. package/markup/rule/separator.js +4 -4
  46. package/markup/rule/unordered.js +4 -4
  47. package/markup/util/regexp.d.ts +6 -6
  48. package/markup/util/regexp.js +3 -3
  49. package/markup/util/rule.d.ts +1 -1
  50. package/markup/util/rule.js +1 -1
  51. package/package.json +8 -7
  52. package/sequence/DeferredSequence.js +3 -3
  53. package/ui/docs/DirectoryCard.d.ts +4 -0
  54. package/ui/docs/DirectoryCard.js +5 -0
  55. package/ui/docs/DirectoryCard.tsx +12 -0
  56. package/ui/docs/DirectoryMenuItem.d.ts +4 -0
  57. package/ui/docs/DirectoryMenuItem.js +5 -0
  58. package/ui/docs/DirectoryMenuItem.tsx +7 -0
  59. package/ui/docs/DirectoryPage.d.ts +4 -0
  60. package/ui/docs/DirectoryPage.js +7 -0
  61. package/ui/docs/DirectoryPage.tsx +15 -0
  62. package/ui/docs/DocumentationCard.d.ts +4 -0
  63. package/ui/docs/DocumentationCard.js +5 -0
  64. package/ui/docs/DocumentationCard.tsx +19 -0
  65. package/ui/docs/DocumentationPage.d.ts +8 -0
  66. package/ui/docs/DocumentationPage.js +11 -0
  67. package/ui/docs/DocumentationPage.tsx +60 -0
  68. package/ui/docs/FileCard.d.ts +4 -0
  69. package/ui/docs/FileCard.js +5 -0
  70. package/ui/docs/FileCard.tsx +12 -0
  71. package/ui/docs/FileMenuItem.d.ts +4 -0
  72. package/ui/docs/FileMenuItem.js +5 -0
  73. package/ui/docs/FileMenuItem.tsx +7 -0
  74. package/ui/docs/FilePage.d.ts +4 -0
  75. package/ui/docs/FilePage.js +7 -0
  76. package/ui/docs/FilePage.tsx +15 -0
  77. package/ui/docs/index.d.ts +8 -0
  78. package/ui/docs/index.js +8 -0
  79. package/ui/docs/index.ts +8 -0
  80. package/ui/form/ButtonInput.d.ts +1 -1
  81. package/ui/form/CheckboxInput.d.ts +1 -1
  82. package/ui/form/ChoiceRadioInputs.js +1 -1
  83. package/ui/form/ChoiceRadioInputs.tsx +1 -1
  84. package/ui/form/DateInput.d.ts +1 -1
  85. package/ui/form/FileInput.d.ts +1 -1
  86. package/ui/form/Input.d.ts +1 -1
  87. package/ui/form/Input.module.css +1 -0
  88. package/ui/form/NumberInput.d.ts +1 -1
  89. package/ui/form/Popover.d.ts +1 -1
  90. package/ui/form/RadioInput.d.ts +1 -1
  91. package/ui/form/TextInput.d.ts +1 -1
  92. package/ui/index.d.ts +2 -0
  93. package/ui/index.js +2 -0
  94. package/ui/index.ts +2 -0
  95. package/ui/misc/Mapper.d.ts +35 -0
  96. package/ui/misc/Mapper.js +51 -0
  97. package/ui/misc/Mapper.tsx +78 -0
  98. package/ui/misc/index.d.ts +1 -0
  99. package/ui/misc/index.js +1 -0
  100. package/ui/misc/index.tsx +1 -0
  101. package/ui/tree/TreeApp.d.ts +19 -0
  102. package/ui/tree/TreeApp.js +23 -0
  103. package/ui/tree/TreeApp.tsx +44 -0
  104. package/ui/tree/TreeCards.d.ts +13 -0
  105. package/ui/tree/TreeCards.js +19 -0
  106. package/ui/tree/TreeCards.module.css +31 -0
  107. package/ui/tree/TreeCards.tsx +31 -0
  108. package/ui/tree/TreeMenu.d.ts +14 -0
  109. package/ui/tree/TreeMenu.js +18 -0
  110. package/ui/tree/TreeMenu.module.css +29 -0
  111. package/ui/tree/TreeMenu.tsx +32 -0
  112. package/ui/tree/TreePage.d.ts +20 -0
  113. package/ui/tree/TreePage.js +29 -0
  114. package/ui/tree/TreePage.tsx +36 -0
  115. package/ui/tree/index.d.ts +4 -0
  116. package/ui/tree/index.js +4 -0
  117. package/ui/tree/index.ts +4 -0
  118. package/util/async.d.ts +2 -2
  119. package/util/async.js +2 -2
  120. package/util/data.d.ts +25 -29
  121. package/util/data.js +8 -8
  122. package/util/dispose.d.ts +2 -0
  123. package/util/dispose.js +2 -0
  124. package/util/element.d.ts +170 -4
  125. package/util/element.js +122 -12
  126. package/util/file.d.ts +15 -3
  127. package/util/file.js +21 -4
  128. package/util/http.d.ts +11 -11
  129. package/util/http.js +14 -14
  130. package/util/iterate.d.ts +1 -1
  131. package/util/path.d.ts +17 -24
  132. package/util/path.js +29 -42
  133. package/util/query.d.ts +16 -15
  134. package/util/query.js +13 -13
  135. package/util/regexp.d.ts +42 -4
  136. package/util/regexp.js +55 -4
  137. package/util/sequence.js +2 -2
  138. package/util/string.d.ts +2 -0
  139. package/util/update.d.ts +10 -9
  140. package/util/update.js +7 -7
@@ -32,7 +32,7 @@ export declare abstract class APIProvider<P = unknown, R = unknown> implements A
32
32
  * @throws {RequiredError} if this endpoint's path has `{placeholders}` but `payload` is not a data object.
33
33
  * @throws {RequiredError} if this is a `HEAD` or `GET` request but `payload` is not a data object.
34
34
  */
35
- abstract getRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
35
+ abstract createRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
36
36
  /** Fetch a `Resource` using this provider (defaults to Javascript `fetch()` API). */
37
37
  abstract fetch(request: Request): Promise<Response>;
38
38
  /**
@@ -2,7 +2,7 @@
2
2
  export class APIProvider {
3
3
  /** Send a payload to an `Endpoint` and retrieve the result. */
4
4
  async call(endpoint, payload, options, caller) {
5
- const request = this.getRequest(endpoint, payload, options, caller);
5
+ const request = this.createRequest(endpoint, payload, options, caller);
6
6
  const response = await this.fetch(request);
7
7
  return this.parseResponse(endpoint, response, caller);
8
8
  }
@@ -17,7 +17,7 @@ export interface ClientAPIProviderOptions {
17
17
  */
18
18
  readonly url: PossibleURL;
19
19
  /**
20
- * Options used for HTTP requests created with `this.getRequest()` and `this.fetch()`
20
+ * Options used for HTTP requests created with `this.createRequest()` and `this.fetch()`
21
21
  * - Omits `signal` because it's not relevant at the provider level.
22
22
  */
23
23
  readonly options?: Omit<RequestOptions, "signal">;
@@ -33,24 +33,24 @@ export interface ClientAPIProviderOptions {
33
33
  * - Can be used on a server environment to make outgoing API calls, or in a browser environment to call a server API.
34
34
  * - Renders endpoint paths and query params into the URL and sends body payloads as JSON.
35
35
  * - Parses JSON responses and throws `ResponseError` for non-2xx responses.
36
- * - Extendable with custom request-building and response-parsing logic by overriding `getRequest()` and `parseResponse()`.
36
+ * - Extendable with custom request-building and response-parsing logic by overriding `createRequest()` and `parseResponse()`.
37
37
  * - Wrap in `ValidationAPIProvider` to add automatic validation of request payloads and response results against endpoint schemas.
38
38
  */
39
39
  export declare class ClientAPIProvider<P = unknown, R = unknown> extends APIProvider<P, R> {
40
40
  /** The common base URL for all rendered endpoint requests. */
41
41
  readonly url: URL;
42
- /** Default options used for HTTP requests created with `this.getRequest()` and `this.fetch()` */
42
+ /** Default options used for HTTP requests created with `this.createRequest()` and `this.fetch()` */
43
43
  readonly options: RequestOptions;
44
44
  /** Timeout in milliseconds before the request is aborted, or `0` for no timeout. */
45
45
  readonly timeout: number;
46
46
  constructor({ url, options, timeout }: ClientAPIProviderOptions);
47
47
  renderURL<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, caller?: AnyCaller): URL;
48
- getRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
49
- /** Internal implementation function for `getRequest()` used for requests that have no body. */
50
- protected _getHeadRequest(method: RequestHeadMethod, //
48
+ createRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
49
+ /** Internal implementation function for `createRequest()` used for requests that have no body. */
50
+ protected _createHeadRequest(method: RequestHeadMethod, //
51
51
  url: PossibleURL, params: Nullish<PossibleURIParams>, options: RequestOptions, caller: AnyCaller): Request;
52
- /** Internal implementation function for `getRequest()` used for requests that have a body. */
53
- protected _getBodyRequest(method: RequestBodyMethod, //
52
+ /** Internal implementation function for `createRequest()` used for requests that have a body. */
53
+ protected _createBodyRequest(method: RequestBodyMethod, //
54
54
  url: PossibleURL, payload: P, options: RequestOptions, caller: AnyCaller): Request;
55
55
  fetch(request: Request): Promise<Response>;
56
56
  parseResponse<PP extends P, RR extends R>(_endpoint: Endpoint<PP, RR>, response: Response, caller?: AnyCaller): Promise<RR>;
@@ -1,7 +1,7 @@
1
1
  import { ResponseError } from "../../error/ResponseError.js";
2
2
  import { isData } from "../../util/data.js";
3
3
  import { getMessage } from "../../util/error.js";
4
- import { assertRequestHeadPayload, getHeadRequest, getRequest, isRequestHeadMethod, mergeRequestOptions, parseResponseBody, } from "../../util/http.js";
4
+ import { assertRequestHeadPayload, createHeadRequest, createRequest, isRequestHeadMethod, mergeRequestOptions, parseResponseBody, } from "../../util/http.js";
5
5
  import { omitProps } from "../../util/object.js";
6
6
  import { withURIParams } from "../../util/uri.js";
7
7
  import { requireBaseURL, requireURL } from "../../util/url.js";
@@ -11,13 +11,13 @@ import { APIProvider } from "./APIProvider.js";
11
11
  * - Can be used on a server environment to make outgoing API calls, or in a browser environment to call a server API.
12
12
  * - Renders endpoint paths and query params into the URL and sends body payloads as JSON.
13
13
  * - Parses JSON responses and throws `ResponseError` for non-2xx responses.
14
- * - Extendable with custom request-building and response-parsing logic by overriding `getRequest()` and `parseResponse()`.
14
+ * - Extendable with custom request-building and response-parsing logic by overriding `createRequest()` and `parseResponse()`.
15
15
  * - Wrap in `ValidationAPIProvider` to add automatic validation of request payloads and response results against endpoint schemas.
16
16
  */
17
17
  export class ClientAPIProvider extends APIProvider {
18
18
  /** The common base URL for all rendered endpoint requests. */
19
19
  url;
20
- /** Default options used for HTTP requests created with `this.getRequest()` and `this.fetch()` */
20
+ /** Default options used for HTTP requests created with `this.createRequest()` and `this.fetch()` */
21
21
  options;
22
22
  /** Timeout in milliseconds before the request is aborted, or `0` for no timeout. */
23
23
  timeout;
@@ -43,7 +43,7 @@ export class ClientAPIProvider extends APIProvider {
43
43
  }
44
44
  return url;
45
45
  }
46
- getRequest(endpoint, payload, options, caller = this.getRequest) {
46
+ createRequest(endpoint, payload, options, caller = this.createRequest) {
47
47
  // Render the path into the base URL.
48
48
  const url = this.renderURL(endpoint, payload, caller);
49
49
  // Merge the param options with `this.options`
@@ -52,20 +52,20 @@ export class ClientAPIProvider extends APIProvider {
52
52
  const mergedOptions = mergeRequestOptions({ signal, ...this.options }, options);
53
53
  // HEAD or GET requests need no payload because it was already rendered into the URL as `?query` params by `this.renderURL()`
54
54
  if (isRequestHeadMethod(endpoint.method))
55
- return this._getHeadRequest(endpoint.method, url, undefined, mergedOptions, caller);
55
+ return this._createHeadRequest(endpoint.method, url, undefined, mergedOptions, caller);
56
56
  // Body request.
57
57
  const body = isData(payload) ? omitProps(payload, ...endpoint.placeholders) : payload; // Omit any params that have already been embedded as `{placeholders}`.
58
- return this._getBodyRequest(endpoint.method, url, body, mergedOptions, caller);
58
+ return this._createBodyRequest(endpoint.method, url, body, mergedOptions, caller);
59
59
  }
60
- /** Internal implementation function for `getRequest()` used for requests that have no body. */
61
- _getHeadRequest(method, //
60
+ /** Internal implementation function for `createRequest()` used for requests that have no body. */
61
+ _createHeadRequest(method, //
62
62
  url, params, options, caller) {
63
- return getHeadRequest(method, url, params, options, caller);
63
+ return createHeadRequest(method, url, params, options, caller);
64
64
  }
65
- /** Internal implementation function for `getRequest()` used for requests that have a body. */
66
- _getBodyRequest(method, //
65
+ /** Internal implementation function for `createRequest()` used for requests that have a body. */
66
+ _createBodyRequest(method, //
67
67
  url, payload, options, caller) {
68
- return getRequest(method, url, payload, options, caller);
68
+ return createRequest(method, url, payload, options, caller);
69
69
  }
70
70
  // Override to set default functionality of a client provider to send requests over the network with `fetch()` and parse responses with `parseResponse()`.
71
71
  async fetch(request) {
@@ -4,7 +4,7 @@ import type { Endpoint } from "../endpoint/Endpoint.js";
4
4
  import { ThroughAPIProvider } from "./ThroughAPIProvider.js";
5
5
  /** Provider that logs everything to the console in some detail to help diagnose issues in development. */
6
6
  export declare class DebugAPIProvider<P, R> extends ThroughAPIProvider<P, R> {
7
- getRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
7
+ createRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
8
8
  fetch(request: Request): Promise<Response>;
9
9
  parseResponse<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, response: Response, caller?: AnyCaller): Promise<RR>;
10
10
  }
@@ -3,9 +3,9 @@ import { debugFullRequest, debugFullResponse, debugRequest } from "../../util/de
3
3
  import { ThroughAPIProvider } from "./ThroughAPIProvider.js";
4
4
  /** Provider that logs everything to the console in some detail to help diagnose issues in development. */
5
5
  export class DebugAPIProvider extends ThroughAPIProvider {
6
- getRequest(endpoint, payload, options, caller = this.getRequest) {
6
+ createRequest(endpoint, payload, options, caller = this.createRequest) {
7
7
  try {
8
- const request = super.getRequest(endpoint, payload, options, caller);
8
+ const request = super.createRequest(endpoint, payload, options, caller);
9
9
  console.debug(`${ANSI_WAITING} ${endpoint.toString()}`, payload);
10
10
  return request;
11
11
  }
@@ -5,7 +5,7 @@ import type { Endpoint } from "../endpoint/Endpoint.js";
5
5
  import { ClientAPIProvider } from "./ClientAPIProvider.js";
6
6
  /** API provider that always sends request bodies as JSON and parses responses as JSON. */
7
7
  export declare class JSONAPIProvider<P = unknown, R = unknown> extends ClientAPIProvider<P, R> {
8
- protected _getBodyRequest(method: RequestBodyMethod, url: PossibleURL, payload: P, options: RequestOptions, caller: AnyCaller): Request;
8
+ protected _createBodyRequest(method: RequestBodyMethod, url: PossibleURL, payload: P, options: RequestOptions, caller: AnyCaller): Request;
9
9
  /**
10
10
  * Parse a JSON `Response` for an endpoint.
11
11
  *
@@ -1,11 +1,11 @@
1
1
  import { ResponseError } from "../../error/ResponseError.js";
2
2
  import { getMessage } from "../../util/error.js";
3
- import { getJSONRequest, parseResponseJSON } from "../../util/http.js";
3
+ import { createJSONRequest, parseResponseJSON } from "../../util/http.js";
4
4
  import { ClientAPIProvider } from "./ClientAPIProvider.js";
5
5
  /** API provider that always sends request bodies as JSON and parses responses as JSON. */
6
6
  export class JSONAPIProvider extends ClientAPIProvider {
7
- _getBodyRequest(method, url, payload, options, caller) {
8
- return getJSONRequest(method, url, payload, options, caller);
7
+ _createBodyRequest(method, url, payload, options, caller) {
8
+ return createJSONRequest(method, url, payload, options, caller);
9
9
  }
10
10
  /**
11
11
  * Parse a JSON `Response` for an endpoint.
@@ -29,7 +29,7 @@ export declare class MockAPIProvider<P = unknown, R = unknown> extends ThroughAP
29
29
  readonly responseCalls: MockAPIResponseCall[];
30
30
  readonly handler: RequestHandler;
31
31
  constructor(handler?: RequestHandler, source?: APIProvider<P, R>);
32
- getRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
32
+ createRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
33
33
  parseResponse<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, response: Response, caller?: AnyCaller): Promise<RR>;
34
34
  fetch(request: Request): Promise<Response>;
35
35
  }
@@ -19,9 +19,9 @@ export class MockAPIProvider extends ThroughAPIProvider {
19
19
  super(source);
20
20
  this.handler = handler;
21
21
  }
22
- // Override `getRequest()` to log the endpoint and payload before delegating to the source provider for request building.
23
- getRequest(endpoint, payload, options, caller = this.getRequest) {
24
- const request = super.getRequest(endpoint, payload, options, caller);
22
+ // Override `createRequest()` to log the endpoint and payload before delegating to the source provider for request building.
23
+ createRequest(endpoint, payload, options, caller = this.createRequest) {
24
+ const request = super.createRequest(endpoint, payload, options, caller);
25
25
  this.requestCalls.push({ endpoint, payload, options, request });
26
26
  return request;
27
27
  }
@@ -12,7 +12,7 @@ export declare class ThroughAPIProvider<P, R> extends APIProvider<P, R> implemen
12
12
  readonly source: APIProvider<P, R>;
13
13
  constructor(source: APIProvider<P, R>);
14
14
  renderURL<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, caller?: AnyCaller): URL;
15
- getRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
15
+ createRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
16
16
  parseResponse<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, response: Response, caller?: AnyCaller): Promise<RR>;
17
17
  fetch(request: Request): Promise<Response>;
18
18
  [Symbol.asyncDispose](): Promise<void>;
@@ -16,8 +16,8 @@ export class ThroughAPIProvider extends APIProvider {
16
16
  renderURL(endpoint, payload, caller = this.renderURL) {
17
17
  return this.source.renderURL(endpoint, payload, caller);
18
18
  }
19
- getRequest(endpoint, payload, options, caller = this.getRequest) {
20
- return this.source.getRequest(endpoint, payload, options, caller);
19
+ createRequest(endpoint, payload, options, caller = this.createRequest) {
20
+ return this.source.createRequest(endpoint, payload, options, caller);
21
21
  }
22
22
  parseResponse(endpoint, response, caller = this.parseResponse) {
23
23
  return this.source.parseResponse(endpoint, response, caller);
@@ -4,6 +4,6 @@ import type { Endpoint } from "../endpoint/Endpoint.js";
4
4
  import { ThroughAPIProvider } from "./ThroughAPIProvider.js";
5
5
  /** Validate an asynchronous source provider (source can have any type because validation guarantees the type). */
6
6
  export declare class ValidationAPIProvider<P, R> extends ThroughAPIProvider<P, R> {
7
- getRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
7
+ createRequest<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, options?: RequestOptions, caller?: AnyCaller): Request;
8
8
  parseResponse<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, response: Response, caller?: AnyCaller): Promise<RR>;
9
9
  }
@@ -2,9 +2,9 @@ import { ResponseError } from "../../error/ResponseError.js";
2
2
  import { ThroughAPIProvider } from "./ThroughAPIProvider.js";
3
3
  /** Validate an asynchronous source provider (source can have any type because validation guarantees the type). */
4
4
  export class ValidationAPIProvider extends ThroughAPIProvider {
5
- getRequest(endpoint, payload, options, caller = this.getRequest) {
5
+ createRequest(endpoint, payload, options, caller = this.createRequest) {
6
6
  // Validate payload — let thrown strings bubble up as user-readable messages for e.g. form handlers.
7
- return super.getRequest(endpoint, endpoint.payload.validate(payload), options, caller);
7
+ return super.createRequest(endpoint, endpoint.payload.validate(payload), options, caller);
8
8
  }
9
9
  async parseResponse(endpoint, response, caller = this.parseResponse) {
10
10
  try {
@@ -6,7 +6,7 @@ import type { Endpoint } from "../endpoint/Endpoint.js";
6
6
  import { ClientAPIProvider } from "./ClientAPIProvider.js";
7
7
  /** API provider that always sends request bodies as XML and parses responses as plain text. */
8
8
  export declare class XMLAPIProvider<P extends Data = Data, R extends string = string> extends ClientAPIProvider<P, R> {
9
- protected _getBodyRequest(method: RequestBodyMethod, url: PossibleURL, payload: P, options: RequestOptions, caller: AnyCaller): Request;
9
+ protected _createBodyRequest(method: RequestBodyMethod, url: PossibleURL, payload: P, options: RequestOptions, caller: AnyCaller): Request;
10
10
  /**
11
11
  * Parse a text `Response` for an endpoint.
12
12
  *
@@ -1,10 +1,10 @@
1
1
  import { ResponseError } from "../../error/ResponseError.js";
2
- import { getXMLRequest } from "../../util/http.js";
2
+ import { createXMLRequest } from "../../util/http.js";
3
3
  import { ClientAPIProvider } from "./ClientAPIProvider.js";
4
4
  /** API provider that always sends request bodies as XML and parses responses as plain text. */
5
5
  export class XMLAPIProvider extends ClientAPIProvider {
6
- _getBodyRequest(method, url, payload, options, caller) {
7
- return getXMLRequest(method, url, payload, options, caller);
6
+ _createBodyRequest(method, url, payload, options, caller) {
7
+ return createXMLRequest(method, url, payload, options, caller);
8
8
  }
9
9
  /**
10
10
  * Parse a text `Response` for an endpoint.
@@ -1,6 +1,7 @@
1
- import type { Data, DataPath } from "../../util/data.js";
1
+ import type { Data } from "../../util/data.js";
2
2
  import type { Identifier } from "../../util/item.js";
3
3
  import type { QueryFilter } from "../../util/query.js";
4
+ import type { Segments } from "../../util/string.js";
4
5
  import type { Update } from "../../util/update.js";
5
6
  import { type SQLFragment, SQLProvider } from "./SQLProvider.js";
6
7
  /** Abstract PostgreSQL provider with JSONB function support for nested keys, array containment, and array mutations. */
@@ -8,7 +9,7 @@ export declare abstract class PostgreSQLProvider<I extends Identifier = Identifi
8
9
  /** Get the Postgres JSONB path for the nested segments of a key, e.g. `{"b","c"}`. */
9
10
  private sqlPath;
10
11
  /** Get the Postgres JSONB extract syntax, e.g. `"a" #>> {"b","c"}` */
11
- sqlExtract(key: DataPath): SQLFragment;
12
+ sqlExtract(key: Segments): SQLFragment;
12
13
  sqlUpdate(update: Update): SQLFragment;
13
14
  sqlFilter(filter: QueryFilter): SQLFragment;
14
15
  }
@@ -1,5 +1,6 @@
1
1
  import type { ImmutableArray } from "../../util/array.js";
2
- import type { Data, DataPath } from "../../util/data.js";
2
+ import type { Data } from "../../util/data.js";
3
+ import type { Segments } from "../../util/index.js";
3
4
  import type { Identifier, Item, Items, ItemsSequence, OptionalItem, OptionalItemSequence } from "../../util/item.js";
4
5
  import { type Query, type QueryFilter, type QueryOrder } from "../../util/query.js";
5
6
  import { type Update, type Updates } from "../../util/update.js";
@@ -32,8 +33,8 @@ export declare abstract class SQLProvider<I extends Identifier = Identifier, T e
32
33
  sql(strings: TemplateStringsArray, ...values: ImmutableArray<unknown>): SQLFragment;
33
34
  /** Define an SQL fragment for an identifier, e.g. `"myTable"` */
34
35
  sqlIdentifier(name: string): SQLFragment;
35
- /** Define an SQL fragment that extracts a deeply nested calue for comparison, e.g. `"a" #>> {"b","c"}` in Postgres */
36
- sqlExtract(key: DataPath): SQLFragment;
36
+ /** Define an SQL fragment that extracts a deeply nested value for comparison, e.g. `"a" #>> {"b","c"}` in Postgres */
37
+ sqlExtract(key: Segments): SQLFragment;
37
38
  /** Define an SQL fragment to generate a series of values with a separator, e.g. `"a" = 1 AND "b" = 2` */
38
39
  sqlConcat(values: ImmutableArray<SQLFragment>, separator?: string, before?: string, after?: string): SQLFragment;
39
40
  /** Define an SQL fragment for setting a list of values, e.g. `"a" = 1, "b" = 2` */
@@ -78,7 +78,7 @@ export class SQLProvider extends DBProvider {
78
78
  sqlIdentifier(name) {
79
79
  return { strings: [_escapeIdentifier(name)], values: [] };
80
80
  }
81
- /** Define an SQL fragment that extracts a deeply nested calue for comparison, e.g. `"a" #>> {"b","c"}` in Postgres */
81
+ /** Define an SQL fragment that extracts a deeply nested value for comparison, e.g. `"a" #>> {"b","c"}` in Postgres */
82
82
  sqlExtract(key) {
83
83
  if (key.length > 1)
84
84
  throw new UnimplementedError("SQLProvider does not support nested filter keys");
@@ -1,6 +1,7 @@
1
- import type { Data, DataPath } from "../../util/data.js";
1
+ import type { Data } from "../../util/data.js";
2
2
  import type { Identifier } from "../../util/item.js";
3
3
  import type { QueryFilter } from "../../util/query.js";
4
+ import type { Segments } from "../../util/string.js";
4
5
  import type { Update } from "../../util/update.js";
5
6
  import type { Collection } from "../collection/Collection.js";
6
7
  import { type SQLFragment, SQLProvider } from "./SQLProvider.js";
@@ -16,7 +17,7 @@ export declare abstract class SQLiteProvider<I extends Identifier = Identifier,
16
17
  /** Get the SQLite JSON path for the nested segments of a key (everything after the column name), e.g. `$.b.c` */
17
18
  private sqlPath;
18
19
  /** Get the SQLite JSON extract syntax, e.g. `json_extract("a", $.b.c)` */
19
- sqlExtract(key: DataPath): SQLFragment;
20
+ sqlExtract(key: Segments): SQLFragment;
20
21
  sqlUpdate(update: Update): SQLFragment;
21
22
  sqlFilter(filter: QueryFilter): SQLFragment;
22
23
  }
@@ -0,0 +1,42 @@
1
+ import type { ImmutableDictionary } from "../util/dictionary.js";
2
+ import { type DirectoryElement } from "../util/element.js";
3
+ import { type AbsolutePath, type Matchables, type Path } from "../util/index.js";
4
+ import { Extractor } from "./Extractor.js";
5
+ import { FileExtractor } from "./FileExtractor.js";
6
+ /** Options for a directory extractor. */
7
+ export interface DirectoryExtractorOptions {
8
+ /** Filenames to treat as the directory's index file. Matched case-insensitively. */
9
+ readonly index?: Matchables;
10
+ /**
11
+ * Extractor dispatch table keyed by file extension (with leading dot, e.g. `".md"`).
12
+ * - Files with no matching extractor are silently skipped.
13
+ * - Defaults to `.md` (markdown), `.ts` (TypeScript), and `.txt` (plain text).
14
+ */
15
+ readonly extractors?: ImmutableDictionary<FileExtractor>;
16
+ /** Absolute base path used to resolve relative paths passed to `extract()`. */
17
+ readonly base?: AbsolutePath;
18
+ /**
19
+ * Glob patterns for entries to skip — applied to both files and directories.
20
+ * - Defaults to test and spec files: `["*.test.ts", "*.test.tsx", "*.spec.ts", "*.spec.tsx"]`.
21
+ * - Hidden entries (`.`-prefixed), underscore-prefixed entries, and `node_modules` are always skipped on top of these patterns.
22
+ */
23
+ readonly ignore?: Matchables;
24
+ }
25
+ /**
26
+ * Extractor that walks a directory on disk and produces a `DirectoryElement` tree.
27
+ * - Recursively descends into subdirectories.
28
+ * - Detects an index file (e.g. `README.md`) and absorbs its content/description/title as the directory's own.
29
+ * - Dispatches non-index files to a matching `FileExtractor` based on extension; files with no matching extractor are silently skipped.
30
+ * - Merges file elements that share the same `key` (e.g. `TEMPLATE.md` and `template.ts`) using each extractor's `priority`.
31
+ * - Throws if a directory and a file (or two directories) share the same `key`.
32
+ */
33
+ export declare class DirectoryExtractor extends Extractor<Path, DirectoryElement> {
34
+ private readonly _indexes;
35
+ private readonly _extractors;
36
+ private readonly _base;
37
+ private readonly _ignore;
38
+ constructor({ index, extractors, base, ignore }?: DirectoryExtractorOptions);
39
+ extract(path: Path): Promise<DirectoryElement>;
40
+ private _extractDirectory;
41
+ private _extractChild;
42
+ }
@@ -0,0 +1,127 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import { mergeElements } from "../util/element.js";
3
+ import { splitFileExtension } from "../util/file.js";
4
+ import { anyMatch, requirePath, splitAbsolutePath } from "../util/index.js";
5
+ import { requireSlug } from "../util/string.js";
6
+ import { Extractor, mergeTreeElements } from "./Extractor.js";
7
+ import { FileExtractor } from "./FileExtractor.js";
8
+ import { MarkdownExtractor } from "./MarkdownExtractor.js";
9
+ import { TypescriptExtractor } from "./TypescriptExtractor.js";
10
+ /**
11
+ * Default list of filenames patterns treated as the directory's index file.
12
+ * - Matched case-insensitively (all entries stored lowercase).
13
+ * - If matched but no extractor is registered for the file's extension, the index is silently skipped.
14
+ */
15
+ const DEFAULT_INDEX = [/^readme\.txt$/i, /^readme\.md$/i, /^index\.md$/i, /^index\.ts$/i, /^index\.tsx$/i];
16
+ /** Default file extractor dispatch by extension. */
17
+ const DEFAULT_EXTRACTORS = {
18
+ md: new MarkdownExtractor(),
19
+ ts: new TypescriptExtractor(),
20
+ tsx: new TypescriptExtractor(),
21
+ txt: new FileExtractor(),
22
+ };
23
+ /**
24
+ * Default ignore patterns.
25
+ * - Skip test and spec files.
26
+ * - Skip `node_modules` directories.
27
+ * - Skip hidden `.` prefixed and underscore-prefixed files and directories.
28
+ */
29
+ const DEFAULT_IGNORE = [/\.test\.tsx?$/i, /\.spec\.tsx?$/i, /^node_modules$/i, /^[_.]/i];
30
+ /**
31
+ * Merge two tree elements, favouring the one with the highest priority.
32
+ * - We merge together elements with the same `key:` (e.g. `TEMPLATE.md` and `template.ts`).
33
+ * - `title` and `description` are taken from the higher-priority element.
34
+ * - `content` and `children` of both elements are merged (with the higher-priority element's content/children first).
35
+ */
36
+ function _mergeChild(existing, next) {
37
+ if (!existing)
38
+ return next;
39
+ return next.priority > existing.priority
40
+ ? { element: mergeTreeElements(next.element, existing.element), priority: next.priority }
41
+ : { element: mergeTreeElements(existing.element, next.element), priority: existing.priority };
42
+ }
43
+ /**
44
+ * Extractor that walks a directory on disk and produces a `DirectoryElement` tree.
45
+ * - Recursively descends into subdirectories.
46
+ * - Detects an index file (e.g. `README.md`) and absorbs its content/description/title as the directory's own.
47
+ * - Dispatches non-index files to a matching `FileExtractor` based on extension; files with no matching extractor are silently skipped.
48
+ * - Merges file elements that share the same `key` (e.g. `TEMPLATE.md` and `template.ts`) using each extractor's `priority`.
49
+ * - Throws if a directory and a file (or two directories) share the same `key`.
50
+ */
51
+ export class DirectoryExtractor extends Extractor {
52
+ _indexes;
53
+ _extractors;
54
+ _base;
55
+ _ignore;
56
+ constructor({ index = DEFAULT_INDEX, extractors = DEFAULT_EXTRACTORS, base, ignore = DEFAULT_IGNORE } = {}) {
57
+ super();
58
+ this._indexes = index;
59
+ this._extractors = extractors;
60
+ this._base = base;
61
+ this._ignore = ignore;
62
+ }
63
+ extract(path) {
64
+ return this._extractDirectory(requirePath(path, this._base, this.extract));
65
+ }
66
+ async _extractDirectory(path) {
67
+ const name = splitAbsolutePath(path).at(-1) ?? "";
68
+ const entries = await readdir(path, { withFileTypes: true });
69
+ // Keep track of the current index entry and children by key, so we can merge same-key elements.
70
+ let index;
71
+ const items = {};
72
+ for (const entry of entries) {
73
+ // Should we ignore this entry?
74
+ if (anyMatch(entry.name, ...this._ignore))
75
+ continue;
76
+ // Extract the child element and possibly merge it.
77
+ const child = await this._extractChild(path, entry);
78
+ if (child) {
79
+ // Is this entry an index? If so, we'll treat it as the directory itself and merge it with any existing index entry if needed.
80
+ if (anyMatch(entry.name, ...this._indexes)) {
81
+ index = _mergeChild(index, child);
82
+ }
83
+ else {
84
+ const key = child.element.key;
85
+ items[key] = _mergeChild(items[key], child);
86
+ }
87
+ }
88
+ }
89
+ const children = Object.values(items).map(({ element }) => element);
90
+ return {
91
+ type: "tree-directory",
92
+ key: requireSlug(name),
93
+ props: {
94
+ path,
95
+ name,
96
+ // `title` is only set when the absorbed index file has a confident one (e.g. README H1).
97
+ // Renderers fall back to `name` otherwise.
98
+ title: index?.element.props.title,
99
+ description: index?.element.props.description,
100
+ content: index?.element.props.content,
101
+ children: mergeElements(index?.element.props.children, children),
102
+ },
103
+ };
104
+ }
105
+ async _extractChild(base, entry) {
106
+ const name = entry.name;
107
+ const path = requirePath(name, base);
108
+ if (entry.isDirectory()) {
109
+ return {
110
+ element: await this._extractDirectory(path),
111
+ priority: this.priority,
112
+ };
113
+ }
114
+ else if (entry.isFile()) {
115
+ const [base, extension] = splitFileExtension(name);
116
+ if (!base || !extension)
117
+ return; // Skip files with no base name or extension.
118
+ const extractor = this._extractors[extension];
119
+ if (!extractor)
120
+ return; // Skip files with no registered extractor (including non-matching index files).
121
+ return {
122
+ element: await extractor.extract(Bun.file(path)),
123
+ priority: extractor.priority,
124
+ };
125
+ }
126
+ }
127
+ }
@@ -0,0 +1,24 @@
1
+ import { type TreeElement } from "../util/element.js";
2
+ /**
3
+ * Base class for an extractor that converts input into a tree element.
4
+ * - Extractors are composable: outer extractors delegate to inner extractors.
5
+ * - The output type is always a `TreeElement` (or a more specific subtype like `TreeElement`).
6
+ */
7
+ export declare abstract class Extractor<I, O extends TreeElement = TreeElement> {
8
+ /** Extract a tree element from the given input. */
9
+ abstract extract(input: I): Partial<O> | Promise<Partial<O>>;
10
+ /**
11
+ * Priority used to resolve same-key collisions when merging elements.
12
+ * - Higher-priority elements contribute their `title`, `description`, `path` to the merged result.
13
+ * - Higher-priority elements a prefixed (rather than suffixed) in `children` and `content` when merged.
14
+ * - Defaults to `0`; subclasses override (e.g. `MarkdownExtractor` is `10`).
15
+ */
16
+ readonly priority: number;
17
+ }
18
+ /**
19
+ * Merge two file elements with the same `key`.
20
+ * - `title` and `path` are taken from `primary` (the higher-priority element).
21
+ * - `description` is taken from `primary` if set, otherwise from `secondary`.
22
+ * - `content` and `children` from both are concatenated (primary first).
23
+ */
24
+ export declare function mergeTreeElements<T extends TreeElement>(primary: T, secondary: TreeElement): T;
@@ -0,0 +1,30 @@
1
+ import { mergeElements } from "../util/element.js";
2
+ /**
3
+ * Base class for an extractor that converts input into a tree element.
4
+ * - Extractors are composable: outer extractors delegate to inner extractors.
5
+ * - The output type is always a `TreeElement` (or a more specific subtype like `TreeElement`).
6
+ */
7
+ export class Extractor {
8
+ /**
9
+ * Priority used to resolve same-key collisions when merging elements.
10
+ * - Higher-priority elements contribute their `title`, `description`, `path` to the merged result.
11
+ * - Higher-priority elements a prefixed (rather than suffixed) in `children` and `content` when merged.
12
+ * - Defaults to `0`; subclasses override (e.g. `MarkdownExtractor` is `10`).
13
+ */
14
+ priority = 0;
15
+ }
16
+ export function mergeTreeElements(primary, secondary) {
17
+ return {
18
+ ...primary,
19
+ type: primary.type,
20
+ key: primary.key,
21
+ props: {
22
+ ...primary.props,
23
+ title: primary.props.title,
24
+ path: primary.props.path,
25
+ description: primary.props.description ?? secondary.props.description,
26
+ content: mergeElements(primary.props.content, secondary.props.content),
27
+ children: mergeElements(primary.props.children, secondary.props.children),
28
+ },
29
+ };
30
+ }
@@ -0,0 +1,22 @@
1
+ import type { BunFile } from "bun";
2
+ import type { FileElement, FileElementProps } from "../util/element.js";
3
+ import { Extractor } from "./Extractor.js";
4
+ /**
5
+ * Base extractor for a file in a tree.
6
+ * - Reads the file's content as text and stores it in `content`.
7
+ * - Sets `key` to the slugified basename (without extension).
8
+ * - Does NOT set `title` — `title` is only set by subclasses that have a confident source for one
9
+ * (e.g. `MarkdownExtractor` uses the first `<h1>`). Renderers fall back to `name` when missing.
10
+ * - Subclasses (e.g. `MarkdownExtractor`, `TypescriptExtractor`) override `extractProps()` to parse the content into richer elements.
11
+ */
12
+ export declare class FileExtractor extends Extractor<BunFile, FileElement> {
13
+ extract(file: BunFile): Promise<FileElement>;
14
+ /**
15
+ * Build the file element props from the extracted content.
16
+ * - `name` is the basename including extension (e.g. `"array.ts"`).
17
+ * - `base` is the basename without extension (e.g. `"array"`) — useful as a title fallback.
18
+ * - Override to parse `text` into richer elements (content/children/description) and to set
19
+ * `title` if a confident title is available.
20
+ */
21
+ extractProps(name: string, content: string): FileElementProps;
22
+ }
@@ -0,0 +1,34 @@
1
+ import { splitFileExtension } from "../util/file.js";
2
+ import { isAbsolutePath, splitAbsolutePath } from "../util/index.js";
3
+ import { requireSlug } from "../util/string.js";
4
+ import { Extractor } from "./Extractor.js";
5
+ /**
6
+ * Base extractor for a file in a tree.
7
+ * - Reads the file's content as text and stores it in `content`.
8
+ * - Sets `key` to the slugified basename (without extension).
9
+ * - Does NOT set `title` — `title` is only set by subclasses that have a confident source for one
10
+ * (e.g. `MarkdownExtractor` uses the first `<h1>`). Renderers fall back to `name` when missing.
11
+ * - Subclasses (e.g. `MarkdownExtractor`, `TypescriptExtractor`) override `extractProps()` to parse the content into richer elements.
12
+ */
13
+ export class FileExtractor extends Extractor {
14
+ async extract(file) {
15
+ const path = file.name ?? "unnamed";
16
+ const name = isAbsolutePath(path) ? (splitAbsolutePath(path).at(-1) ?? "unnamed") : path;
17
+ const [base = name] = splitFileExtension(name);
18
+ return {
19
+ type: "tree-file",
20
+ key: requireSlug(base),
21
+ props: this.extractProps(name, await file.text()),
22
+ };
23
+ }
24
+ /**
25
+ * Build the file element props from the extracted content.
26
+ * - `name` is the basename including extension (e.g. `"array.ts"`).
27
+ * - `base` is the basename without extension (e.g. `"array"`) — useful as a title fallback.
28
+ * - Override to parse `text` into richer elements (content/children/description) and to set
29
+ * `title` if a confident title is available.
30
+ */
31
+ extractProps(name, content) {
32
+ return { name, content };
33
+ }
34
+ }