@deslop/trips 0.1.1249 → 0.1.1256
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/README.md +2 -2
- package/dist/server.js +221 -24
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@ Your flights, trains and stays, with live gates, delays and platforms, for the T
|
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npm install --global @deslop/trips
|
|
7
|
-
trips service install --url https://trips.mp281x.xyz --auth https://auth.mp281x.xyz --apns-key-id <id> --apns-team-id <team>
|
|
7
|
+
trips service install --url https://trips.mp281x.xyz --auth https://auth.mp281x.xyz --gateway https://gateway.mp281x.xyz --apns-key-id <id> --apns-team-id <team>
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
- **Secrets** in `~/.deslop/trips.env`: `AEROAPI_KEY`, `
|
|
10
|
+
- **Secrets** in `~/.deslop/trips.env`: `AEROAPI_KEY`, `APNS_KEY`; AI keys live in Gateway.
|
|
11
11
|
|
|
12
12
|
Common flags and service commands: [Deslop app runtime](https://github.com/MP281X/deslop/blob/main/packages/runtime/README.md).
|
package/dist/server.js
CHANGED
|
@@ -5957,6 +5957,36 @@ const has$4 = /*#__PURE__*/ dual(2, (self, key) => Object.hasOwn(self, key));
|
|
|
5957
5957
|
*/
|
|
5958
5958
|
const get$11 = /*#__PURE__*/ dual(2, (self, key) => Object.hasOwn(self, key) ? some$1(self[key]) : none());
|
|
5959
5959
|
/**
|
|
5960
|
+
* Removes a key from a record.
|
|
5961
|
+
*
|
|
5962
|
+
* **When to use**
|
|
5963
|
+
*
|
|
5964
|
+
* Use to create a shallow copy of a record without one property.
|
|
5965
|
+
*
|
|
5966
|
+
* **Details**
|
|
5967
|
+
*
|
|
5968
|
+
* If the key is not present, the result is still a shallow copy of the original
|
|
5969
|
+
* record.
|
|
5970
|
+
*
|
|
5971
|
+
* **Example** (Removing a key)
|
|
5972
|
+
*
|
|
5973
|
+
* ```ts import.meta.vitest
|
|
5974
|
+
* import { Record } from "effect"
|
|
5975
|
+
*
|
|
5976
|
+
* Record.remove({ a: 1, b: 2 }, "a") // => { b: 2 }
|
|
5977
|
+
* ```
|
|
5978
|
+
*
|
|
5979
|
+
* @stability stable
|
|
5980
|
+
* @category mutations
|
|
5981
|
+
* @since 2.0.0
|
|
5982
|
+
*/
|
|
5983
|
+
const remove$6 = /*#__PURE__*/ dual(2, (self, key) => {
|
|
5984
|
+
if (!has$4(self, key)) return { ...self };
|
|
5985
|
+
const out = { ...self };
|
|
5986
|
+
delete out[key];
|
|
5987
|
+
return out;
|
|
5988
|
+
});
|
|
5989
|
+
/**
|
|
5960
5990
|
* Maps a record into another record by applying a transformation function to each of its values.
|
|
5961
5991
|
*
|
|
5962
5992
|
* **Example** (Mapping record values)
|
|
@@ -34849,6 +34879,8 @@ function decodeUnknownEffect$1(schema, options) {
|
|
|
34849
34879
|
function decodeUnknownOption$1(schema, options) {
|
|
34850
34880
|
return asOption(decodeUnknownEffect$1(schema, options));
|
|
34851
34881
|
}
|
|
34882
|
+
/** @internal */
|
|
34883
|
+
const decodeOption$1 = decodeUnknownOption$1;
|
|
34852
34884
|
/**
|
|
34853
34885
|
* Creates an effectful encoder for `unknown` input.
|
|
34854
34886
|
*
|
|
@@ -37366,6 +37398,33 @@ const decodeEffect = decodeUnknownEffect;
|
|
|
37366
37398
|
*/
|
|
37367
37399
|
const decodeUnknownOption = decodeUnknownOption$1;
|
|
37368
37400
|
/**
|
|
37401
|
+
* Decodes a typed input (the schema's `Encoded` type) against a schema,
|
|
37402
|
+
* returning an `Option` that is `Some` with the decoded value on success or
|
|
37403
|
+
* `None` for schema mismatches.
|
|
37404
|
+
*
|
|
37405
|
+
* **When to use**
|
|
37406
|
+
*
|
|
37407
|
+
* Use when you already have input typed as the schema's `Encoded` type and
|
|
37408
|
+
* only need to know whether decoding succeeded.
|
|
37409
|
+
*
|
|
37410
|
+
* **Details**
|
|
37411
|
+
*
|
|
37412
|
+
* For `unknown` input use {@link decodeUnknownOption}.
|
|
37413
|
+
* Options may be provided either when creating the decoder or when applying it;
|
|
37414
|
+
* application options override creation options.
|
|
37415
|
+
*
|
|
37416
|
+
* **Gotchas**
|
|
37417
|
+
*
|
|
37418
|
+
* Only causes made entirely of schema issues are converted to `None`. Causes
|
|
37419
|
+
* that contain defects, interruptions, or other non-schema reasons throw
|
|
37420
|
+
* instead.
|
|
37421
|
+
*
|
|
37422
|
+
* @stability stable
|
|
37423
|
+
* @category decoding
|
|
37424
|
+
* @since 3.10.0
|
|
37425
|
+
*/
|
|
37426
|
+
const decodeOption = decodeOption$1;
|
|
37427
|
+
/**
|
|
37369
37428
|
* Decodes an `unknown` input against a schema synchronously, returning the
|
|
37370
37429
|
* decoded value or throwing a {@link SchemaError} for schema mismatches.
|
|
37371
37430
|
*
|
|
@@ -39697,6 +39756,25 @@ function Redacted$1(value$7, options) {
|
|
|
39697
39756
|
});
|
|
39698
39757
|
return make$56(schema.ast, { value: value$7 });
|
|
39699
39758
|
}
|
|
39759
|
+
/**
|
|
39760
|
+
* Decodes a value and wraps it in `Redacted<A>`. Unlike {@link Redacted} which
|
|
39761
|
+
* expects the input to already be a `Redacted` instance, this schema decodes
|
|
39762
|
+
* the raw value and wraps it.
|
|
39763
|
+
*
|
|
39764
|
+
* @see {@link Redacted} for schemas whose input is already a `Redacted` value.
|
|
39765
|
+
* @stability stable
|
|
39766
|
+
* @category schemas
|
|
39767
|
+
* @since 4.0.0
|
|
39768
|
+
*/
|
|
39769
|
+
function RedactedFromValue(value$8, options) {
|
|
39770
|
+
return decodeTo(Redacted$1(toType(value$8), {
|
|
39771
|
+
label: options?.label,
|
|
39772
|
+
disallowJsonEncode: options?.disallowEncode
|
|
39773
|
+
}), {
|
|
39774
|
+
decode: transform$4((t) => make$61(t, { label: options?.label })),
|
|
39775
|
+
encode: options?.disallowEncode ? forbidden((oe) => "Cannot encode Redacted" + (isSome(oe) && typeof oe.value.label === "string" ? ` with label: "${oe.value.label}"` : "")) : transform$4(value)
|
|
39776
|
+
})(value$8);
|
|
39777
|
+
}
|
|
39700
39778
|
const immerable = /*#__PURE__*/ globalThis.Symbol.for("immer-draftable");
|
|
39701
39779
|
const payloadToken = {};
|
|
39702
39780
|
function makeClass(Inherited, identifier, struct$1, annotations, proto) {
|
|
@@ -51476,6 +51554,14 @@ const endSpanWithStatusError = (fiber, span, request, response) => {
|
|
|
51476
51554
|
*/
|
|
51477
51555
|
const mapRequest = /*#__PURE__*/ dual(2, (self, f) => makeWith(self.postprocess, (request) => map$5(self.preprocess(request), f)));
|
|
51478
51556
|
/**
|
|
51557
|
+
* Appends an effectful transformation of the request object before sending it.
|
|
51558
|
+
*
|
|
51559
|
+
* @stability unstable
|
|
51560
|
+
* @category mapping
|
|
51561
|
+
* @since 4.0.0
|
|
51562
|
+
*/
|
|
51563
|
+
const mapRequestEffect = /*#__PURE__*/ dual(2, (self, f) => makeWith(self.postprocess, (request) => flatMap$3(self.preprocess(request), f)));
|
|
51564
|
+
/**
|
|
51479
51565
|
* Retries common transient errors, such as rate limiting, timeouts or network issues.
|
|
51480
51566
|
*
|
|
51481
51567
|
* **When to use**
|
|
@@ -78537,6 +78623,29 @@ var AiError = class extends (/*#__PURE__*/ Error$1("effect/ai/AiError/AiError")(
|
|
|
78537
78623
|
}
|
|
78538
78624
|
};
|
|
78539
78625
|
/**
|
|
78626
|
+
* Type guard to check if a value is an `AiError`.
|
|
78627
|
+
*
|
|
78628
|
+
* **Example** (Checking for an AI error)
|
|
78629
|
+
*
|
|
78630
|
+
* ```ts import.meta.vitest
|
|
78631
|
+
* import { AiError } from "effect/ai"
|
|
78632
|
+
*
|
|
78633
|
+
* const someError = new Error("generic error")
|
|
78634
|
+
* const aiError = AiError.make({
|
|
78635
|
+
* module: "Test",
|
|
78636
|
+
* method: "example",
|
|
78637
|
+
* reason: new AiError.RateLimitError({})
|
|
78638
|
+
* })
|
|
78639
|
+
*
|
|
78640
|
+
* const result = [AiError.isAiError(someError), AiError.isAiError(aiError)] // => [false, true]
|
|
78641
|
+
* ```
|
|
78642
|
+
*
|
|
78643
|
+
* @stability unstable
|
|
78644
|
+
* @category guards
|
|
78645
|
+
* @since 4.0.0
|
|
78646
|
+
*/
|
|
78647
|
+
const isAiError = (u) => hasProperty(u, TypeId$4);
|
|
78648
|
+
/**
|
|
78540
78649
|
* Type guard to check if a value is an `AiErrorReason`.
|
|
78541
78650
|
*
|
|
78542
78651
|
* **Example** (Checking for an AI error reason)
|
|
@@ -83106,6 +83215,78 @@ function failureOptions(error, status) {
|
|
|
83106
83215
|
}
|
|
83107
83216
|
var CurrentUser = class extends Service$1()("@deslop/runtime/auth/lib/utils/CurrentUser") {};
|
|
83108
83217
|
var RpcAuth = class extends Service()("@deslop/runtime/auth/lib/utils/RpcAuth", { error: AuthError }) {};
|
|
83218
|
+
Literals([
|
|
83219
|
+
"anthropic",
|
|
83220
|
+
"openrouter",
|
|
83221
|
+
"opencode-zen",
|
|
83222
|
+
"opencode-go"
|
|
83223
|
+
]);
|
|
83224
|
+
// ../../packages/runtime/src/ai/service.ts
|
|
83225
|
+
var AiUnavailable = class extends TaggedError()("AiUnavailable", { message: String$6 }) {};
|
|
83226
|
+
const Refusal = fromJsonString(Struct({ error: Struct({ message: String$6 }) }));
|
|
83227
|
+
function aiFailure(cause) {
|
|
83228
|
+
if (is(AiUnavailable)(cause)) return some$1(cause.message);
|
|
83229
|
+
if (!isAiError(cause)) return none();
|
|
83230
|
+
if (cause.reason._tag === "NetworkError") return some$1(cause.reason.description ?? cause.reason.message);
|
|
83231
|
+
if (cause.reason._tag === "UnknownError" && cause.reason.http?.body !== void 0) return map$11(decodeOption(Refusal)(cause.reason.http.body), (body) => body.error.message);
|
|
83232
|
+
return some$1(cause.reason.message);
|
|
83233
|
+
}
|
|
83234
|
+
var AiGateway = class AiGateway extends Service$1()("@deslop/runtime/ai/service/AiGateway") {
|
|
83235
|
+
static layer = effect(this, gen(function* () {
|
|
83236
|
+
const gateway = yield* option(String$5("GATEWAY_URL"));
|
|
83237
|
+
const local = yield* localAuth;
|
|
83238
|
+
const app = yield* String$5("APP_URL");
|
|
83239
|
+
const client = yield* HttpClient;
|
|
83240
|
+
const store = toSchemaStore(yield* KeyValueStore, Record$1(String$6, RedactedFromValue(String$6)));
|
|
83241
|
+
const grants = yield* make$42(getOrElse(yield* store.get("ai-gateway-grants"), () => ({})));
|
|
83242
|
+
const lock = yield* make$66(1);
|
|
83243
|
+
return AiGateway.of({
|
|
83244
|
+
apiUrl: (provider) => match$9(gateway, {
|
|
83245
|
+
onNone: () => fail$6(AiUnavailable.make({ message: "Start the app with --gateway" })),
|
|
83246
|
+
onSome: (url) => succeed$5(`${url}/ai/${provider}${match$1(provider === "openrouter", {
|
|
83247
|
+
onFalse: () => "",
|
|
83248
|
+
onTrue: () => "/v1"
|
|
83249
|
+
})}`)
|
|
83250
|
+
}),
|
|
83251
|
+
authorize: (userId) => (http) => pipe(mapRequestEffect(http, (request) => gen(function* () {
|
|
83252
|
+
if (local) return request;
|
|
83253
|
+
const token = (yield* get$2(grants))[userId];
|
|
83254
|
+
if (token === void 0) return yield* new HttpClientError({ reason: new TransportError({
|
|
83255
|
+
description: "AI access is unavailable; sign in again to enroll with Gateway",
|
|
83256
|
+
request
|
|
83257
|
+
}) });
|
|
83258
|
+
return setHeader$1(request, "authorization", `Bearer ${value(token)}`);
|
|
83259
|
+
})), tap((response) => pipe(gen(function* () {
|
|
83260
|
+
if (local || response.headers["x-gateway-grant-refused"] === void 0 || !exists(gateway, (url) => startsWith(`${url}/ai/`)(response.request.url))) return;
|
|
83261
|
+
const current = yield* get$2(grants);
|
|
83262
|
+
const token = current[userId];
|
|
83263
|
+
if (token === void 0 || response.request.headers["authorization"] !== `Bearer ${value(token)}`) return;
|
|
83264
|
+
const next = remove$6(current, userId);
|
|
83265
|
+
yield* pipe(store.set("ai-gateway-grants", next), ignore$1({
|
|
83266
|
+
log: "Warn",
|
|
83267
|
+
message: "The rejected AI grant could not be removed from storage"
|
|
83268
|
+
}));
|
|
83269
|
+
yield* set(grants, next);
|
|
83270
|
+
}), withPermit(lock)))),
|
|
83271
|
+
enroll: fnUntraced(function* (userId, headers) {
|
|
83272
|
+
return yield* pipe(gen(function* () {
|
|
83273
|
+
if (local || isNone(gateway) || (yield* get$2(grants))[userId] !== void 0) return;
|
|
83274
|
+
const response = yield* client.execute(yield* bodyJson(post(`${getOrElse(gateway, () => "")}/ai/grants`, { headers: match$1(headers["authorization"] !== void 0, {
|
|
83275
|
+
onFalse: () => ({ cookie: headers["cookie"] ?? "" }),
|
|
83276
|
+
onTrue: () => ({ authorization: headers["authorization"] })
|
|
83277
|
+
}) }), { app }));
|
|
83278
|
+
const result = yield* schemaBodyJson(Struct({ token: String$6 }))(response);
|
|
83279
|
+
const next = {
|
|
83280
|
+
...yield* get$2(grants),
|
|
83281
|
+
[userId]: make$61(result.token)
|
|
83282
|
+
};
|
|
83283
|
+
yield* store.set("ai-gateway-grants", next);
|
|
83284
|
+
yield* set(grants, next);
|
|
83285
|
+
}), withPermit(lock), timeout$1("10 seconds"), catch_$2(() => logWarning("AI Gateway enrollment failed")));
|
|
83286
|
+
})
|
|
83287
|
+
});
|
|
83288
|
+
}));
|
|
83289
|
+
};
|
|
83109
83290
|
// ../../packages/runtime/src/auth/service.ts
|
|
83110
83291
|
function rejected(message) {
|
|
83111
83292
|
return mapError$2((cause) => {
|
|
@@ -83124,12 +83305,18 @@ function rejected(message) {
|
|
|
83124
83305
|
function developer() {
|
|
83125
83306
|
return succeed$5(DEVELOPER);
|
|
83126
83307
|
}
|
|
83308
|
+
function enrolled(user, headers) {
|
|
83309
|
+
return gen(function* () {
|
|
83310
|
+
const gateway = getOrUndefined(yield* context(), AiGateway);
|
|
83311
|
+
if (gateway !== void 0) yield* gateway.enroll(user.id, headers);
|
|
83312
|
+
});
|
|
83313
|
+
}
|
|
83127
83314
|
const unavailable = text$1("The authorization service is temporarily unavailable; retry later", {
|
|
83128
83315
|
headers: { "retry-after": "5" },
|
|
83129
83316
|
status: 503
|
|
83130
83317
|
});
|
|
83131
83318
|
var Auth = class Auth extends Service$1()("@deslop/runtime/auth/service/Auth") {
|
|
83132
|
-
static makeContext = (auth) => pipe(make$76(Auth, auth), add$1(RpcAuth, RpcAuth.of((effect, request) => pipe(auth.user(request.headers), tap$2(() => {
|
|
83319
|
+
static makeContext = (auth) => pipe(make$76(Auth, auth), add$1(RpcAuth, RpcAuth.of((effect, request) => pipe(auth.user(request.headers), tap$2((user) => enrolled(user, request.headers)), tap$2(() => {
|
|
83133
83320
|
if (isStreamSchema(request.rpc.successSchema)) return annotateCurrentSpan("rpc.stream", true);
|
|
83134
83321
|
return void_$1;
|
|
83135
83322
|
}), flatMap$3((user) => raceFirst(provideService$2(effect, CurrentUser, user), pipe(delay(auth.user(request.headers), "5 minutes"), retry({ while: (error) => error.error === "temporarily_unavailable" }), forever)))))));
|
|
@@ -83164,6 +83351,7 @@ middleware()(gen(function* () {
|
|
|
83164
83351
|
if (user.failure.error === "temporarily_unavailable") return unavailable;
|
|
83165
83352
|
return text$1("Sign in first", { status: 401 });
|
|
83166
83353
|
}
|
|
83354
|
+
yield* enrolled(user.success, (yield* HttpServerRequest).headers);
|
|
83167
83355
|
return yield* provideService$2(app, CurrentUser, user.success);
|
|
83168
83356
|
});
|
|
83169
83357
|
}));
|
|
@@ -83546,6 +83734,11 @@ const SETTINGS = {
|
|
|
83546
83734
|
flag: "auth",
|
|
83547
83735
|
schema: SecureOrigin
|
|
83548
83736
|
},
|
|
83737
|
+
GATEWAY_URL: {
|
|
83738
|
+
description: "Deslop Gateway origin for AI calls",
|
|
83739
|
+
flag: "gateway",
|
|
83740
|
+
schema: Origin
|
|
83741
|
+
},
|
|
83549
83742
|
HOST: {
|
|
83550
83743
|
description: `Listen address; defaults to ${DEFAULT_HOST}`,
|
|
83551
83744
|
flag: "host",
|
|
@@ -83577,7 +83770,7 @@ function server(app) {
|
|
|
83577
83770
|
return pipe(serve(pipe(mergeAll$2(app.routes, layerRoutes, layerIcon(app.icon), layerWeb, layerAnnounce), provide$2(match$9(fromUndefinedOr(app.middleware), {
|
|
83578
83771
|
onNone: () => empty$13,
|
|
83579
83772
|
onSome: (middleware$1) => middleware()(middleware$1).layer
|
|
83580
|
-
})), provide$2(Auth.layer)), {
|
|
83773
|
+
})), provide$2(Auth.layer), provideMerge(pipe(AiGateway.layer, provide$2(layerDataStore)))), {
|
|
83581
83774
|
disableLogger: true,
|
|
83582
83775
|
middleware: guard
|
|
83583
83776
|
}), provide$2(mergeAll$2(layerProtocol, match$1(app.telemetry === false, {
|
|
@@ -93071,15 +93264,22 @@ function bounded(text) {
|
|
|
93071
93264
|
}
|
|
93072
93265
|
var Extractor = class Extractor extends Service$1()("@deslop/trips/services/bookings/lib/extraction/Extractor") {
|
|
93073
93266
|
static layer = effect(this, gen(function* () {
|
|
93074
|
-
const
|
|
93075
|
-
const
|
|
93076
|
-
|
|
93077
|
-
|
|
93078
|
-
|
|
93079
|
-
|
|
93080
|
-
|
|
93081
|
-
|
|
93082
|
-
|
|
93267
|
+
const gateway = yield* AiGateway;
|
|
93268
|
+
const http = yield* HttpClient;
|
|
93269
|
+
const model = fnUntraced(function* (userId) {
|
|
93270
|
+
return yield* pipe(make({
|
|
93271
|
+
config: {
|
|
93272
|
+
max_tokens: 16e3,
|
|
93273
|
+
output_config: { effort: "high" }
|
|
93274
|
+
},
|
|
93275
|
+
model: "claude-haiku-5-5"
|
|
93276
|
+
}), provideServiceEffect(AnthropicClient, pipe(make$1({
|
|
93277
|
+
apiUrl: yield* gateway.apiUrl("anthropic"),
|
|
93278
|
+
transformClient: gateway.authorize(userId)
|
|
93279
|
+
}), provideService$2(HttpClient, http))));
|
|
93280
|
+
});
|
|
93281
|
+
return Extractor.of({ read: fn("Extractor.read")(function* (userId, source) {
|
|
93282
|
+
const anthropic = yield* model(userId);
|
|
93083
93283
|
const today = `Today: ${formatIsoDateUtc(makeUnsafe$3(yield* currentTimeMillis))}`;
|
|
93084
93284
|
function content() {
|
|
93085
93285
|
if (hasProperty(source, "image")) return [{
|
|
@@ -93092,7 +93292,7 @@ var Extractor = class Extractor extends Service$1()("@deslop/trips/services/book
|
|
|
93092
93292
|
}];
|
|
93093
93293
|
return `${today}\n\n${bounded(source.text)}`;
|
|
93094
93294
|
}
|
|
93095
|
-
return (yield*
|
|
93295
|
+
return (yield* anthropic.generateObject({
|
|
93096
93296
|
prompt: [{
|
|
93097
93297
|
content: INSTRUCTIONS,
|
|
93098
93298
|
role: "system"
|
|
@@ -93102,16 +93302,13 @@ var Extractor = class Extractor extends Service$1()("@deslop/trips/services/book
|
|
|
93102
93302
|
}],
|
|
93103
93303
|
schema: Extraction
|
|
93104
93304
|
})).value.items;
|
|
93105
|
-
}, timeout$1("3 minutes"), retry({
|
|
93305
|
+
}, timeout$1("3 minutes"), retry({
|
|
93306
|
+
times: 1,
|
|
93307
|
+
while: (cause) => !is(AiUnavailable)(cause)
|
|
93308
|
+
}), mapError$2((cause) => BookingsError.make({
|
|
93106
93309
|
cause: make$61(cause),
|
|
93107
|
-
message: "The AI could not read the booking."
|
|
93108
|
-
})));
|
|
93109
|
-
return Extractor.of({ read: fn("Extractor.read")(function* (source) {
|
|
93110
|
-
return yield* match$9(key, {
|
|
93111
|
-
onNone: () => fail$6(BookingsError.make({ message: "The server has no AI key to read bookings." })),
|
|
93112
|
-
onSome: () => generate(source)
|
|
93113
|
-
});
|
|
93114
|
-
}) });
|
|
93310
|
+
message: getOrElse(aiFailure(cause), () => "The AI could not read the booking.")
|
|
93311
|
+
}))) });
|
|
93115
93312
|
}));
|
|
93116
93313
|
};
|
|
93117
93314
|
// src/services/bookings/lib/utils.ts
|
|
@@ -93819,8 +94016,8 @@ var Bookings = class Bookings extends Service$1()("@deslop/trips/services/bookin
|
|
|
93819
94016
|
return make$75(void 0, [...current, booking]);
|
|
93820
94017
|
});
|
|
93821
94018
|
}),
|
|
93822
|
-
save: fn("Bookings.save")(function* (source) {
|
|
93823
|
-
const items = yield* extractor.read(source);
|
|
94019
|
+
save: fn("Bookings.save")(function* (userId, source) {
|
|
94020
|
+
const items = yield* extractor.read(userId, source);
|
|
93824
94021
|
if (isReadonlyArrayEmpty(items)) return yield* BookingsError.make({ message: "No booking found. Copy a confirmation or boarding pass and try again." });
|
|
93825
94022
|
const resolved = yield* forEach$1(items, (item) => result(resolve(item)), { concurrency: 1 });
|
|
93826
94023
|
const issues = getFailures(resolved);
|
|
@@ -121874,7 +122071,7 @@ runApp({
|
|
|
121874
122071
|
"bookings.refresh": (input) => tracker.refresh(input.id),
|
|
121875
122072
|
"bookings.remove": (input) => bookings.remove(input.id),
|
|
121876
122073
|
"bookings.restore": (input) => bookings.restore(input),
|
|
121877
|
-
"bookings.save": (input) => bookings.save(input),
|
|
122074
|
+
"bookings.save": (input) => flatMap$3(CurrentUser, (user) => bookings.save(user.id, input)),
|
|
121878
122075
|
"bookings.watch": () => bookings.events,
|
|
121879
122076
|
"devices.register": (input) => push.register(input)
|
|
121880
122077
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deslop/trips",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1256",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/MP281X/deslop.git",
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"engines": {
|
|
31
31
|
"node": ">=26"
|
|
32
32
|
},
|
|
33
|
-
"fingerprint": "
|
|
33
|
+
"fingerprint": "72cb3e330ae400d6eed04c6308b0f230fd667441197fd59f248740abe95c20a1"
|
|
34
34
|
}
|