ignotum 0.0.7 → 0.0.8

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/README.md +85 -101
  2. package/dist/cli/bin.mjs +869 -175
  3. package/dist/cli/bin.mjs.map +1 -1
  4. package/dist/runtime/{api-DtX8qPrq.js → api-BTeMI5tx.js} +27 -3
  5. package/dist/runtime/api-BTeMI5tx.js.map +1 -0
  6. package/dist/runtime/{api-Dp4J-xt-.d.ts → api-D9lV-5av.d.ts} +7 -9
  7. package/dist/runtime/client.d.ts +12 -5
  8. package/dist/runtime/client.js +275 -52
  9. package/dist/runtime/client.js.map +1 -1
  10. package/dist/runtime/{descriptor-t6BOEGw9-C1rwYIlx.js → descriptor-C5VA9qRl-C338iC6l.js} +38 -7
  11. package/dist/runtime/descriptor-C5VA9qRl-C338iC6l.js.map +1 -0
  12. package/dist/runtime/file-BXf63ulU.js +166 -0
  13. package/dist/runtime/file-BXf63ulU.js.map +1 -0
  14. package/dist/runtime/{id-Btwac71X-DhnKYsjY.d.ts → id-Btwac71X-DGj0DQuu.d.ts} +50 -4
  15. package/dist/runtime/{index-B5KSOjGN.d.ts → index-CF04_Dps.d.ts} +39 -20
  16. package/dist/runtime/internal/api.d.ts +2 -2
  17. package/dist/runtime/internal/api.js +1 -1
  18. package/dist/runtime/internal/host.d.ts +8 -7
  19. package/dist/runtime/internal/host.js +21 -10
  20. package/dist/runtime/internal/host.js.map +1 -1
  21. package/dist/runtime/internal/server.d.ts +1 -1
  22. package/dist/runtime/internal/server.js +1 -1
  23. package/dist/runtime/internal/types.d.ts +1 -1
  24. package/dist/runtime/internal/types.js +1 -1
  25. package/dist/runtime/pagination-BNFhAjns.d.ts +1 -0
  26. package/dist/runtime/{pagination-B1BzNkh8-BUSTbeSg.d.ts → pagination-DrOowBve-Bnipd34u.d.ts} +8 -4
  27. package/dist/runtime/{schema-D9RmboaS.js → schema-DJfwfq87.js} +17 -3
  28. package/dist/runtime/schema-DJfwfq87.js.map +1 -0
  29. package/dist/runtime/server.d.ts +3 -3
  30. package/dist/runtime/server.js +2 -2
  31. package/dist/runtime/server.js.map +1 -1
  32. package/dist/runtime/sync-mIXn9eKv.d.ts +8 -0
  33. package/package.json +4 -4
  34. package/src/cli/agent-files.ts +52 -13
  35. package/src/cli/app-configuration.ts +4 -1
  36. package/src/cli/build/server.ts +83 -6
  37. package/src/cli/new-app.ts +15 -0
  38. package/src/client/files.ts +168 -0
  39. package/src/client/hooks.ts +2 -15
  40. package/src/client/index.ts +7 -0
  41. package/src/client/sync.ts +137 -21
  42. package/src/dev-runtime/database.ts +69 -57
  43. package/src/dev-runtime/files.ts +338 -0
  44. package/src/dev-runtime/functions.ts +14 -6
  45. package/src/dev-runtime/migrations.ts +14 -0
  46. package/src/dev-runtime/sync.ts +123 -5
  47. package/src/internal/api.ts +16 -1
  48. package/src/server/index.ts +8 -1
  49. package/dist/runtime/api-DtX8qPrq.js.map +0 -1
  50. package/dist/runtime/descriptor-t6BOEGw9-C1rwYIlx.js.map +0 -1
  51. package/dist/runtime/id-D570vudg.js +0 -26
  52. package/dist/runtime/id-D570vudg.js.map +0 -1
  53. package/dist/runtime/pagination-BKPko9Hm.d.ts +0 -1
  54. package/dist/runtime/schema-D9RmboaS.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { a as InvocationId, c as SubscriptionId, n as DeploymentId, t as AppId } from "./id-D570vudg.js";
1
+ import { _ as AppId, a as RuntimeFileMetadata, o as RuntimeFileOccurrence, v as DeploymentId, w as SubscriptionId, x as InvocationId } from "./file-BXf63ulU.js";
2
2
  import { Predicate, Schema } from "effect";
3
3
  //#region ../contracts/dist/runtime/identity.js
4
4
  const InvocationKey = Schema.String.pipe(Schema.brand("ignotum/hosted/InvocationKey"));
@@ -36,9 +36,18 @@ const Invoke = Schema.Struct({
36
36
  function: FunctionAddress,
37
37
  args: Schema.Json
38
38
  });
39
+ const PrepareMutation = Schema.Struct({
40
+ type: Schema.Literal("PrepareMutation"),
41
+ id: InvocationId,
42
+ kind: Schema.Literal("Mutation"),
43
+ function: FunctionAddress,
44
+ args: Schema.Json,
45
+ files: Schema.Array(RuntimeFileOccurrence)
46
+ });
39
47
  const ClientMessage = Schema.Union([
40
48
  Subscribe,
41
49
  Unsubscribe,
50
+ PrepareMutation,
42
51
  Invoke
43
52
  ]);
44
53
  const SubscriptionOperation = Schema.Struct({
@@ -73,7 +82,21 @@ const Snapshot = Schema.Struct({
73
82
  type: Schema.Literal("Snapshot"),
74
83
  id: SubscriptionId,
75
84
  result: WireResult,
76
- revision: AppStateRevision
85
+ revision: AppStateRevision,
86
+ files: Schema.optional(Schema.Array(Schema.Struct({
87
+ path: RuntimeFileOccurrence.fields.path,
88
+ file: RuntimeFileMetadata,
89
+ url: Schema.String
90
+ })))
91
+ });
92
+ const MutationPrepared = Schema.Struct({
93
+ type: Schema.Literal("MutationPrepared"),
94
+ id: InvocationId,
95
+ uploads: Schema.Array(Schema.Struct({
96
+ path: RuntimeFileOccurrence.fields.path,
97
+ file: RuntimeFileMetadata,
98
+ url: Schema.optional(Schema.String)
99
+ }))
77
100
  });
78
101
  const SyncResultSuccess = Schema.Struct({
79
102
  type: Schema.Literal("Result"),
@@ -111,6 +134,7 @@ const DeploymentChangedCloseCode = 4409;
111
134
  const ServerMessage = Schema.Union([
112
135
  SyncHandshake,
113
136
  Snapshot,
137
+ MutationPrepared,
114
138
  SyncResultSuccess,
115
139
  SyncResultFailure,
116
140
  ProtocolError,
@@ -147,4 +171,4 @@ function createApi() {
147
171
  //#endregion
148
172
  export { FunctionAddress as a, ServerMessageJson as c, WireSuccess as d, AppStateRevision as f, DeploymentChangedCloseCode as i, WireFailure as l, InvocationKey as m, functionPathOf as n, Operation as o, DeploymentGeneration as p, ClientMessageJson as r, ProtocolErrorCode as s, createApi as t, WireResult as u };
149
173
 
150
- //# sourceMappingURL=api-DtX8qPrq.js.map
174
+ //# sourceMappingURL=api-BTeMI5tx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-BTeMI5tx.js","names":[],"sources":["../../../contracts/dist/runtime/identity.js","../../../contracts/dist/runtime/sync.js","../../src/internal/api.ts"],"sourcesContent":["import { AppId, ConnectionId, DeploymentId, DevDatabaseLockId, InvocationId, PlatformPrincipalId, RequestId, RuntimeRequestNonce, SubscriptionId, TableId, TeamId } from \"./id.js\";\nimport { Schema } from \"effect\";\n//#region src/runtime/identity.ts\nconst InvocationKey = Schema.String.pipe(Schema.brand(\"ignotum/hosted/InvocationKey\"));\nconst DeploymentGeneration = Schema.Natural.pipe(Schema.brand(\"ignotum/hosted/DeploymentGeneration\"));\nconst AppStateRevision = Schema.Natural.pipe(Schema.brand(\"ignotum/hosted/AppStateRevision\"));\n//#endregion\nexport { AppId, AppStateRevision, ConnectionId, DeploymentGeneration, DeploymentId, DevDatabaseLockId, InvocationId, InvocationKey, PlatformPrincipalId, RequestId, RuntimeRequestNonce, SubscriptionId, TableId, TeamId };\n\n//# sourceMappingURL=identity.js.map","import { AppId, DeploymentId, InvocationId, SubscriptionId } from \"./id.js\";\nimport { AppStateRevision, DeploymentGeneration } from \"./identity.js\";\nimport { RuntimeFileMetadata, RuntimeFileOccurrence } from \"../schema/file.js\";\nimport { TransportValueSchema, datePathsOf, datePathsOfObject, decodeTransportObject, decodeTransportValue, encodeTransportObject, encodeTransportValue } from \"./value.js\";\nimport { Schema } from \"effect\";\n//#region src/runtime/sync.ts\nconst FunctionNamePart = Schema.String.check(Schema.isPattern(/^[A-Za-z_$][A-Za-z0-9_$]*$/));\nconst ApiFunctionAddressParts = Schema.TemplateLiteralParser([\n\t\"api.\",\n\tFunctionNamePart,\n\t\".\",\n\tFunctionNamePart\n]);\nconst FunctionAddress = Schema.TemplateLiteral([\n\t\"api.\",\n\tFunctionNamePart,\n\t\".\",\n\tFunctionNamePart\n]);\nconst apiFunctionParts = (address) => {\n\tconst [, moduleName, , functionName] = Schema.decodeSync(ApiFunctionAddressParts)(address);\n\treturn {\n\t\tfunctionName,\n\t\tmoduleName\n\t};\n};\nconst Subscribe = Schema.Struct({\n\ttype: Schema.Literal(\"Subscribe\"),\n\tid: SubscriptionId,\n\tfunction: FunctionAddress,\n\targs: Schema.Json\n});\nconst Unsubscribe = Schema.Struct({\n\ttype: Schema.Literal(\"Unsubscribe\"),\n\tid: SubscriptionId\n});\nconst Invoke = Schema.Struct({\n\ttype: Schema.Literal(\"Invoke\"),\n\tid: InvocationId,\n\tkind: Schema.Literal(\"Mutation\"),\n\tfunction: FunctionAddress,\n\targs: Schema.Json\n});\nconst PrepareMutation = Schema.Struct({\n\ttype: Schema.Literal(\"PrepareMutation\"),\n\tid: InvocationId,\n\tkind: Schema.Literal(\"Mutation\"),\n\tfunction: FunctionAddress,\n\targs: Schema.Json,\n\tfiles: Schema.Array(RuntimeFileOccurrence)\n});\nconst ClientMessage = Schema.Union([\n\tSubscribe,\n\tUnsubscribe,\n\tPrepareMutation,\n\tInvoke\n]);\nconst SubscriptionOperation = Schema.Struct({\n\ttype: Schema.Literal(\"Subscription\"),\n\tid: SubscriptionId\n});\nconst InvocationOperation = Schema.Struct({\n\ttype: Schema.Literal(\"Invocation\"),\n\tid: InvocationId\n});\nconst Operation = Schema.Union([SubscriptionOperation, InvocationOperation]);\nconst DatePath = Schema.Array(Schema.Union([Schema.String, Schema.Natural]));\nconst DatePaths = Schema.Array(DatePath);\nconst WireSuccess = Schema.Struct({\n\ttype: Schema.Literal(\"Success\"),\n\tvalue: Schema.optional(Schema.Json),\n\tdates: Schema.optional(DatePaths)\n});\nconst WireFailure = Schema.Struct({\n\ttype: Schema.Literal(\"Failure\"),\n\terror: Schema.Json,\n\tdates: Schema.optional(DatePaths)\n});\nconst WireResult = Schema.Union([WireSuccess, WireFailure]);\nconst SyncHandshake = Schema.Struct({\n\ttype: Schema.Literal(\"Handshake\"),\n\tappId: AppId,\n\tdeploymentId: DeploymentId,\n\tgeneration: DeploymentGeneration\n});\nconst Snapshot = Schema.Struct({\n\ttype: Schema.Literal(\"Snapshot\"),\n\tid: SubscriptionId,\n\tresult: WireResult,\n\trevision: AppStateRevision,\n\tfiles: Schema.optional(Schema.Array(Schema.Struct({\n\t\tpath: RuntimeFileOccurrence.fields.path,\n\t\tfile: RuntimeFileMetadata,\n\t\turl: Schema.String\n\t})))\n});\nconst MutationPrepared = Schema.Struct({\n\ttype: Schema.Literal(\"MutationPrepared\"),\n\tid: InvocationId,\n\tuploads: Schema.Array(Schema.Struct({\n\t\tpath: RuntimeFileOccurrence.fields.path,\n\t\tfile: RuntimeFileMetadata,\n\t\turl: Schema.optional(Schema.String)\n\t}))\n});\nconst SyncResultSuccess = Schema.Struct({\n\ttype: Schema.Literal(\"Result\"),\n\tid: InvocationId,\n\tresult: WireSuccess,\n\tcommittedRevision: AppStateRevision\n});\nconst SyncResultFailure = Schema.Struct({\n\ttype: Schema.Literal(\"Result\"),\n\tid: InvocationId,\n\tresult: WireFailure\n});\nconst ProtocolErrorCode = Schema.Literals([\n\t\"DuplicateOperationId\",\n\t\"FunctionUnavailable\",\n\t\"InvalidArguments\",\n\t\"InvalidMessage\",\n\t\"InvocationIdConflict\",\n\t\"ResourceLimitExceeded\",\n\t\"UnknownFunction\",\n\t\"WrongFunctionKind\"\n]);\nconst ProtocolError = Schema.Struct({\n\ttype: Schema.Literal(\"ProtocolError\"),\n\toperation: Schema.optional(Operation),\n\tcode: ProtocolErrorCode,\n\tmessage: Schema.String\n});\nconst DeploymentChanged = Schema.Struct({\n\ttype: Schema.Literal(\"DeploymentChanged\"),\n\tdeploymentId: DeploymentId,\n\tgeneration: DeploymentGeneration\n});\nconst DeploymentChangedCloseCode = 4409;\nconst ServerMessage = Schema.Union([\n\tSyncHandshake,\n\tSnapshot,\n\tMutationPrepared,\n\tSyncResultSuccess,\n\tSyncResultFailure,\n\tProtocolError,\n\tDeploymentChanged\n]);\nconst ClientMessageJson = Schema.fromJsonString(ClientMessage);\nconst ServerMessageJson = Schema.fromJsonString(ServerMessage);\n//#endregion\nexport { ClientMessage, ClientMessageJson, DatePath, DeploymentChanged, DeploymentChangedCloseCode, FunctionAddress, FunctionNamePart, InvocationId, Operation, ProtocolErrorCode, ServerMessage, ServerMessageJson, SubscriptionId, SyncHandshake, TransportValueSchema, WireFailure, WireResult, WireSuccess, apiFunctionParts, datePathsOf, datePathsOfObject, decodeTransportObject, decodeTransportValue, encodeTransportObject, encodeTransportValue };\n\n//# sourceMappingURL=sync.js.map","import { Predicate } from \"effect\";\nimport type { Effect } from \"effect\";\n\nimport type { ErrorValue, InternalServerError } from \"@ignotum/contracts/runtime/result\";\nimport { FunctionAddress } from \"@ignotum/contracts/runtime/sync\";\nimport type { FileValue } from \"@ignotum/contracts/schema/file\";\n\nconst FunctionReferenceTypeId: unique symbol = Symbol.for(\"ignotum/internal/api/FunctionReference\");\ndeclare const FunctionReferenceTypesTypeId: unique symbol;\n\ntype FunctionKind = \"Mutation\" | \"Query\";\n\nexport type MutationInput<Value> = Value extends FileValue\n ? Value | File\n : Value extends Date\n ? Value\n : Value extends ReadonlyArray<infer Item>\n ? ReadonlyArray<MutationInput<Item>>\n : Value extends object\n ? { readonly [Key in keyof Value]: MutationInput<Value[Key]> }\n : Value;\n\nexport interface FunctionReference<\n Kind extends FunctionKind,\n Args,\n Success,\n Failure extends ErrorValue,\n> {\n readonly [FunctionReferenceTypeId]: FunctionAddress;\n readonly [FunctionReferenceTypesTypeId]?: {\n readonly kind: Kind;\n readonly args: Args;\n readonly value: Success;\n readonly error: Failure;\n };\n}\n\ntype ReferenceTypes<Reference> = Reference extends {\n readonly [FunctionReferenceTypesTypeId]?: infer Types;\n}\n ? Exclude<Types, undefined>\n : never;\n\nexport declare namespace FunctionReference {\n type Args<Reference> =\n ReferenceTypes<Reference> extends { readonly args: infer Args } ? Args : never;\n type Failure<Reference> =\n ReferenceTypes<Reference> extends {\n readonly error: infer Failure;\n }\n ? Failure\n : never;\n type Kind<Reference> =\n ReferenceTypes<Reference> extends { readonly kind: infer Kind } ? Kind : never;\n type Success<Reference> =\n ReferenceTypes<Reference> extends {\n readonly value: infer Success;\n }\n ? Success\n : never;\n}\n\ntype ReferenceOf<Definition> = Definition extends {\n readonly _tag: infer Kind extends FunctionKind;\n readonly handler: (\n ...arguments_: infer HandlerArguments\n ) => Generator<infer Yielded, infer Success, never>;\n}\n ? HandlerArguments extends readonly [infer _Context, ...infer Rest]\n ? FunctionReference<\n Kind,\n Rest extends readonly [infer Args, ...ReadonlyArray<unknown>]\n ? Kind extends \"Mutation\"\n ? MutationInput<Args>\n : Args\n : void,\n Success,\n | (Yielded extends Effect.Effect<unknown, infer Failure extends ErrorValue, never>\n ? Failure\n : never)\n | InternalServerError\n >\n : never\n : never;\n\ntype ApiModule<Module> = {\n readonly [FunctionName in keyof Module as FunctionName extends string\n ? ReferenceOf<Module[FunctionName]> extends never\n ? never\n : FunctionName\n : never]: ReferenceOf<Module[FunctionName]>;\n};\n\nexport type Api<Modules> = {\n readonly [ModuleName in keyof Modules]: ApiModule<Modules[ModuleName]>;\n};\n\nexport const functionPathOf = <\n Kind extends FunctionKind,\n Args,\n Success,\n Failure extends ErrorValue,\n>(\n reference: FunctionReference<Kind, Args, Success, Failure>,\n) => reference[FunctionReferenceTypeId];\n\nconst makeModuleReference = (moduleName: string) => {\n const references = new Map<string, object>();\n\n return new Proxy(\n {},\n {\n get: (_target, functionName) => {\n if (!Predicate.isString(functionName)) {\n return undefined;\n }\n\n const existing = references.get(functionName);\n if (existing !== undefined) {\n return existing;\n }\n\n const reference = {\n [FunctionReferenceTypeId]: FunctionAddress.make(`api.${moduleName}.${functionName}`),\n };\n references.set(functionName, reference);\n return reference;\n },\n },\n );\n};\n\nexport function createApi<Modules>(): Api<Modules>;\nexport function createApi() {\n const modules = new Map<string, object>();\n\n return new Proxy(\n {},\n {\n get: (_target, moduleName) => {\n if (!Predicate.isString(moduleName)) {\n return undefined;\n }\n\n const existing = modules.get(moduleName);\n if (existing !== undefined) {\n return existing;\n }\n\n const moduleReference = makeModuleReference(moduleName);\n modules.set(moduleName, moduleReference);\n return moduleReference;\n },\n },\n );\n}\n"],"mappings":"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"}
@@ -1,13 +1,11 @@
1
- import { a as InternalServerError, i as ErrorValue } from "./id-Btwac71X-DhnKYsjY.js";
2
- import { Effect, Schema } from "effect";
3
- //#region ../contracts/dist/runtime/sync.d.ts
4
- declare const FunctionAddress: Schema.TemplateLiteral<readonly ["api.", Schema.String, ".", Schema.String]>;
5
- type FunctionAddress = typeof FunctionAddress.Type;
6
- //#endregion
1
+ import { a as InternalServerError, g as FileValue, i as ErrorValue } from "./id-Btwac71X-DGj0DQuu.js";
2
+ import { t as FunctionAddress } from "./sync-mIXn9eKv.js";
3
+ import { Effect } from "effect";
7
4
  //#region src/internal/api.d.ts
8
5
  declare const FunctionReferenceTypeId: unique symbol;
9
6
  declare const FunctionReferenceTypesTypeId: unique symbol;
10
7
  type FunctionKind = "Mutation" | "Query";
8
+ type MutationInput<Value> = Value extends FileValue ? Value | File : Value extends Date ? Value : Value extends ReadonlyArray<infer Item> ? ReadonlyArray<MutationInput<Item>> : Value extends object ? { readonly [Key in keyof Value]: MutationInput<Value[Key]>; } : Value;
11
9
  interface FunctionReference<Kind extends FunctionKind, Args, Success, Failure extends ErrorValue> {
12
10
  readonly [FunctionReferenceTypeId]: FunctionAddress;
13
11
  readonly [FunctionReferenceTypesTypeId]?: {
@@ -37,11 +35,11 @@ declare namespace FunctionReference {
37
35
  type ReferenceOf<Definition> = Definition extends {
38
36
  readonly _tag: infer Kind extends FunctionKind;
39
37
  readonly handler: (...arguments_: infer HandlerArguments) => Generator<infer Yielded, infer Success, never>;
40
- } ? HandlerArguments extends readonly [infer _Context, ...infer Rest] ? FunctionReference<Kind, Rest extends readonly [infer Args, ...ReadonlyArray<unknown>] ? Args : void, Success, (Yielded extends Effect.Effect<unknown, infer Failure extends ErrorValue, never> ? Failure : never) | InternalServerError> : never : never;
38
+ } ? HandlerArguments extends readonly [infer _Context, ...infer Rest] ? FunctionReference<Kind, Rest extends readonly [infer Args, ...ReadonlyArray<unknown>] ? Kind extends "Mutation" ? MutationInput<Args> : Args : void, Success, (Yielded extends Effect.Effect<unknown, infer Failure extends ErrorValue, never> ? Failure : never) | InternalServerError> : never : never;
41
39
  type ApiModule<Module> = { readonly [FunctionName in keyof Module as FunctionName extends string ? ReferenceOf<Module[FunctionName]> extends never ? never : FunctionName : never]: ReferenceOf<Module[FunctionName]>; };
42
40
  type Api<Modules> = { readonly [ModuleName in keyof Modules]: ApiModule<Modules[ModuleName]>; };
43
41
  declare const functionPathOf: <Kind extends FunctionKind, Args, Success, Failure extends ErrorValue>(reference: FunctionReference<Kind, Args, Success, Failure>) => `api.${string}.${string}`;
44
42
  declare function createApi<Modules>(): Api<Modules>;
45
43
  //#endregion
46
- export { functionPathOf as i, FunctionReference as n, createApi as r, Api as t };
47
- //# sourceMappingURL=api-Dp4J-xt-.d.ts.map
44
+ export { functionPathOf as a, createApi as i, FunctionReference as n, MutationInput as r, Api as t };
45
+ //# sourceMappingURL=api-D9lV-5av.d.ts.map
@@ -1,9 +1,16 @@
1
- import { a as InternalServerError, i as ErrorValue, l as SettledResult, o as Match, s as QueryResult$1 } from "./id-Btwac71X-DhnKYsjY.js";
2
- import { n as FunctionReference } from "./api-Dp4J-xt-.js";
3
- import { n as PaginationPage, t as PaginationOptions } from "./pagination-B1BzNkh8-BUSTbeSg.js";
4
- import "./pagination-BKPko9Hm.js";
1
+ import { a as InternalServerError, g as FileValue, h as FileMimeType, i as ErrorValue, l as SettledResult, m as FileMetadata, o as Match, p as FileFormat, s as QueryResult$1 } from "./id-Btwac71X-DGj0DQuu.js";
2
+ import "./sync-mIXn9eKv.js";
3
+ import { n as FunctionReference } from "./api-D9lV-5av.js";
4
+ import { n as PaginationPage, t as PaginationOptions } from "./pagination-DrOowBve-Bnipd34u.js";
5
+ import "./pagination-BNFhAjns.js";
6
+ import { Context as Context$1, Effect, Layer } from "effect";
5
7
  import { Dispatch, Reducer, StateUpdater, useCallback, useContext, useDebugValue, useEffect, useErrorBoundary, useId, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState } from "preact/hooks";
6
8
  import { AnyComponent, Attributes, ClassAttributes, Component, ComponentChild, ComponentChildren, ComponentClass, ComponentConstructor, ComponentFactory, ComponentProps, ComponentType, ComponentType as ComponentType$1, Consumer, Context, ContextType, ErrorInfo, Fragment, FunctionComponent, FunctionalComponent, JSX, Key, PreactConsumer, PreactContext, PreactDOMAttributes, PreactProvider, Provider, Ref, RefCallback, RefObject, RenderableProps, TargetedAnimationEvent, TargetedClipboardEvent, TargetedCommandEvent, TargetedCompositionEvent, TargetedDragEvent, TargetedEvent, TargetedFocusEvent, TargetedInputEvent, TargetedKeyboardEvent, TargetedMouseEvent, TargetedPictureInPictureEvent, TargetedPointerEvent, TargetedSnapEvent, TargetedSubmitEvent, TargetedToggleEvent, TargetedTouchEvent, TargetedTransitionEvent, TargetedUIEvent, TargetedWheelEvent, VNode, cloneElement, createContext, createElement, createRef, h, isValidElement, toChildArray } from "preact";
9
+ //#region src/client/files.d.ts
10
+ declare const Files: {
11
+ readonly url: (file: FileValue) => string;
12
+ };
13
+ //#endregion
7
14
  //#region src/client/query.d.ts
8
15
  declare const QuerySkipTypeId: unique symbol;
9
16
  interface QuerySkip {
@@ -49,5 +56,5 @@ declare const Result: {
49
56
  type Result<Value, Error extends ErrorValue> = SettledResult<Value, Error>;
50
57
  type QueryResult<Value, Error extends ErrorValue> = QueryResult$1<Value, Error>;
51
58
  //#endregion
52
- export { type AnyComponent, type AppDefinition, type Attributes, type ClassAttributes, Component, type ComponentChild, type ComponentChildren, type ComponentClass, type ComponentConstructor, type ComponentFactory, type ComponentProps, type ComponentType, type Consumer, type Context, type ContextType, type Dispatch, type ErrorInfo, Fragment, type FunctionComponent, type FunctionalComponent, type InternalServerError, type JSX, type Key, type PaginatedQueryOptions, type PaginatedQueryValue, type PaginationStatus, type PreactConsumer, type PreactContext, type PreactDOMAttributes, type PreactProvider, type Provider, Query, QueryResult, type QuerySkip, type Reducer, type Ref, type RefCallback, type RefObject, type RenderableProps, Result, type StateUpdater, type TargetedAnimationEvent, type TargetedClipboardEvent, type TargetedCommandEvent, type TargetedCompositionEvent, type TargetedDragEvent, type TargetedEvent, type TargetedFocusEvent, type TargetedInputEvent, type TargetedKeyboardEvent, type TargetedMouseEvent, type TargetedPictureInPictureEvent, type TargetedPointerEvent, type TargetedSnapEvent, type TargetedSubmitEvent, type TargetedToggleEvent, type TargetedTouchEvent, type TargetedTransitionEvent, type TargetedUIEvent, type TargetedWheelEvent, type VNode, app, cloneElement, createContext, createElement, createRef, h, isValidElement, toChildArray, useCallback, useContext, useDebugValue, useEffect, useErrorBoundary, useId, useImperativeHandle, useLayoutEffect, useMemo, useMutation, usePaginatedQuery, useQuery, useReducer, useRef, useState };
59
+ export { type AnyComponent, type AppDefinition, type Attributes, type ClassAttributes, Component, type ComponentChild, type ComponentChildren, type ComponentClass, type ComponentConstructor, type ComponentFactory, type ComponentProps, type ComponentType, type Consumer, type Context, type ContextType, type Dispatch, type ErrorInfo, type FileFormat, type FileMetadata, type FileMimeType, type FileValue, Files, Fragment, type FunctionComponent, type FunctionalComponent, type InternalServerError, type JSX, type Key, type PaginatedQueryOptions, type PaginatedQueryValue, type PaginationStatus, type PreactConsumer, type PreactContext, type PreactDOMAttributes, type PreactProvider, type Provider, Query, QueryResult, type QuerySkip, type Reducer, type Ref, type RefCallback, type RefObject, type RenderableProps, Result, type StateUpdater, type TargetedAnimationEvent, type TargetedClipboardEvent, type TargetedCommandEvent, type TargetedCompositionEvent, type TargetedDragEvent, type TargetedEvent, type TargetedFocusEvent, type TargetedInputEvent, type TargetedKeyboardEvent, type TargetedMouseEvent, type TargetedPictureInPictureEvent, type TargetedPointerEvent, type TargetedSnapEvent, type TargetedSubmitEvent, type TargetedToggleEvent, type TargetedTouchEvent, type TargetedTransitionEvent, type TargetedUIEvent, type TargetedWheelEvent, type VNode, app, cloneElement, createContext, createElement, createRef, h, isValidElement, toChildArray, useCallback, useContext, useDebugValue, useEffect, useErrorBoundary, useId, useImperativeHandle, useLayoutEffect, useMemo, useMutation, usePaginatedQuery, useQuery, useReducer, useRef, useState };
53
60
  //# sourceMappingURL=client.d.ts.map
@@ -1,12 +1,116 @@
1
- import { a as InvocationId, c as SubscriptionId, i as IdAlphabet, l as TableId, n as DeploymentId, r as GeneratedId, s as RuntimeRequestNonce, t as AppId } from "./id-D570vudg.js";
2
- import { d as failureFromWire, f as inspectResult, l as Result$1, o as PaginationPageSize, p as pending, t as ValueDescriptor, v as decodeTransportValue, y as encodeTransportObject } from "./descriptor-t6BOEGw9-C1rwYIlx.js";
3
- import { a as FunctionAddress, c as ServerMessageJson, d as WireSuccess, f as AppStateRevision, i as DeploymentChangedCloseCode, l as WireFailure, m as InvocationKey, n as functionPathOf, o as Operation, p as DeploymentGeneration, r as ClientMessageJson, s as ProtocolErrorCode, u as WireResult } from "./api-DtX8qPrq.js";
1
+ import { C as RuntimeRequestNonce, T as TableId, _ as AppId, a as RuntimeFileMetadata, b as IdAlphabet, c as fileFormats, d as fileLimits, f as fileMimeTypes, h as makeFileValue, l as fileGrantUrlOf, m as isFileValue, o as RuntimeFileOccurrence, p as grantFileValue, r as FileId, u as fileIdOf, v as DeploymentId, w as SubscriptionId, x as InvocationId, y as GeneratedId } from "./file-BXf63ulU.js";
2
+ import { b as decodeTransportValue, c as upgrade, d as Result$1, h as pending, m as inspectResult, o as PaginationPageSize, p as failureFromWire, s as initial, t as ValueDescriptor, x as encodeTransportObject } from "./descriptor-C5VA9qRl-C338iC6l.js";
3
+ import { a as FunctionAddress, c as ServerMessageJson, d as WireSuccess, f as AppStateRevision, i as DeploymentChangedCloseCode, l as WireFailure, m as InvocationKey, n as functionPathOf, o as Operation, p as DeploymentGeneration, r as ClientMessageJson, s as ProtocolErrorCode, u as WireResult } from "./api-BTeMI5tx.js";
4
4
  import { Array as Array$1, Cause, Context, Deferred, Duration, Effect, ErrorReporter, Fiber, HashMap, Layer, ManagedRuntime, Predicate, Schedule, Schema, String } from "effect";
5
+ import { customAlphabet } from "nanoid";
5
6
  import { useCallback, useCallback as useCallback$1, useContext, useDebugValue, useDebugValue as useDebugValue$1, useEffect, useEffect as useEffect$1, useErrorBoundary, useId, useImperativeHandle, useLayoutEffect, useMemo, useMemo as useMemo$1, useReducer, useRef, useState, useState as useState$1 } from "preact/hooks";
6
7
  import * as Socket from "effect/unstable/socket/Socket";
7
8
  import * as BrowserCrypto from "@effect/platform-browser/BrowserCrypto";
8
- import { customAlphabet } from "nanoid";
9
9
  import { Component, Fragment, cloneElement, createContext, createElement, createRef, h, isValidElement, toChildArray } from "preact";
10
+ //#region ../shared/dist/id.js
11
+ const decodeGenerated = (definition, payload) => Schema.decodeSync(definition)(definition.idPrefix === void 0 ? payload : `${definition.idPrefix}_${payload}`);
12
+ var IdGenerator = class IdGenerator extends Context.Service()("@ignotum/shared/id/IdGenerator") {
13
+ static layer = Layer.sync(IdGenerator, () => {
14
+ const generatePayload = customAlphabet(IdAlphabet, 24);
15
+ return IdGenerator.of({ generate: (definition) => Effect.sync(() => decodeGenerated(definition, generatePayload())) });
16
+ });
17
+ static deterministic = (startAt = 1) => Layer.sync(IdGenerator, () => {
18
+ const counters = /* @__PURE__ */ new Map();
19
+ return IdGenerator.of({ generate: (definition) => Effect.sync(() => {
20
+ const counter = (counters.get(definition.idPrefix) ?? startAt - 1) + 1;
21
+ counters.set(definition.idPrefix, counter);
22
+ return decodeGenerated(definition, counter.toString(36).padStart(24, "0"));
23
+ }) });
24
+ });
25
+ };
26
+ //#endregion
27
+ //#region src/client/files.ts
28
+ const Files = { url: (file) => {
29
+ const url = fileGrantUrlOf(file);
30
+ if (url === void 0) throw new Error("This FileValue has no active query grant.");
31
+ return url;
32
+ } };
33
+ const formatByMime = {};
34
+ for (const format of fileFormats) formatByMime[fileMimeTypes[format]] = format;
35
+ const collectNativeFiles = (value, path, occurrences) => {
36
+ if (value instanceof File) {
37
+ occurrences.push({
38
+ path,
39
+ value
40
+ });
41
+ return;
42
+ }
43
+ if (isFileValue(value) || Predicate.isDate(value)) return;
44
+ if (globalThis.Array.isArray(value)) {
45
+ for (const [index, child] of value.entries()) collectNativeFiles(child, [...path, index], occurrences);
46
+ return;
47
+ }
48
+ if (!Predicate.isObject(value)) return;
49
+ for (const [key, child] of Object.entries(value)) collectNativeFiles(child, [...path, key], occurrences);
50
+ };
51
+ const replaceNativeFiles = (value, replacements) => {
52
+ if (value instanceof File) return replacements.get(value);
53
+ if (isFileValue(value) || Predicate.isDate(value)) return value;
54
+ if (globalThis.Array.isArray(value)) return value.map((child) => replaceNativeFiles(child, replacements));
55
+ if (!Predicate.isObject(value)) return value;
56
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, replaceNativeFiles(child, replacements)]));
57
+ };
58
+ const prepareMutationArguments = Effect.fn("SyncClient.prepareMutationArguments")(function* (input) {
59
+ const ids = yield* IdGenerator;
60
+ const native = [];
61
+ collectNativeFiles(input, [], native);
62
+ const unique = new Set(native.map(({ value }) => value));
63
+ if (unique.size > fileLimits.filesPerMutation) throw new Error(`A mutation may upload at most ${fileLimits.filesPerMutation} files.`);
64
+ if ([...unique].reduce((total, file) => total + file.size, 0) > fileLimits.mutationBytes) throw new Error(`Mutation uploads may total at most ${fileLimits.mutationBytes} bytes.`);
65
+ const replacements = /* @__PURE__ */ new Map();
66
+ const nativeFiles = /* @__PURE__ */ new Map();
67
+ for (const file of unique) {
68
+ const format = formatByMime[file.type.toLowerCase()];
69
+ if (format === void 0) throw new Error(`File '${file.name}' has unsupported media type '${file.type || "unknown"}'.`);
70
+ if (file.size === 0 || file.size > fileLimits.fileBytes) throw new Error(`File '${file.name}' must be between 1 and ${fileLimits.fileBytes} bytes.`);
71
+ if (new TextEncoder().encode(file.name).byteLength > fileLimits.filenameBytes) throw new Error(`File '${file.name}' has a filename that is too long.`);
72
+ const id = yield* ids.generate(FileId);
73
+ replacements.set(file, makeFileValue(id, {
74
+ format,
75
+ name: file.name,
76
+ size: file.size
77
+ }));
78
+ nativeFiles.set(id, file);
79
+ }
80
+ return {
81
+ value: replaceNativeFiles(input, replacements),
82
+ nativeFiles,
83
+ occurrences: native.map(({ path, value: file }) => {
84
+ const replacement = replacements.get(file);
85
+ if (replacement === void 0) throw new Error("A native file replacement is missing.");
86
+ return {
87
+ path,
88
+ file: {
89
+ id: fileIdOf(replacement),
90
+ format: replacement.format,
91
+ name: replacement.name,
92
+ size: replacement.size
93
+ }
94
+ };
95
+ })
96
+ };
97
+ });
98
+ const pathKey = (path) => JSON.stringify(path);
99
+ const applyFileGrants = (value, grants) => {
100
+ const byPath = new Map(grants.map((grant) => [pathKey(grant.path), grant]));
101
+ const visit = (current, path) => {
102
+ const grant = byPath.get(pathKey(path));
103
+ if (grant !== void 0) {
104
+ if (!isFileValue(current) || fileIdOf(current) !== grant.file.id) throw new Error("A query file grant does not match its result value.");
105
+ return grantFileValue(current, grant.url);
106
+ }
107
+ if (globalThis.Array.isArray(current)) return current.map((child, index) => visit(child, [...path, index]));
108
+ if (!Predicate.isObject(current) || Predicate.isDate(current) || isFileValue(current)) return current;
109
+ return Object.fromEntries(Object.entries(current).map(([key, child]) => [key, visit(child, [...path, key])]));
110
+ };
111
+ return visit(value, []);
112
+ };
113
+ //#endregion
10
114
  //#region ../contracts/dist/json.js
11
115
  const encodeScalar = (value) => Schema.decodeSync(Schema.String)(JSON.stringify(value));
12
116
  const encodeCanonicalJson = (value) => {
@@ -114,13 +218,41 @@ const RuntimeQueryResult = Schema.Struct({
114
218
  type: Schema.Literal("Query"),
115
219
  result: WireResult,
116
220
  dependencies: DependencySet,
117
- observedRevision: AppStateRevision
221
+ observedRevision: AppStateRevision,
222
+ files: Schema.optional(Schema.Array(RuntimeFileOccurrence))
223
+ });
224
+ const FileReferenceAdded = Schema.Struct({
225
+ type: Schema.Literal("AddReference"),
226
+ file: RuntimeFileMetadata,
227
+ tableId: TableId,
228
+ documentId: GeneratedId
229
+ });
230
+ const FileReferenceRemoved = Schema.Struct({
231
+ type: Schema.Literal("RemoveReference"),
232
+ fileId: FileId,
233
+ tableId: TableId,
234
+ documentId: GeneratedId
235
+ });
236
+ const FileReferenceEffect = Schema.Union([FileReferenceAdded, FileReferenceRemoved]);
237
+ const FileEffectBatch = Schema.Struct({
238
+ id: InvocationId,
239
+ committedRevision: AppStateRevision,
240
+ effects: Schema.Array(FileReferenceEffect)
118
241
  });
242
+ Schema.Struct({ appId: AppId });
243
+ Schema.Struct({ batches: Schema.Array(FileEffectBatch) });
244
+ Schema.Struct({
245
+ appId: AppId,
246
+ invocationId: InvocationId,
247
+ acknowledgedAt: Schema.Int
248
+ });
249
+ Schema.Struct({ completed: Schema.Literal(true) });
119
250
  const RuntimeMutationSuccess = Schema.Struct({
120
251
  type: Schema.Literal("Mutation"),
121
252
  result: WireSuccess,
122
253
  invalidations: InvalidationSet,
123
- committedRevision: AppStateRevision
254
+ committedRevision: AppStateRevision,
255
+ fileEffects: Schema.optional(FileEffectBatch)
124
256
  });
125
257
  const RuntimeMutationFailure = Schema.Struct({
126
258
  type: Schema.Literal("Mutation"),
@@ -143,7 +275,8 @@ const QueryInvocation = Schema.Struct({
143
275
  const MutationInvocation = Schema.Struct({
144
276
  ...InvocationBase,
145
277
  type: Schema.Literal("Mutation"),
146
- invocationId: InvocationId
278
+ invocationId: InvocationId,
279
+ files: Schema.optional(Schema.Array(RuntimeFileOccurrence))
147
280
  });
148
281
  Schema.Union([QueryInvocation, MutationInvocation]);
149
282
  Schema.Struct({
@@ -182,23 +315,6 @@ Schema.Union([
182
315
  RuntimeInvocationUnavailable
183
316
  ]);
184
317
  //#endregion
185
- //#region ../shared/dist/id.js
186
- const decodeGenerated = (definition, payload) => Schema.decodeSync(definition)(definition.idPrefix === void 0 ? payload : `${definition.idPrefix}_${payload}`);
187
- var IdGenerator = class IdGenerator extends Context.Service()("@ignotum/shared/id/IdGenerator") {
188
- static layer = Layer.sync(IdGenerator, () => {
189
- const generatePayload = customAlphabet(IdAlphabet, 24);
190
- return IdGenerator.of({ generate: (definition) => Effect.sync(() => decodeGenerated(definition, generatePayload())) });
191
- });
192
- static deterministic = (startAt = 1) => Layer.sync(IdGenerator, () => {
193
- const counters = /* @__PURE__ */ new Map();
194
- return IdGenerator.of({ generate: (definition) => Effect.sync(() => {
195
- const counter = (counters.get(definition.idPrefix) ?? startAt - 1) + 1;
196
- counters.set(definition.idPrefix, counter);
197
- return decodeGenerated(definition, counter.toString(36).padStart(24, "0"));
198
- }) });
199
- });
200
- };
201
- //#endregion
202
318
  //#region ../contracts/dist/runtime/functions.js
203
319
  const FunctionKind = Schema.Literals(["Mutation", "Query"]);
204
320
  Schema.TaggedError()("UnknownFunction", {
@@ -253,24 +369,27 @@ const ClientRoute = Schema.Struct({
253
369
  pathname: ClientPath,
254
370
  artifact: ArtifactReference
255
371
  });
256
- Schema.Struct({
372
+ const DeploymentInventoryV1 = Schema.Struct({
257
373
  formatVersion: Schema.Literal(1),
258
374
  files: Schema.Array(ArtifactFile)
259
375
  });
260
- Schema.Struct({
376
+ initial(DeploymentInventoryV1);
377
+ const ClientManifestV1 = Schema.Struct({
261
378
  formatVersion: Schema.Literal(1),
262
379
  shell: ArtifactReference,
263
380
  routes: Schema.Array(ClientRoute)
264
381
  });
382
+ initial(ClientManifestV1);
265
383
  const ClientRoutingRoute = Schema.Struct({
266
384
  pathname: ClientPath,
267
385
  artifact: ArtifactPath
268
386
  });
269
- Schema.Struct({
387
+ const ClientRoutingV1 = Schema.Struct({
270
388
  formatVersion: Schema.Literal(1),
271
389
  shell: ArtifactPath,
272
390
  routes: Schema.Array(ClientRoutingRoute)
273
391
  });
392
+ initial(ClientRoutingV1);
274
393
  const SchemaSnapshotField = Schema.Struct({
275
394
  name: Schema.String,
276
395
  value: ValueDescriptor
@@ -279,26 +398,60 @@ const SchemaSnapshotIndex = Schema.Struct({
279
398
  name: Schema.String,
280
399
  fields: Schema.Array(Schema.String)
281
400
  });
401
+ const SchemaSnapshotTableV1 = Schema.Struct({
402
+ name: Schema.String,
403
+ fields: Schema.Array(SchemaSnapshotField)
404
+ });
405
+ const SchemaSnapshotV1 = Schema.Struct({
406
+ formatVersion: Schema.Literal(1),
407
+ tables: Schema.Array(SchemaSnapshotTableV1)
408
+ });
282
409
  const SchemaSnapshotTable = Schema.Struct({
283
410
  name: Schema.String,
284
411
  fields: Schema.Array(SchemaSnapshotField),
285
412
  indexes: Schema.Array(SchemaSnapshotIndex)
286
413
  });
287
- Schema.Struct({
414
+ const SchemaSnapshotV2 = Schema.Struct({
288
415
  formatVersion: Schema.Literal(2),
289
416
  tables: Schema.Array(SchemaSnapshotTable)
290
417
  });
418
+ upgrade(initial(SchemaSnapshotV1), SchemaSnapshotV2, (snapshot) => ({
419
+ formatVersion: 2,
420
+ tables: snapshot.tables.map((table) => ({
421
+ ...table,
422
+ indexes: []
423
+ }))
424
+ }));
425
+ const ServerFunctionArtifactV1 = Schema.Struct({
426
+ address: FunctionAddress,
427
+ kind: FunctionKind,
428
+ bundle: ArtifactReference,
429
+ sourceMap: ArtifactReference
430
+ });
291
431
  const ServerFunctionArtifact = Schema.Struct({
292
432
  address: FunctionAddress,
293
433
  kind: FunctionKind,
434
+ args: Schema.optional(ValueDescriptor),
435
+ returns: Schema.optional(ValueDescriptor),
436
+ errors: Schema.optional(ValueDescriptor),
294
437
  bundle: ArtifactReference,
295
438
  sourceMap: ArtifactReference
296
439
  });
297
- Schema.Struct({
440
+ const ServerBuildManifestV1 = Schema.Struct({
298
441
  formatVersion: Schema.Literal(1),
299
442
  schema: ArtifactReference,
443
+ functions: Schema.Array(ServerFunctionArtifactV1)
444
+ });
445
+ const ServerBuildManifestV2 = Schema.Struct({
446
+ formatVersion: Schema.Literal(2),
447
+ schema: ArtifactReference,
300
448
  functions: Schema.Array(ServerFunctionArtifact)
301
449
  });
450
+ upgrade(initial(ServerBuildManifestV1), ServerBuildManifestV2, (manifest) => ({
451
+ formatVersion: 2,
452
+ schema: manifest.schema,
453
+ functions: manifest.functions
454
+ }));
302
455
  ArtifactPath.make("inventory.json");
303
456
  ArtifactPath.make("client/manifest.json");
304
457
  ArtifactPath.make("client/shell.html");
@@ -312,12 +465,16 @@ const runtimeInvocationPath = "/v1/invoke";
312
465
  const runtimeRevisionPath = "/v1/revision";
313
466
  const runtimeIndexPreparePath = "/v1/indexes/prepare";
314
467
  const runtimeIndexCommitPath = "/v1/indexes/commit";
468
+ const runtimeFileEffectsPath = "/v1/files/effects";
469
+ const runtimeFileEffectsAcknowledgePath = "/v1/files/effects/acknowledge";
315
470
  const appSyncPath = `/_ignotum/v1/sync`;
316
471
  const RuntimeRequestPath = Schema.Literals([
317
472
  runtimeInvocationPath,
318
473
  runtimeRevisionPath,
319
474
  runtimeIndexPreparePath,
320
- runtimeIndexCommitPath
475
+ runtimeIndexCommitPath,
476
+ runtimeFileEffectsPath,
477
+ runtimeFileEffectsAcknowledgePath
321
478
  ]);
322
479
  const RuntimeRequestTimestamp = Schema.FiniteFromString.pipe(Schema.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0)), Schema.brand("ignotum/runtime/RequestTimestamp"));
323
480
  const RuntimeRequestSignature = Sha256.pipe(Schema.brand("ignotum/runtime/RequestSignature"));
@@ -440,7 +597,7 @@ const makeQueryCache = (allocateId, sendLifecycleMessage) => {
440
597
  }
441
598
  };
442
599
  };
443
- const resultFromWire = Effect.fn("SyncClient.resultFromWire")((wire) => Effect.succeed(wire.type === "Success" ? Result$1.succeed(wire.value === void 0 ? void 0 : decodeTransportValue(wire.value, wire.dates ?? [])) : failureFromWire(wire.error, wire.dates)));
600
+ const resultFromWire = Effect.fn("SyncClient.resultFromWire")((wire, files = []) => Effect.succeed(wire.type === "Success" ? Result$1.succeed(wire.value === void 0 ? void 0 : applyFileGrants(decodeTransportValue(wire.value, wire.dates ?? []), files)) : failureFromWire(wire.error, wire.dates)));
444
601
  const shouldReloadForCloseCode = (code) => code === DeploymentChangedCloseCode;
445
602
  const handshakesMatch = (first, next) => first.appId === next.appId && first.deploymentId === next.deploymentId && first.generation === next.generation;
446
603
  const handshakeDecision = (remembered, acceptedOnConnection, next) => {
@@ -484,14 +641,19 @@ var SyncClient = class SyncClient extends Context.Service()("ignotum/client/sync
484
641
  const pendingInvocation = HashMap.getUnsafe(invocations, id);
485
642
  if (pendingInvocation === void 0) return Effect.void;
486
643
  invocations = HashMap.remove(invocations, id);
487
- return reportClientError(error).pipe(Effect.andThen(Deferred.fail(pendingInvocation.deferred, error)), Effect.asVoid);
644
+ return reportClientError(error).pipe(Effect.andThen(Deferred.fail(pendingInvocation.prepared, error)), Effect.andThen(Deferred.fail(pendingInvocation.deferred, error)), Effect.asVoid);
488
645
  };
489
646
  const handleMessage = Effect.fn("SyncClient.handleMessage")(function* (message) {
490
647
  switch (message.type) {
491
648
  case "Snapshot":
492
649
  if (queryCache.getById(message.id) === void 0) return;
493
- yield* resultFromWire(message.result).pipe(Effect.tap((result) => Effect.sync(() => queryCache.setResult(message.id, result, message.revision))));
650
+ yield* resultFromWire(message.result, message.files ?? []).pipe(Effect.tap((result) => Effect.sync(() => queryCache.setResult(message.id, result, message.revision))));
651
+ return;
652
+ case "MutationPrepared": {
653
+ const pendingInvocation = HashMap.getUnsafe(invocations, message.id);
654
+ if (pendingInvocation !== void 0) yield* Deferred.succeed(pendingInvocation.prepared, message.uploads);
494
655
  return;
656
+ }
495
657
  case "Result": {
496
658
  const pendingInvocation = HashMap.getUnsafe(invocations, message.id);
497
659
  if (pendingInvocation === void 0) return;
@@ -581,24 +743,94 @@ var SyncClient = class SyncClient extends Context.Service()("ignotum/client/sync
581
743
  });
582
744
  const mutate = Effect.fn("SyncClient.mutate")(function* (functionAddress, args) {
583
745
  const invocationId = yield* ids.generate(InvocationId);
746
+ const preparedArguments = yield* prepareMutationArguments(args).pipe(Effect.provideService(IdGenerator, ids), Effect.mapError((cause) => InvalidMutationArguments.make({
747
+ cause,
748
+ function: functionAddress,
749
+ message: `Mutation arguments for ${functionAddress} contain an unsupported file or value.`
750
+ })), Effect.tapError(reportClientError));
751
+ const jsonArgs = yield* Effect.try({
752
+ try: () => encodeTransportObject(preparedArguments.value),
753
+ catch: (cause) => InvalidMutationArguments.make({
754
+ cause,
755
+ function: functionAddress,
756
+ message: `Mutation arguments for ${functionAddress} contain an unsupported value.`
757
+ })
758
+ }).pipe(Effect.tapError(reportClientError));
584
759
  const deferred = yield* Deferred.make();
585
- const message = {
760
+ const prepared = yield* Deferred.make();
761
+ const invokeMessage = {
586
762
  type: "Invoke",
587
763
  id: invocationId,
588
764
  kind: "Mutation",
589
765
  function: functionAddress,
590
- args
766
+ args: jsonArgs
767
+ };
768
+ const message = preparedArguments.occurrences.length === 0 ? invokeMessage : {
769
+ type: "PrepareMutation",
770
+ id: invocationId,
771
+ kind: "Mutation",
772
+ function: functionAddress,
773
+ args: jsonArgs,
774
+ files: preparedArguments.occurrences
591
775
  };
592
776
  invocations = HashMap.set(invocations, invocationId, {
593
777
  deferred,
594
778
  function: functionAddress,
595
- message
779
+ message,
780
+ prepared
596
781
  });
597
- if (writer !== void 0) yield* sendWith(writer, message).pipe(Effect.catchTags({
598
- ConnectionUnavailable: reportClientError,
599
- InvalidClientMessage: (error) => rejectInvocation(invocationId, error)
600
- }));
601
- return yield* Deferred.await(deferred);
782
+ return yield* Effect.gen(function* () {
783
+ if (writer !== void 0) yield* sendWith(writer, message).pipe(Effect.catchTags({
784
+ ConnectionUnavailable: reportClientError,
785
+ InvalidClientMessage: (error) => rejectInvocation(invocationId, error)
786
+ }));
787
+ if (message.type === "PrepareMutation") {
788
+ const uploads = yield* Deferred.await(prepared);
789
+ const uploaded = /* @__PURE__ */ new Set();
790
+ for (const upload of uploads) {
791
+ if (upload.url === void 0 || uploaded.has(upload.file.id)) continue;
792
+ const uploadUrl = upload.url;
793
+ uploaded.add(upload.file.id);
794
+ const file = preparedArguments.nativeFiles.get(upload.file.id);
795
+ if (file === void 0) return yield* InvalidServerMessage.make({
796
+ cause: /* @__PURE__ */ new Error(`Missing native file '${upload.file.id}'.`),
797
+ message: "The server prepared an unknown application file."
798
+ });
799
+ const response = yield* Effect.tryPromise({
800
+ try: () => fetch(uploadUrl, {
801
+ method: "PUT",
802
+ body: file,
803
+ headers: { "content-type": file.type }
804
+ }),
805
+ catch: (cause) => ConnectionUnavailable.make({
806
+ cause,
807
+ message: `File '${file.name}' could not be uploaded.`
808
+ })
809
+ });
810
+ if (!response.ok) {
811
+ const detail = yield* Effect.promise(() => response.text());
812
+ return yield* InvalidMutationArguments.make({
813
+ cause: new Error(detail),
814
+ function: functionAddress,
815
+ message: `File '${file.name}' was rejected by application storage.`
816
+ });
817
+ }
818
+ }
819
+ const pendingInvocation = HashMap.getUnsafe(invocations, invocationId);
820
+ if (pendingInvocation === void 0) return yield* Deferred.await(deferred);
821
+ invocations = HashMap.set(invocations, invocationId, {
822
+ ...pendingInvocation,
823
+ message: invokeMessage
824
+ });
825
+ if (writer !== void 0) yield* sendWith(writer, invokeMessage).pipe(Effect.catchTags({
826
+ ConnectionUnavailable: reportClientError,
827
+ InvalidClientMessage: (error) => rejectInvocation(invocationId, error)
828
+ }));
829
+ }
830
+ return yield* Deferred.await(deferred);
831
+ }).pipe(Effect.tapError(() => Effect.sync(() => {
832
+ invocations = HashMap.remove(invocations, invocationId);
833
+ })));
602
834
  });
603
835
  return SyncClient.of({
604
836
  mutate,
@@ -801,16 +1033,7 @@ const useMutation = (reference) => useMemo$1(() => {
801
1033
  const functionPath = functionPathOf(reference);
802
1034
  const input = args === void 0 ? {} : args;
803
1035
  return syncRuntime.runPromise(Effect.gen(function* () {
804
- const client = yield* SyncClient;
805
- const jsonArgs = yield* Effect.try({
806
- try: () => encodeTransportObject(input),
807
- catch: (cause) => InvalidMutationArguments.make({
808
- cause,
809
- function: functionPath,
810
- message: `Mutation arguments for ${functionPath} contain an unsupported value.`
811
- })
812
- }).pipe(Effect.tapError(reportClientError));
813
- return yield* client.mutate(functionPath, jsonArgs);
1036
+ return yield* (yield* SyncClient).mutate(functionPath, input);
814
1037
  }));
815
1038
  };
816
1039
  return mutate;
@@ -825,6 +1048,6 @@ const app = (definition) => {
825
1048
  //#region src/client/index.ts
826
1049
  const Result = { match: Result$1.match };
827
1050
  //#endregion
828
- export { Component, Fragment, Query, Result, app, cloneElement, createContext, createElement, createRef, h, isValidElement, toChildArray, useCallback, useContext, useDebugValue, useEffect, useErrorBoundary, useId, useImperativeHandle, useLayoutEffect, useMemo, useMutation, usePaginatedQuery, useQuery, useReducer, useRef, useState };
1051
+ export { Component, Files, Fragment, Query, Result, app, cloneElement, createContext, createElement, createRef, h, isValidElement, toChildArray, useCallback, useContext, useDebugValue, useEffect, useErrorBoundary, useId, useImperativeHandle, useLayoutEffect, useMemo, useMutation, usePaginatedQuery, useQuery, useReducer, useRef, useState };
829
1052
 
830
1053
  //# sourceMappingURL=client.js.map