@mdbase-dev/pickle 0.1.0-beta.31 → 0.1.0-beta.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { CollectionContractDescriptor, CollectionDescription, CollectionTypeDescriptor, JsonObject, RecordDocument } from "@mdbase-dev/connect-protocol";
2
- import { type MdbaseConnection } from "@mdbase-dev/connect";
2
+ import { type ConnectRequestOptions, type MdbaseConnection, type PendingMutation } from "@mdbase-dev/connect";
3
3
  export { PICKLE_ACK_RESPONSE_TYPE_DOCUMENT, PICKLE_APPROVAL_RESPONSE_TYPE_DOCUMENT, PICKLE_REQUEST_CONTRACT_DOCUMENT, PICKLE_REQUEST_CONTRACT_DIGEST, PICKLE_TYPE_PACK_PROVISION, PICKLE_REQUEST_TYPE_DOCUMENT } from "./resources.js";
4
4
  export declare const PICKLE_REQUEST_CONTRACT = "pickle.request";
5
5
  export declare const PICKLE_REQUEST_CONTRACT_VERSION = "1.0.0";
@@ -78,13 +78,23 @@ export interface PickleRequest {
78
78
  response?: PickleResponse;
79
79
  frontmatter: PickleFrontmatter;
80
80
  }
81
- export interface RespondOptions {
81
+ export interface RespondOptions extends ConnectRequestOptions {
82
82
  responder?: string;
83
83
  }
84
+ export type PickleResponseSubmission = {
85
+ kind: "recorded";
86
+ record: RecordDocument<PickleFrontmatter>;
87
+ } | {
88
+ kind: "pending";
89
+ requestId: string;
90
+ };
91
+ export type PicklePendingResponse = PendingMutation<RecordDocument<PickleFrontmatter>>;
84
92
  export interface PickleClient {
85
- describe(): ReturnType<MdbaseConnection<PickleFrontmatter>["describe"]>;
86
- queryAll(input: Parameters<MdbaseConnection<PickleFrontmatter>["queryAll"]>[0]): ReturnType<MdbaseConnection<PickleFrontmatter>["queryAll"]>;
87
- create(input: Parameters<MdbaseConnection<PickleFrontmatter>["create"]>[0]): ReturnType<MdbaseConnection<PickleFrontmatter>["create"]>;
93
+ describe(options?: ConnectRequestOptions): ReturnType<MdbaseConnection<PickleFrontmatter>["describe"]>;
94
+ queryAll(input: Parameters<MdbaseConnection<PickleFrontmatter>["queryAll"]>[0], options?: Parameters<MdbaseConnection<PickleFrontmatter>["queryAll"]>[1]): ReturnType<MdbaseConnection<PickleFrontmatter>["queryAll"]>;
95
+ create(input: Parameters<MdbaseConnection<PickleFrontmatter>["create"]>[0], options?: ConnectRequestOptions): ReturnType<MdbaseConnection<PickleFrontmatter>["create"]>;
96
+ pendingMutations<Result = unknown>(): readonly PendingMutation<Result>[];
97
+ pendingMutation<Result = unknown>(requestId: string): PendingMutation<Result> | null;
88
98
  }
89
99
  export declare function resolvePickleContract(description: CollectionDescription): PickleContract;
90
100
  export declare class PickleCollection {
@@ -96,8 +106,14 @@ export declare class PickleCollection {
96
106
  collection: CollectionDescription;
97
107
  contract: PickleContract;
98
108
  }>;
99
- list(): Promise<PickleRequest[]>;
100
- respond(request: PickleRequest, payload: JsonObject, options?: RespondOptions): Promise<RecordDocument<PickleFrontmatter>>;
109
+ describe(options: ConnectRequestOptions): Promise<{
110
+ collection: CollectionDescription;
111
+ contract: PickleContract;
112
+ }>;
113
+ list(options?: ConnectRequestOptions): Promise<PickleRequest[]>;
114
+ respond(request: PickleRequest, payload: JsonObject, options?: RespondOptions): Promise<PickleResponseSubmission>;
115
+ pendingResponses(): readonly PicklePendingResponse[];
116
+ recoverResponse(requestId: string, options?: ConnectRequestOptions): Promise<PickleResponseSubmission>;
101
117
  }
102
118
  export declare class PickleContractError extends Error {
103
119
  }
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { MDBASE_RECORD_CREATED_CONTRACT } from "@mdbase-dev/connect-protocol";
2
- import { unwrapConnectOutcome } from "@mdbase-dev/connect";
2
+ import { ConnectOutcomeError, unwrapConnectOutcome } from "@mdbase-dev/connect";
3
3
  import { PICKLE_REQUEST_CONTRACT_DIGEST } from "./resources.js";
4
4
  export { PICKLE_ACK_RESPONSE_TYPE_DOCUMENT, PICKLE_APPROVAL_RESPONSE_TYPE_DOCUMENT, PICKLE_REQUEST_CONTRACT_DOCUMENT, PICKLE_REQUEST_CONTRACT_DIGEST, PICKLE_TYPE_PACK_PROVISION, PICKLE_REQUEST_TYPE_DOCUMENT } from "./resources.js";
5
5
  export const PICKLE_REQUEST_CONTRACT = "pickle.request";
@@ -47,18 +47,18 @@ export class PickleCollection {
47
47
  constructor(connect) {
48
48
  this.connect = connect;
49
49
  }
50
- async describe() {
51
- this.description ??= unwrapConnectOutcome(await this.connect.describe());
50
+ async describe(options = {}) {
51
+ this.description ??= unwrapConnectOutcome(await this.connect.describe(options));
52
52
  this.contract ??= resolvePickleContract(this.description);
53
53
  return { collection: this.description, contract: this.contract };
54
54
  }
55
- async list() {
56
- const { collection, contract } = await this.describe();
55
+ async list(options = {}) {
56
+ const { collection, contract } = await this.describe(options);
57
57
  const requestQuery = unwrapConnectOutcome(await this.connect.queryAll({
58
58
  types: contract.implementations.map(({ typeName }) => typeName),
59
59
  include_body: true,
60
60
  frontmatter_mode: "effective"
61
- }));
61
+ }, options));
62
62
  const requests = requestQuery.results.map(requireEffectiveFrontmatter);
63
63
  const responseTypes = [
64
64
  ...new Set(requests
@@ -73,7 +73,7 @@ export class PickleCollection {
73
73
  types: responseTypes,
74
74
  include_body: true,
75
75
  frontmatter_mode: "effective"
76
- }))).results.map(requireEffectiveFrontmatter)
76
+ }, options))).results.map(requireEffectiveFrontmatter)
77
77
  : [];
78
78
  return requests
79
79
  .map((record) => normalizeRequest(record, responses, collection, contract))
@@ -91,23 +91,50 @@ export class PickleCollection {
91
91
  }
92
92
  const responseFolder = stringField(asObject(responseType.collection?.path), "folder") ||
93
93
  "responses";
94
+ const { responder, ...requestOptions } = options;
94
95
  const frontmatter = {
95
96
  ...payload,
96
97
  type: request.responseType,
97
98
  request: requestLink(request.path),
98
- responder: options.responder?.trim() || "human"
99
+ responder: responder?.trim() || "human"
99
100
  };
100
101
  const created = await this.connect.create({
101
102
  type: request.responseType,
102
103
  path: `${trimSlashes(responseFolder)}/${crypto.randomUUID()}.md`,
103
104
  frontmatter,
104
105
  body: ""
105
- });
106
- return unwrapConnectOutcome(created);
106
+ }, requestOptions);
107
+ return responseSubmission(created);
108
+ }
109
+ pendingResponses() {
110
+ return this.connect
111
+ .pendingMutations()
112
+ .filter((mutation) => mutation.operation === "create");
113
+ }
114
+ async recoverResponse(requestId, options = {}) {
115
+ const pending = this.connect.pendingMutation(requestId);
116
+ if (!pending || pending.operation !== "create") {
117
+ throw new PickleContractError("This pending Pickle response is no longer available for recovery.");
118
+ }
119
+ return responseSubmission(await pending.recover(options));
107
120
  }
108
121
  }
109
122
  export class PickleContractError extends Error {
110
123
  }
124
+ function responseSubmission(outcome) {
125
+ if (outcome.ok)
126
+ return { kind: "recorded", record: outcome.value };
127
+ const requestId = outcome.problem.code === "operation_outcome_unknown" &&
128
+ outcome.problem.details &&
129
+ typeof outcome.problem.details === "object" &&
130
+ "request_id" in outcome.problem.details &&
131
+ typeof outcome.problem.details.request_id === "string"
132
+ ? outcome.problem.details.request_id
133
+ : null;
134
+ if (requestId)
135
+ return { kind: "pending", requestId };
136
+ throw new ConnectOutcomeError(outcome.problem);
137
+ }
111
138
  function normalizeRequest(record, responseRecords, description, contract) {
112
139
  const implementation = implementationForRecord(contract, record);
113
140
  const responseType = stringField(record.effective_frontmatter, role(implementation, "response_type", "response_type")) || "pickle_response_approval";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mdbase-dev/pickle",
3
- "version": "0.1.0-beta.31",
3
+ "version": "0.1.0-beta.32",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -22,13 +22,13 @@
22
22
  "README.md"
23
23
  ],
24
24
  "dependencies": {
25
- "@mdbase-dev/connect": "0.1.0-beta.31",
26
- "@mdbase-dev/connect-protocol": "0.1.0-beta.31"
25
+ "@mdbase-dev/connect-protocol": "0.1.0-beta.32",
26
+ "@mdbase-dev/connect": "0.1.0-beta.32"
27
27
  },
28
28
  "devDependencies": {
29
29
  "typescript": "^7.0.2",
30
30
  "vitest": "^4.1.10",
31
- "@mdbase-dev/connect-dev": "0.1.0-beta.31"
31
+ "@mdbase-dev/connect-dev": "0.1.0-beta.32"
32
32
  },
33
33
  "scripts": {
34
34
  "build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json",