@process.co/element-types 0.0.18 → 0.0.19

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/src/index.ts CHANGED
@@ -21,6 +21,7 @@ import type {
21
21
  ISlotStaticInstanceDefinition,
22
22
  ISlotDefinition,
23
23
  } from './slot-definition';
24
+ import { ConfigureResponseCachingOptions } from './http-request-cache';
24
25
 
25
26
  export type { ISlotInstanceDefinition, ISlotStaticInstanceDefinition, ISlotDefinition };
26
27
 
@@ -60,6 +61,19 @@ export {
60
61
  isPlatformBoundLoaderType,
61
62
  } from './platform-loader-type';
62
63
 
64
+ export {
65
+ HTTP_REQUEST_CACHE_POLICY_KEY,
66
+ REPLAY_BINDING_RANGE,
67
+ REPLAY_META_RANGE,
68
+ type BodyVaryProjection,
69
+ type CacheVaryInfoWire,
70
+ type ConfigureResponseCachingOptions,
71
+ type DurationWire,
72
+ type HttpRequestCacheMode,
73
+ type HttpRequestCachePolicy,
74
+ type HttpRequestCacheVary,
75
+ } from './http-request-cache';
76
+
63
77
  // Base types for module definitions
64
78
  export type ModuleDefinition = {
65
79
  type: string;
@@ -110,7 +124,7 @@ export type SignalEventShape = {
110
124
  * When {@link HttpInterfaceSchemaWire.validation} is true, the runtime does **not** validate against
111
125
  * those JSON blobs alone: it loads the ESM at {@link HttpInterfaceSchemaWire.compiledValidatorKey}
112
126
  * (default export = Zod schema) and runs full `safeParse` on the payload via the runner-bound
113
- * {@link SignalHostServices.enforceSchema} RPC (see {@link setSignalEmitValidationHost}).
127
+ * {@link SignalRunHostServices.enforceSchema} RPC (see {@link setSignalEmitValidationHost}).
114
128
  */
115
129
  export type HttpInterfaceSchemaWire = {
116
130
  /**
@@ -141,9 +155,13 @@ export type HttpInterfaceSchemaWire = {
141
155
  coerceLeafPrimitives?: boolean | 'auto';
142
156
  };
143
157
 
144
- /** Host-backed RPC surface passed as `params.$` to signal `run` (parallel to action `ActionRunOptions.$`). */
145
- export type SignalHostServices = {
158
+ /**
159
+ * Host `params.$` during signal **`run`** (live webhook / test execution).
160
+ * Not passed to `hooks.save` — use {@link SignalSaveHookHostServices} there.
161
+ */
162
+ export type SignalRunHostServices = {
146
163
  export: (category: string, message: string) => void | Promise<void>;
164
+
147
165
  $transitionToSlot: (slots: Array<SlotTransitionDefinition>) => void | Promise<void>;
148
166
 
149
167
  /**
@@ -158,12 +176,30 @@ export type SignalHostServices = {
158
176
 
159
177
  /**
160
178
  * Wire for the primary `$.interface.schema` property (same persisted object the publish
161
- * pipeline attaches `compiledValidatorKey` to). Use with {@link SignalHostServices.enforceSchema},
179
+ * pipeline attaches `compiledValidatorKey` to). Use with {@link SignalRunHostServices.enforceSchema},
162
180
  * e.g. `await $.enforceSchema($.interfaceEmitSchema, toEmit)`.
163
181
  */
164
182
  interfaceEmitSchema?: HttpInterfaceSchemaWire;
165
183
  };
166
184
 
185
+ /** @deprecated Use {@link SignalRunHostServices} for `run`; hook `$` types are separate. */
186
+ export type SignalHostServices = SignalRunHostServices;
187
+
188
+ /** Host `params.$` during **`hooks.save`** (publish materialization only). */
189
+ export type SignalSaveHookHostServices = {
190
+ http: {
191
+ configureResponseCaching: (
192
+ options: ConfigureResponseCachingOptions,
193
+ ) => Promise<void> | void;
194
+ };
195
+ };
196
+
197
+ /** @deprecated Use {@link SignalSaveHookHostServices} */
198
+ export type HookSaveHostServices = SignalSaveHookHostServices;
199
+
200
+ /** Host `params.$` during `hooks.activate` / `hooks.deactivate` (no `run` or `save` surfaces). */
201
+ export type SignalLifecycleHookHostServices = Pick<SignalRunHostServices, 'export'>;
202
+
167
203
  /** One row from a failed Zod `safeParse` (host / `validateEmitPayload`). */
168
204
  export type SchemaValidationIssue = {
169
205
  path: string;
@@ -193,7 +229,7 @@ export type EnforceSchemaResult<T extends unknown = unknown> =
193
229
  export const PROCESS_CO_ENFORCE_SCHEMA_HOST_PAYLOAD_MARKER = 'enforceSchema' as const;
194
230
 
195
231
  export type SignalRunOptions = {
196
- $: SignalHostServices;
232
+ $: SignalRunHostServices;
197
233
  event: SignalEventShape;
198
234
  };
199
235
 
@@ -206,10 +242,10 @@ const SIGNAL_EMIT_VALIDATION_HOST = Symbol.for('process.co.signalEmitValidationH
206
242
 
207
243
  /**
208
244
  * Host shape accepted from the runner RPC bridge (`$.enforceSchema` may be typed as
209
- * returning `Promise<unknown>` while {@link SignalHostServices} uses a generic `T`).
245
+ * returning `Promise<unknown>` while {@link SignalRunHostServices} uses a generic `T`).
210
246
  */
211
247
  export type SignalEmitValidationHostBinding =
212
- | Pick<SignalHostServices, 'enforceSchema'>
248
+ | Pick<SignalRunHostServices, 'enforceSchema'>
213
249
  | {
214
250
  enforceSchema?: (
215
251
  inputSchema: HttpInterfaceSchemaWire | undefined,
@@ -217,8 +253,8 @@ export type SignalEmitValidationHostBinding =
217
253
  ) => Promise<unknown>;
218
254
  };
219
255
 
220
- function getSignalEmitValidationHostBinding(): Pick<SignalHostServices, 'enforceSchema'> | undefined {
221
- return (globalThis as Record<symbol, Pick<SignalHostServices, 'enforceSchema'> | undefined>)[
256
+ function getSignalEmitValidationHostBinding(): Pick<SignalRunHostServices, 'enforceSchema'> | undefined {
257
+ return (globalThis as Record<symbol, Pick<SignalRunHostServices, 'enforceSchema'> | undefined>)[
222
258
  SIGNAL_EMIT_VALIDATION_HOST
223
259
  ];
224
260
  }
@@ -232,11 +268,11 @@ function getSignalEmitValidationHostBinding(): Pick<SignalHostServices, 'enforce
232
268
  export function setSignalEmitValidationHost(
233
269
  host: SignalEmitValidationHostBinding | undefined,
234
270
  ): void {
235
- const g = globalThis as Record<symbol, Pick<SignalHostServices, 'enforceSchema'> | undefined>;
271
+ const g = globalThis as Record<symbol, Pick<SignalRunHostServices, 'enforceSchema'> | undefined>;
236
272
  if (host === undefined) {
237
273
  delete g[SIGNAL_EMIT_VALIDATION_HOST];
238
274
  } else {
239
- g[SIGNAL_EMIT_VALIDATION_HOST] = host as Pick<SignalHostServices, 'enforceSchema'>;
275
+ g[SIGNAL_EMIT_VALIDATION_HOST] = host as Pick<SignalRunHostServices, 'enforceSchema'>;
240
276
  }
241
277
  }
242
278
 
@@ -663,10 +699,12 @@ type PropDefinitionInput<TType = unknown> = BasePropDefinition & {
663
699
  };
664
700
 
665
701
  export type HttpInterfaceType = {
702
+
666
703
  /**
667
704
  * Full HTTP response (status / headers / body). Sending `body` completes the exchange for typical requests.
668
705
  */
669
706
  respond: (response: HTTPResponse) => Promise<any> | void;
707
+
670
708
  /**
671
709
  * Incremental write or SSE frame; does not complete the exchange. Pair with {@link end} or a terminal {@link respond} where applicable.
672
710
  */
@@ -680,6 +718,12 @@ export type HttpInterfaceType = {
680
718
  */
681
719
  deferHttpResponse: (timeoutMs?: number, options?: HttpDeferResponseOptions) => void;
682
720
 
721
+ /**
722
+ * Optional runtime vary suffix (hashed and appended to the HTTP base scenario key).
723
+ * Call when saved `$httpRequestCachePolicy.needsRuntimeVaryKey` is true.
724
+ */
725
+ setRequestVaryKey: (value: string) => void;
726
+
683
727
  /**
684
728
  * Append one JSON value to an incremental stream (`ndjson` or `jsonArray` defer modes). Each call is one line (NDJSON) or one array element (json-array).
685
729
  */
@@ -693,6 +737,7 @@ export type HttpInterfaceType = {
693
737
  flow: FlowFunctions;
694
738
  end: () => void;
695
739
  execute: () => Promise<{ headers?: Record<string, string>;[key: string]: any }>
740
+
696
741
  };
697
742
 
698
743
 
@@ -729,12 +774,32 @@ type PropTypeFromTypeValue<U, T = unknown> =
729
774
  : U extends "integer" ? number
730
775
  : U extends "$.interface.schema" ? HttpInterfaceSchemaWire
731
776
  : U extends "$.interface.http" ? HttpInterfaceType
777
+ : U extends "$.interface.duration" ? import('./http-request-cache').DurationWire
778
+ : U extends "$.interface.cacheVaryInfo" ? import('./http-request-cache').CacheVaryInfoWire
732
779
  : unknown;
733
780
 
781
+ /**
782
+ * Runtime shape of an embedded app prop (`props: { http: httpApp }` on a signal/action).
783
+ * Maps `propDefinitions` / `props` / `methods` to instance fields — not the `defineApp` module metadata (`type`, `app`, …).
784
+ */
785
+ export type DeriveEmbeddedAppPropInstance<T extends { type: 'app' }> = Spread<
786
+ (T extends { propDefinitions: Record<string, any> }
787
+ ? { [K in keyof T['propDefinitions']]: PropType<T['propDefinitions'][K]> }
788
+ : {}) &
789
+ (T extends { props: Record<string, any> }
790
+ ? { [K in keyof T['props']]: PropType<T['props'][K]> }
791
+ : {}) &
792
+ (T extends { methods: Record<string, any> }
793
+ ? { [K in keyof T['methods']]: T['methods'][K] }
794
+ : {})
795
+ >;
796
+
734
797
  // Utility type for transforming prop definitions to their runtime types
735
798
  export type PropType<T> =
736
- // 1. If T is an app definition, derive its instance type
737
- T extends { props: Record<string, any>; methods: Record<string, any> }
799
+ // 1. Embedded app module runtime prop surface (not the definition object)
800
+ T extends { type: 'app' }
801
+ ? DeriveEmbeddedAppPropInstance<T>
802
+ : T extends { props: Record<string, any>; methods: Record<string, any> }
738
803
  ? DeriveAppInstance<T>
739
804
  // 2. If T is a propDefinition, resolve from propDefinitions or props
740
805
  : T extends { propDefinition: readonly [infer App, infer PropName] }
@@ -801,24 +866,69 @@ export type DeriveAppInstance<T> =
801
866
  { [K in keyof T as K extends "props" | "propDefinitions" | "methods" ? never : K]: T[K] }
802
867
  >;
803
868
 
869
+ /** True when a prop definition resolves to `$.interface.http` (runtime-only on `run`). */
870
+ type IsHttpInterfacePropDef<P> =
871
+ P extends { type: '$.interface.http' }
872
+ ? true
873
+ : P extends { propDefinition: readonly [infer App, infer PropName] }
874
+ ? App extends { propDefinitions: Record<string, any> }
875
+ ? PropName extends keyof App['propDefinitions']
876
+ ? App['propDefinitions'][PropName] extends { type: '$.interface.http' }
877
+ ? true
878
+ : false
879
+ : false
880
+ : App extends { props: Record<string, any> }
881
+ ? PropName extends keyof App['props']
882
+ ? App['props'][PropName] extends { type: '$.interface.http' }
883
+ ? true
884
+ : false
885
+ : false
886
+ : false
887
+ : false;
888
+
804
889
  export type DeriveSignalInstance<T> =
805
890
  Spread<
806
- Omit<T, "props" | "propDefinitions" | "methods"> &
891
+ Omit<T, SignalInstanceExcludedKeys> &
807
892
  (T extends { props: Record<string, any> }
808
- ? { [K in keyof T["props"]]: PropType<T["props"][K]> }
893
+ ? { [K in keyof T['props']]: PropType<T['props'][K]> }
809
894
  : {}) &
810
895
  (T extends { propDefinitions: Record<string, any> }
811
- ? { [K in keyof T["propDefinitions"]]: PropType<T["propDefinitions"][K]> }
896
+ ? { [K in keyof T['propDefinitions']]: PropType<T['propDefinitions'][K]> }
812
897
  : {}) &
813
- // Add $emit to all signal instances
814
898
  EmitFunction &
815
899
  (T extends { methods: Record<string, any> }
816
- ? { [K in keyof T["methods"]]: T["methods"][K] }
900
+ ? { [K in keyof T['methods']]: T['methods'][K] }
817
901
  : {}) &
818
- // Also include all direct methods on the object
819
- { [K in keyof T as K extends "props" | "propDefinitions" | "methods" ? never : K]: T[K] }
902
+ {
903
+ [K in keyof T as K extends SignalInstanceExcludedKeys ? never : K]: T[K];
904
+ }
820
905
  >;
821
906
 
907
+ /** Module definition keys that are not instance fields on `this` in `run` or hooks. */
908
+ type SignalInstanceExcludedKeys =
909
+ | 'props'
910
+ | 'propDefinitions'
911
+ | 'methods'
912
+ | 'run'
913
+ | 'hooks';
914
+
915
+ /** Prop names on `T` that are `$.interface.http` (excluded from hook `this`). */
916
+ type HttpInterfacePropKeys<T> =
917
+ T extends { props: infer P extends Record<string, unknown> }
918
+ ? keyof {
919
+ [K in keyof P as IsHttpInterfacePropDef<P[K]> extends true ? K : never]: true;
920
+ }
921
+ : never;
922
+
923
+ /**
924
+ * `this` inside signal hooks: instance props minus `$.interface.http` and `$emit`.
925
+ * Use `params.$.http.configureResponseCaching` in `save`.
926
+ */
927
+ export type DeriveSignalHookInstance<T> = Omit<
928
+ DeriveSignalInstance<T>,
929
+ HttpInterfacePropKeys<T> | keyof EmitFunction
930
+ >;
931
+
822
932
  // In your element-types
823
933
  export type PropDefinitionType<App, PropName extends string> =
824
934
  App extends { propDefinitions: Record<string, any> }
@@ -827,21 +937,37 @@ export type PropDefinitionType<App, PropName extends string> =
827
937
  : unknown
828
938
  : unknown;
829
939
 
830
- // --- Add this helper above DeriveActionInstance ---
831
-
832
- // Enhanced action instance type
940
+ /** Module definition keys that are not instance fields on `this` in `run`. */
941
+ type ActionInstanceExcludedKeys =
942
+ | 'props'
943
+ | 'propDefinitions'
944
+ | 'methods'
945
+ | 'run'
946
+ | 'type'
947
+ | 'name'
948
+ | 'description'
949
+ | 'icon'
950
+ | 'noAuth'
951
+ | 'slots'
952
+ | 'hasNew'
953
+ | 'initValue';
954
+
955
+ /** Runtime `this` for action `run` (prop values via {@link PropType}, including embedded apps). */
833
956
  export type DeriveActionInstance<T> =
834
957
  Spread<
835
- Omit<T, "props" | "propDefinitions" | "methods"> &
958
+ Omit<T, ActionInstanceExcludedKeys> &
836
959
  (T extends { props: Record<string, any> }
837
- ? { [K in keyof T["props"]]: PropType<T["props"][K]> }
960
+ ? { [K in keyof T['props']]: PropType<T['props'][K]> }
838
961
  : {}) &
839
962
  (T extends { propDefinitions: Record<string, any> }
840
- ? { [K in keyof T["propDefinitions"]]: PropType<T["propDefinitions"][K]> }
963
+ ? { [K in keyof T['propDefinitions']]: PropType<T['propDefinitions'][K]> }
841
964
  : {}) &
842
965
  (T extends { methods: Record<string, any> }
843
- ? { [K in keyof T["methods"]]: T["methods"][K] }
844
- : {})
966
+ ? { [K in keyof T['methods']]: T['methods'][K] }
967
+ : {}) &
968
+ {
969
+ [K in keyof T as K extends ActionInstanceExcludedKeys ? never : K]: T[K];
970
+ }
845
971
  >;
846
972
 
847
973
  // Helper type to create a module with proper this context
@@ -878,7 +1004,10 @@ export type ActionInstance<A extends Action> = DeriveActionInstance<A>;
878
1004
  export type SignalInstance<S extends Signal> = DeriveSignalInstance<S>;
879
1005
 
880
1006
  export type SignalMethod<S extends Signal> = (this: SignalInstance<S>, params: SignalRunOptions) => Promise<unknown>;
881
- export type ActionMethod<A extends Action> = (this: ActionInstance<A>, params: { $: any }) => Promise<unknown>;
1007
+ export type ActionMethod<A extends Action> = (
1008
+ this: ActionInstance<A>,
1009
+ params: ActionRunOptions,
1010
+ ) => Promise<unknown>;
882
1011
 
883
1012
  export type PropStringDefinitionTypes = "text" | "html" | "markdown" | "json" | "xml" | "yaml" | "csv" | "tsv" | "css" | "sql" | "email" | "emailList" | "urlList" | "url" | "base64" | "javascript";
884
1013
 
@@ -905,22 +1034,112 @@ export function defineApp<const T extends object>(app: T & ThisType<DeriveAppIns
905
1034
  return app;
906
1035
  }
907
1036
 
908
- // Helper to provide ThisType context for action definitions
909
- export function defineAction<const T extends
910
- { props?: Record<string, unknown> } &
911
- { type: "action" } &
912
- { name?: string } &
913
- { description?: string } &
914
- { icon?: ElementIcon } &
915
- { noAuth?: boolean } &
916
- { slots?: ISlotDefinition } &
917
- { methods?: Record<string, (...args: any[]) => any> } &
918
- { hasNew?: boolean } &
919
- { initValue?: any }>(action: T & ThisType<DeriveActionInstance<T>>): T {
1037
+ export type ActionRunFn = (params: ActionRunOptions) => void | Promise<unknown>;
1038
+
1039
+ /** Canonical action entrypoint — implement `run` here (see process-internal loop, etc.). */
1040
+ export type ActionMethodsRun = {
1041
+ methods: Record<string, unknown> & { run: ActionRunFn };
1042
+ };
1043
+
1044
+ /**
1045
+ * @deprecated Use `methods: { run }` instead of a top-level `run` property.
1046
+ * Runtime still accepts this shape via `restructureElement`.
1047
+ */
1048
+ export type ActionMethodsLegacyTopLevelRun = {
1049
+ /** @deprecated Use `methods.run`. */
1050
+ run?: ActionRunFn;
1051
+ };
1052
+
1053
+ /** Minimum shape for {@link defineAction}. Prefer {@link ActionMethodsRun}. */
1054
+ export type ActionMethods = ActionMethodsRun | ActionMethodsLegacyTopLevelRun;
1055
+
1056
+ /** Structural requirements for an action module (tooling; prefer {@link defineAction}). */
1057
+ export type ActionDefinitionShape<T> = {
1058
+ methods: Record<string, unknown> & {
1059
+ run: (this: DeriveActionInstance<T>, params: ActionRunOptions) => Promise<unknown>;
1060
+ };
1061
+ /**
1062
+ * @deprecated Use `methods.run`.
1063
+ */
1064
+ run?: (this: DeriveActionInstance<T>, params: ActionRunOptions) => Promise<unknown>;
1065
+ };
1066
+
1067
+ /** Contextual `this` for top-level and `methods.*` action functions. */
1068
+ export type ActionMethodsWithThis<T> = T &
1069
+ ThisType<DeriveActionInstance<T>> &
1070
+ (T extends { methods?: infer M extends Record<string, unknown> }
1071
+ ? { methods: M & ThisType<DeriveActionInstance<T>> }
1072
+ : {});
1073
+
1074
+ export function defineAction<
1075
+ const T extends ActionMethods & { type: 'action' } & Record<string, unknown>,
1076
+ >(action: ActionMethodsWithThis<T>): T {
920
1077
  return action;
921
1078
  }
922
1079
 
923
- export function defineSignal<const T extends { run: (params: SignalRunOptions) => Promise<unknown> }>(signal: T & ThisType<DeriveSignalInstance<T>>): T {
1080
+ /** `params.$` for `hooks.activate` / `hooks.deactivate`. */
1081
+ export type SignalHostHookParameters = {
1082
+ $: SignalLifecycleHookHostServices;
1083
+ };
1084
+
1085
+ /** `params.$` for `hooks.save` — publish-only; not {@link SignalRunHostServices}. */
1086
+ export type SignalSaveHostParameters = {
1087
+ $: SignalSaveHookHostServices;
1088
+ };
1089
+
1090
+ export type SignalHostHookMethod<T> = (
1091
+ this: DeriveSignalHookInstance<T>,
1092
+ params: SignalHostHookParameters,
1093
+ ) => void | Promise<void>;
1094
+
1095
+ export type SignalSaveHookMethod<T> = (
1096
+ this: DeriveSignalHookInstance<T>,
1097
+ params: SignalSaveHostParameters,
1098
+ ) => void | Promise<void>;
1099
+
1100
+ export type SignalHooksDefinition<T> = {
1101
+ deactivate?: SignalHostHookMethod<T>;
1102
+ activate?: SignalHostHookMethod<T>;
1103
+ save?: SignalSaveHookMethod<T>;
1104
+ onDeactivate?: SignalHostHookMethod<T>;
1105
+ onActivate?: SignalHostHookMethod<T>;
1106
+ onSave?: SignalSaveHookMethod<T>;
1107
+ };
1108
+
1109
+ /**
1110
+ * Hook implementations for {@link defineSignal}: `params.$` is typed here; `this` comes from
1111
+ * {@link ThisType}<{@link DeriveSignalHookInstance}<T>> (avoids circular `T` and empty `this`).
1112
+ */
1113
+ export type SignalHooksContextualDefinition = {
1114
+ deactivate?: (params: SignalHostHookParameters) => void | Promise<void>;
1115
+ activate?: (params: SignalHostHookParameters) => void | Promise<void>;
1116
+ save?: (params: SignalSaveHostParameters) => void | Promise<void>;
1117
+ onDeactivate?: (params: SignalHostHookParameters) => void | Promise<void>;
1118
+ onActivate?: (params: SignalHostHookParameters) => void | Promise<void>;
1119
+ onSave?: (params: SignalSaveHostParameters) => void | Promise<void>;
1120
+ };
1121
+
1122
+ /** Hook bag for {@link defineSignal}. */
1123
+ export type SignalHooksWithThis<T> = SignalHooksContextualDefinition &
1124
+ ThisType<DeriveSignalHookInstance<T>>;
1125
+
1126
+ /** Structural requirements for a signal module (used by tooling; prefer {@link defineSignal}). */
1127
+ export type SignalDefinitionShape<T> = {
1128
+ run: (this: DeriveSignalInstance<T>, params: SignalRunOptions) => Promise<unknown>;
1129
+ hooks?: SignalHooksDefinition<T>;
1130
+ };
1131
+
1132
+ /** @deprecated Use {@link defineSignal} — kept for generated lib compatibility. */
1133
+ export type SignalMethods = {
1134
+ run: (params: SignalRunOptions) => Promise<unknown>;
1135
+ };
1136
+
1137
+ export function defineSignal<const T extends SignalMethods & Record<string, unknown>>(
1138
+ signal: T &
1139
+ ThisType<DeriveSignalInstance<T>> & {
1140
+ hooks?: SignalHooksWithThis<T>;
1141
+ },
1142
+ ): T {
924
1143
  return signal;
925
1144
  }
926
1145