@valancex/valance 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,16 @@
1
+ # @valancex/valance
2
+
3
+ The application-composition boundary over [NEXUS](https://github.com/ValanceX/Nexus) (behavior), [MESH](https://github.com/ValanceX/Mesh) (template semantics) and [PORT](https://github.com/ValanceX/Port) (target realization): one application, one NEXUS state, a view derived from it, MESH programs rendered to a PORT target.
4
+
5
+ ```ts
6
+ import * as Valance from "@valancex/valance"; // define, start, mount, hydrate (+ ApplicationHandle, Mounted, TargetFactory)
7
+ import * as Web from "@valancex/valance/web"; // Web.target, Web.history (needs @valancex/port-web)
8
+ import { renderToHtml } from "@valancex/valance/web/server";
9
+ ```
10
+
11
+ - **Compatibility set (0.1.0):** `@valancex/nexus` ^0.10.1 (a dependency); peers `@valancex/mesh-runtime` ^0.7.0, `@valancex/port-web` ^0.2.2 (optional, for the Web entries) and `effect` ^3.10.0.
12
+ - **Lifetimes:** the application lives in the caller's `Scope`; each mount lives in the caller's (separate) `Scope`.
13
+ - **Status:** pre-1.0. `./internal` is the composition protocol for binding authors and tests, unstable by design.
14
+ - **Architecture, ownership rules and evidence:** [`docs/FINDINGS.md`](https://github.com/ValanceX/Valance/blob/main/docs/FINDINGS.md) (see "Architectural checkpoint" and "Canonical lifecycle architecture"); constraints in [`docs/CONSTRAINTS.md`](https://github.com/ValanceX/Valance/blob/main/docs/CONSTRAINTS.md); release notes in [`docs/releases/v0.1.md`](https://github.com/ValanceX/Valance/blob/main/docs/releases/v0.1.md).
15
+
16
+ MIT licensed.
@@ -0,0 +1,138 @@
1
+ /**
2
+ * @valancex/valance: the application-composition boundary over NEXUS, MESH and PORT.
3
+ *
4
+ * It owns the composition that no substrate may own (NEXUS ARCHITECTURE §16, PORT CONTRACT "the composer"):
5
+ *
6
+ * define(app) data: program, state, scope, command bindings. No target, no platform.
7
+ * start(app, options) starts the NEXUS application in the CALLER's Scope; supplies the platform;
8
+ * creates the application's state and its MESH host; returns the application's handle:
9
+ * its `state` and `invoke`, and nothing of the composition (see ./internal).
10
+ * mount / hydrate connects a PORT target to a started application: draws (or adopts server
11
+ * server output for) the current render, follows later renders as updates, and
12
+ * dispatches each reported event with the render that was drawn.
13
+ *
14
+ * Command lifetime: commands admitted through `invoke` or MESH dispatch are owned by the application until they exit; closing the
15
+ * caller's Scope closes admission and drains them before NEXUS terminates and platform resources release (docs/FINDINGS.md, "Canonical lifecycle architecture").
16
+ *
17
+ * Nothing here is target-specific. A target is whatever satisfies `Target`, which is PORT's
18
+ * contract (draw / update / unmount, plus hydrate where a PORT has one) and nothing more.
19
+ */
20
+ import type { BoundaryValue, RenderTree } from "@valancex/mesh-runtime";
21
+ import * as Nexus from "@valancex/nexus";
22
+ import { type DispatchExit } from "./internal.js";
23
+ import { Effect, Exit, Schema, Scope } from "effect";
24
+ /** What a command binding may require: only what the NEXUS application runtime itself provides. */
25
+ export type Ambient = Nexus.Capability.EnvironmentShape | Nexus.Event.EventBusShape;
26
+ /** One MESH program the application can show, and the manifest-shaped values it is rendered from. */
27
+ export interface View<S> {
28
+ /** MESH program: templates compiled at build time, and the manifest's text. */
29
+ readonly program: Nexus.Mesh.Program;
30
+ /** State → the program root's scope values, shaped to the manifest. */
31
+ readonly scope: (state: S) => Record<string, unknown>;
32
+ }
33
+ export interface ApplicationDefinition<S, E, R extends Ambient, V extends string> {
34
+ readonly name: string;
35
+ /** The application's one NEXUS state. `initial` is the default; `start` may be given another (hydration). */
36
+ readonly state: {
37
+ readonly schema: Schema.Schema<S>;
38
+ readonly initial: S;
39
+ };
40
+ /** The MESH programs the application can show. The application's state outlives a change of program. */
41
+ readonly views: {
42
+ readonly [K in V]: View<S>;
43
+ };
44
+ /** Which program the current state shows. A function of application state: what the active view is, is the application's. */
45
+ readonly view: (state: S) => V;
46
+ /** Behavior: NEXUS commands over the state, bound to MESH command intents ("component/name"), for every view. */
47
+ readonly commands: (state: Nexus.State.StateHandle<S>) => Readonly<Record<string, Nexus.Mesh.Binding<E, R>>>;
48
+ }
49
+ /** The definition, typed. An application is data: defining one starts nothing. */
50
+ export declare const define: <S, E, R extends Ambient, V extends string>(definition: ApplicationDefinition<S, E, R, V>) => ApplicationDefinition<S, E, R, V>;
51
+ export type StartError = Nexus.Application.ApplicationInitError | Nexus.State.StateInitError;
52
+ export interface StartOptions<S> {
53
+ /** Supplied to NEXUS `Application.start`, where platform services (capabilities, Clock, …) enter. */
54
+ readonly platform?: Nexus.Application.Platform;
55
+ /** Overrides the definition's initial state: the client's, from what the server embedded. */
56
+ readonly state?: S;
57
+ }
58
+ /**
59
+ * The application's external face: what code outside its definition, and outside any MESH render, may do with it.
60
+ * Whoever holds it (a host page, a custom producer, a headless host, one of Valance's own bindings) holds exactly this.
61
+ *
62
+ * It carries no runtime, no render, no dispatch, and no lifecycle: the application's lifetime is the `Scope` `start`
63
+ * ran in, and nothing here ends it, restarts it, or reports on it.
64
+ */
65
+ export interface ApplicationHandle<S, E> {
66
+ /**
67
+ * The application's current state: one read, as of when it runs. A read, not a subscription: the state a host sees
68
+ * is the state commands have committed, whatever view is shown.
69
+ */
70
+ readonly state: Effect.Effect<S>;
71
+ /**
72
+ * Runs the command bound to `key` with the given arguments, exactly as a MESH intent for that key would:
73
+ * through the same table, so there is one way into application behavior. For input that does not come from a MESH
74
+ * render (a browser event, a host page, a headless caller).
75
+ *
76
+ * It executes in the application's own context, with the platform's FiberRefs, and nothing of that context flows
77
+ * back to the caller (NEXUS I44). The caller needs no runtime and provides no services: interrupting the returned
78
+ * effect interrupts the command, and typed failures and defects pass through unchanged.
79
+ */
80
+ readonly invoke: (key: string, args: ReadonlyArray<Nexus.Mesh.IntentArgument>) => Effect.Effect<unknown, Nexus.Mesh.UnmappedCommand | E>;
81
+ }
82
+ /**
83
+ * Starts the application. Its lifetime is the caller's `Scope`: closing it ends the application and its state, and
84
+ * Valance keeps nothing that outlives that scope. (NEXUS can also end an application early; that is the substrate's,
85
+ * is outside this model, and nothing here asks for it. The command drain below belongs to the Scope close, so that route does not pass it.)
86
+ */
87
+ export declare const start: <S, E, R extends Ambient, V extends string>(app: ApplicationDefinition<S, E, R, V>, options?: StartOptions<S>) => Effect.Effect<ApplicationHandle<S, E>, StartError, Scope.Scope>;
88
+ /** Reports what the user did: PORT's handler identifier and payload. */
89
+ export type Report = (handler: string, payload?: BoundaryValue) => void;
90
+ /** PORT's contract as the composer uses it. `draw`/`update` carry program continuity, which only the composer knows. */
91
+ export interface Target {
92
+ draw(tree: RenderTree): void;
93
+ update(tree: RenderTree): void;
94
+ unmount(): void;
95
+ }
96
+ /** A target whose PORT can take over server output (a PORT with a `hydrate`). `H` is PORT's own result. */
97
+ export interface HydratableTarget<H> extends Target {
98
+ hydrate(tree: RenderTree): H;
99
+ }
100
+ /** Builds a target that reports to `report`. */
101
+ export type TargetFactory<T extends Target> = (report: Report) => T;
102
+ /**
103
+ * What `mount` returns (and `hydrate` returns with `hydration` added): a host's view of ONE mount, owned by that mount's Scope. Every member is
104
+ * mount-owned information that no other public surface gives a host: `followed` is the only way to learn how the mount ended (the application ended, a render
105
+ * failed, or its Scope closed), `settled` the only way to wait for the event dispatches the mount made, `dispatched` the only record of their outcomes.
106
+ * Hosts that need none of them can ignore the value. The lifecycle of each member is stated in "Canonical lifecycle architecture" (docs/FINDINGS.md).
107
+ */
108
+ export interface Mounted<E> {
109
+ /**
110
+ * The exit of every dispatch this mount made for a reported event, appended as each one settles (settle order, never removed, never reordered).
111
+ * The only place the outcome of an event-triggered command is recorded: a failure or a defect appears nowhere else (not in state, values or the render).
112
+ * It belongs to the mount that dispatched, so exits keep arriving after that mount closed (a command is the application's once admitted, and ends with
113
+ * the application at the latest). It is an observation facility for hosts and tests, not part of the application programming model: nothing in
114
+ * Valance reads it, and `ApplicationHandle` does not expose it. It lives as long as the `Mounted` value is held.
115
+ */
116
+ readonly dispatched: ReadonlyArray<DispatchExit<E>>;
117
+ /**
118
+ * A barrier: succeeds once every dispatch this OPEN mount has made so far has settled (and those made while it waits). It does not read `dispatched`.
119
+ * A closed mount holds no dispatches, so `settled` returns at once and does not wait for the exits that are still to arrive in `dispatched`.
120
+ */
121
+ readonly settled: Effect.Effect<void>;
122
+ /** Completes when Valance stops following renders: Success when the application ended, a Failure when a render failed, Interrupted when the scope closed. */
123
+ readonly followed: Effect.Effect<Exit.Exit<void, Nexus.Mesh.MeshDiagnostics>>;
124
+ }
125
+ /**
126
+ * Draws the application's current render on a target, and keeps it current. Ends with the caller's Scope: the mount's lifetime is that Scope's,
127
+ * whatever Scope it is. If the application ends first (its own Scope closed), the follower ends (`Mounted.followed` Success) but the target stays
128
+ * drawn, inert, until this Scope closes.
129
+ */
130
+ export declare const mount: <S, E>(application: ApplicationHandle<S, E>, create: TargetFactory<Target>) => Effect.Effect<Mounted<E>, Nexus.Mesh.MeshDiagnostics, Scope.Scope>;
131
+ /**
132
+ * Takes over server output with the client's own render (never the server's), then keeps it current.
133
+ * What adoption or mismatch means is PORT's: `hydration` is its result, unchanged.
134
+ */
135
+ export declare const hydrate: <S, E, H>(application: ApplicationHandle<S, E>, create: TargetFactory<HydratableTarget<H>>) => Effect.Effect<Mounted<E> & {
136
+ readonly hydration: H;
137
+ }, Nexus.Mesh.MeshDiagnostics, Scope.Scope>;
138
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,142 @@
1
+ import * as Nexus from "@valancex/nexus";
2
+ import { handleOf, runningOf } from "./internal.js";
3
+ import { Deferred, Effect, Exit, Fiber, Layer, Stream } from "effect";
4
+ /** The definition, typed. An application is data: defining one starts nothing. */
5
+ export const define = (definition) => definition;
6
+ /**
7
+ * Starts the application. Its lifetime is the caller's `Scope`: closing it ends the application and its state, and
8
+ * Valance keeps nothing that outlives that scope. (NEXUS can also end an application early; that is the substrate's,
9
+ * is outside this model, and nothing here asks for it. The command drain below belongs to the Scope close, so that route does not pass it.)
10
+ */
11
+ export const start = (app, options = {}) => Effect.gen(function* () {
12
+ const definition = Nexus.Application.define({ name: app.name, runtime: Layer.empty });
13
+ const nexus = yield* Nexus.Application.start(definition, options.platform === undefined ? undefined : { platform: options.platform });
14
+ // Command lifetime: a command admitted through `inApplication` stays owned by the application until it exits. When the
15
+ // application's Scope closes, VALANCE closes admission and interrupts and awaits every admitted command BEFORE NEXUS
16
+ // terminates and the platform releases its resources. This finalizer is added right after `Application.start` registered
17
+ // NEXUS's own; Scope finalizers run in reverse order, so it runs first. It owns commands only, not daemons or escaped fibers.
18
+ const admitted = new Set();
19
+ let admissionClosed = false;
20
+ yield* Effect.addFinalizer(() => Effect.suspend(() => {
21
+ admissionClosed = true; // closes synchronously, before anything below can run
22
+ return Effect.forEach([...admitted], (command) => Fiber.interrupt(command), { discard: true }); // interrupts, and awaits each ACTUAL exit
23
+ }));
24
+ const state = yield* Nexus.Application.createState(nexus, app.state.schema, options.state ?? app.state.initial);
25
+ const commands = app.commands(state);
26
+ // One host per view, used to dispatch (render, handler) → intent → command. The one NEXUS state is shared by all of them.
27
+ const hosts = new Map(Object.entries(app.views).map(([name, view]) => [name, Nexus.Mesh.host({ program: view.program, scope: Nexus.Selector.define(state, view.scope), commands })]));
28
+ // The render of one given state. The adapter renders a host's scope value, not a value it is handed, and a
29
+ // sequential stream must render each emitted state exactly: a constant scope does that.
30
+ const renderOf = (value) => {
31
+ const view = app.view(value);
32
+ const snapshot = app.views[view].scope(value);
33
+ const scope = { value: Effect.succeed(snapshot), changes: Stream.empty, values: Stream.make(snapshot) };
34
+ return Nexus.Mesh.host({ program: app.views[view].program, scope, commands: {} }).render.pipe(Effect.map((render) => ({ view, render })));
35
+ };
36
+ // The one place an event enters the application's execution: its own fiber, with its own FiberRefs (NEXUS
37
+ // `runFork`: the handle holds none of them, so joining it imports nothing into the caller). The caller's
38
+ // interruption interrupts the event; results, typed failures and defects pass through unchanged.
39
+ // Admission: the command registers ITS OWN fiber as its first step. The admission check and the registration are one
40
+ // synchronous step inside that fiber (no gap in which the drain's snapshot could be taken between them); a refusal is a
41
+ // defect, by Effect's own means. The command leaves the registry on every exit.
42
+ const admit = (effect) => Effect.acquireUseRelease(Effect.withFiberRuntime((fiber) => Effect.sync(() => {
43
+ if (admissionClosed) {
44
+ throw new Error("VALANCE: admission is closed (draining)");
45
+ }
46
+ admitted.add(fiber);
47
+ })), () => effect, () => Effect.withFiberRuntime((fiber) => Effect.sync(() => { admitted.delete(fiber); })));
48
+ const inApplication = (effect) => Effect.suspend(() => {
49
+ const handle = Nexus.Runtime.runFork(nexus.runtime, admit(effect));
50
+ return Fiber.join(handle).pipe(Effect.onInterrupt(() => Fiber.interrupt(handle)));
51
+ });
52
+ const running = {
53
+ nexus,
54
+ render: Effect.flatMap(state.get, renderOf),
55
+ values: Stream.mapEffect(state.values, renderOf),
56
+ dispatch: (viewed, handler, payload) => {
57
+ const host = hosts.get(viewed.view);
58
+ return host === undefined ? Effect.die(new Error(`no view named ${viewed.view}`)) : inApplication(host.dispatch(viewed.render, handler, payload));
59
+ },
60
+ state: state.get,
61
+ states: state.values,
62
+ invoke: (key, args) => {
63
+ const binding = Object.hasOwn(commands, key) ? commands[key] : undefined;
64
+ const [component = "", name = ""] = key.split("/");
65
+ return binding === undefined ? Effect.fail({ _tag: "UnmappedCommand", component, name }) : inApplication(binding(args));
66
+ },
67
+ };
68
+ return handleOf(running);
69
+ });
70
+ const connect = (application, create, first) => Effect.gen(function* () {
71
+ const running = runningOf(application);
72
+ const scope = yield* Effect.scope;
73
+ // The render whose tree is drawn: the only render an event may be dispatched with (NEXUS M1, M2).
74
+ const drawn = { current: undefined };
75
+ const dispatched = [];
76
+ const pending = [];
77
+ const target = create((handler, payload) => {
78
+ const render = drawn.current;
79
+ if (render === undefined) {
80
+ throw new Error("the target reported an interaction before anything was drawn");
81
+ }
82
+ // `dispatch` runs inside the application (its platform's FiberRefs apply) and nothing flows back (NEXUS I44).
83
+ pending.push(Effect.runFork(Effect.exit(running.dispatch(render, handler, payload)).pipe(Effect.tap((exit) => Effect.sync(() => { dispatched.push(exit); })))));
84
+ });
85
+ // `running.values` is the render of the current state, then one per later commit, atomically (NEXUS 0.10): the
86
+ // first element is the first draw (or hydration), no commit can fall between. A later render of the SAME view is
87
+ // the same program: update. One of ANOTHER view is another program, and only the composer knows that: draw afresh.
88
+ // The follower is Valance's fiber, not NEXUS's (O15): the caller's scope owns it.
89
+ const firstDone = yield* Deferred.make();
90
+ const follower = yield* Stream.runForEach(running.values, (viewed) => Effect.suspend(() => {
91
+ if (drawn.current !== undefined) {
92
+ if (drawn.current.view === viewed.view) {
93
+ target.update(viewed.render.tree);
94
+ }
95
+ else {
96
+ target.draw(viewed.render.tree);
97
+ }
98
+ drawn.current = viewed;
99
+ return Effect.void;
100
+ }
101
+ // Draw or hydrate, and retain the render, in one synchronous step: no event can be reported in between.
102
+ const result = first(target, viewed.render.tree);
103
+ drawn.current = viewed;
104
+ return Deferred.succeed(firstDone, result);
105
+ })).pipe(
106
+ // Ending before the first render (a diagnostic, a failure of the target, an application that ended) is mount's failure.
107
+ Effect.onExit((exit) => Exit.match(exit, {
108
+ onFailure: (cause) => Deferred.failCause(firstDone, cause),
109
+ onSuccess: () => Deferred.die(firstDone, new Error("the application ended before its first render")),
110
+ })), Effect.forkIn(scope));
111
+ const result = yield* Deferred.await(firstDone);
112
+ // Scope finalizers run in reverse: this runs before the application ends.
113
+ yield* Effect.addFinalizer(() => Effect.gen(function* () {
114
+ yield* Fiber.interrupt(follower);
115
+ yield* Effect.sync(() => { target.unmount(); });
116
+ // A command an event started is the APPLICATION's once admitted (C20): closing the mount ends the follower and the target, not the command.
117
+ // The mount only lets go of the dispatch fibers it held; the application's registry still owns, drains and interrupts them (Stage 39).
118
+ yield* Effect.sync(() => { pending.splice(0); });
119
+ }));
120
+ // Dispatches may start more dispatches' worth of work only through the target, so draining until empty terminates.
121
+ const settled = Effect.suspend(() => pending.length === 0
122
+ ? Effect.void
123
+ : Effect.forEach(pending.splice(0), Fiber.await, { discard: true }).pipe(Effect.andThen(settled)));
124
+ return {
125
+ first: result,
126
+ dispatched,
127
+ settled,
128
+ followed: Fiber.await(follower),
129
+ };
130
+ });
131
+ /**
132
+ * Draws the application's current render on a target, and keeps it current. Ends with the caller's Scope: the mount's lifetime is that Scope's,
133
+ * whatever Scope it is. If the application ends first (its own Scope closed), the follower ends (`Mounted.followed` Success) but the target stays
134
+ * drawn, inert, until this Scope closes.
135
+ */
136
+ export const mount = (application, create) => Effect.map(connect(application, create, (target, tree) => { target.draw(tree); }), ({ first: _, ...mounted }) => mounted);
137
+ /**
138
+ * Takes over server output with the client's own render (never the server's), then keeps it current.
139
+ * What adoption or mismatch means is PORT's: `hydration` is its result, unchanged.
140
+ */
141
+ export const hydrate = (application, create) => Effect.map(connect(application, create, (target, tree) => target.hydrate(tree)), ({ first, ...mounted }) => ({ ...mounted, hydration: first }));
142
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The composition protocol between Valance's core and the code that binds an application to something outside it
3
+ * (a PORT target, browser history, a server render, a test). It is NOT the application's face: the public handle
4
+ * (`ApplicationHandle`, from the package entry) carries only `state` and `invoke`, and does not reach this.
5
+ *
6
+ * `Running` is what `start` builds. A handle is registered against the `Running` it fronts in a module-private map,
7
+ * so nothing reachable from a handle leads here; only code that imports this module (the package's own bindings and,
8
+ * through the `./internal` entry, binding authors and tests) can resolve one. Unstable by design.
9
+ */
10
+ import type * as Nexus from "@valancex/nexus";
11
+ import type { Effect, Exit, Stream } from "effect";
12
+ import type { ApplicationHandle } from "./index.js";
13
+ /**
14
+ * How one event dispatch ended, as `Mounted.dispatched` records it: what MESH dispatched, or why it did not (a MESH diagnostic, an unmapped
15
+ * command, the command's own typed failure, a defect, interruption). A diagnostic type: it is not nameable from the package entry, which commits to
16
+ * no consumer of it (Stage 42); readers of `dispatched` use its structure.
17
+ */
18
+ export type DispatchExit<E> = Exit.Exit<Nexus.Mesh.Dispatched, Nexus.Mesh.MeshDiagnostics | Nexus.Mesh.UnmappedCommand | E>;
19
+ /** A MESH render, and which view's program made it. Program continuity is "same view as the drawn one". */
20
+ export interface Viewed {
21
+ readonly view: string;
22
+ readonly render: Nexus.Mesh.Render;
23
+ }
24
+ export interface Running<S, E> {
25
+ /** The NEXUS application. Read only to observe the substrate (a test); never needed to deliver an event. */
26
+ readonly nexus: Nexus.Application.RunningApplication<never>;
27
+ /** The render of the current state, in the view the current state selects. */
28
+ readonly render: Effect.Effect<Viewed, Nexus.Mesh.MeshDiagnostics>;
29
+ /** The render of the state current at subscription, then one per later commit, in order, with no gap (NEXUS `State.values`). */
30
+ readonly values: Stream.Stream<Viewed, Nexus.Mesh.MeshDiagnostics>;
31
+ /**
32
+ * Dispatches an event against exactly the render it was reported on, through its own view's command table. It runs
33
+ * in the application, whoever calls it: the caller needs no runtime.
34
+ */
35
+ readonly dispatch: (viewed: Viewed, handler: string, payload?: Parameters<Nexus.Mesh.Host<never, never>["dispatch"]>[2]) => Effect.Effect<Nexus.Mesh.Dispatched, Nexus.Mesh.MeshDiagnostics | Nexus.Mesh.UnmappedCommand | E>;
36
+ /** The application's state, read only. */
37
+ readonly state: Effect.Effect<S>;
38
+ /** The state current at subscription, then every later commit, with no gap (NEXUS `State.values`). Read only. */
39
+ readonly states: Stream.Stream<S>;
40
+ /** Runs the command bound to `key`, in the application's own context (see `ApplicationHandle.invoke`). */
41
+ readonly invoke: (key: string, args: ReadonlyArray<Nexus.Mesh.IntentArgument>) => Effect.Effect<unknown, Nexus.Mesh.UnmappedCommand | E>;
42
+ }
43
+ /** The public face of a `Running`: its `state` and `invoke`, and nothing else. Registered, so bindings can resolve it. */
44
+ export declare const handleOf: <S, E>(running: Running<S, E>) => ApplicationHandle<S, E>;
45
+ /** The `Running` a handle fronts. For bindings (and tests): an application's caller never needs it. */
46
+ export declare const runningOf: <S, E>(handle: ApplicationHandle<S, E>) => Running<S, E>;
47
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,KAAK,KAAK,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD;;;;GAIG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;AAE5H,2GAA2G;AAC3G,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,OAAO,CAAC,CAAC,EAAE,CAAC;IAC3B,4GAA4G;IAC5G,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC5D,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACnE,gIAAgI;IAChI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACnE;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;IAC9N,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACjC,iHAAiH;IACjH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAClC,0GAA0G;IAC1G,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;CAC1I;AAID,0HAA0H;AAC1H,eAAO,MAAM,QAAQ,GAAI,CAAC,EAAE,CAAC,EAAE,SAAS,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAM7E,CAAC;AAEF,uGAAuG;AACvG,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAQ7E,CAAC"}
@@ -0,0 +1,16 @@
1
+ const registry = new WeakMap();
2
+ /** The public face of a `Running`: its `state` and `invoke`, and nothing else. Registered, so bindings can resolve it. */
3
+ export const handleOf = (running) => {
4
+ const handle = Object.freeze({ state: running.state, invoke: running.invoke });
5
+ registry.set(handle, running);
6
+ return handle;
7
+ };
8
+ /** The `Running` a handle fronts. For bindings (and tests): an application's caller never needs it. */
9
+ export const runningOf = (handle) => {
10
+ const running = registry.get(handle);
11
+ if (running === undefined) {
12
+ throw new Error("not an application handle that Valance started");
13
+ }
14
+ return running;
15
+ };
16
+ //# sourceMappingURL=internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AA8CA,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAiC,CAAC;AAE9D,0HAA0H;AAC1H,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAO,OAAsB,EAA2B,EAAE;IAChF,MAAM,MAAM,GAA4B,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAExG,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,OAA2C,CAAC,CAAC;IAElE,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,uGAAuG;AACvG,MAAM,CAAC,MAAM,SAAS,GAAG,CAAO,MAA+B,EAAiB,EAAE;IAChF,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAErC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IAED,OAAO,OAAmC,CAAC;AAC7C,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Server rendering for the Web target: start the application, take its current MESH render, and let
3
+ * PORT's server entry write it as HTML. The state is returned so the application can embed it for the
4
+ * client: serializing it into a page is the application's job, not NEXUS's, PORT's or Valance's.
5
+ */
6
+ import type { Mesh } from "@valancex/nexus";
7
+ import type { WebPrimitives } from "@valancex/port-web/server";
8
+ import type { Ambient, ApplicationDefinition, StartError, StartOptions } from "./index.js";
9
+ import { Effect } from "effect";
10
+ export interface Served<S> {
11
+ readonly html: string;
12
+ readonly state: S;
13
+ }
14
+ /** Starts the application, renders it once, and ends it. No target object, no DOM. */
15
+ export declare const renderToHtml: <S, E, R extends Ambient, V extends string>(app: ApplicationDefinition<S, E, R, V>, options: StartOptions<S> & {
16
+ readonly primitives: WebPrimitives;
17
+ }) => Effect.Effect<Served<S>, StartError | Mesh.MeshDiagnostics>;
18
+ //# sourceMappingURL=web-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-server.d.ts","sourceRoot":"","sources":["../src/web-server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG3F,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKhC,MAAM,WAAW,MAAM,CAAC,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB;AAED,sFAAsF;AACtF,eAAO,MAAM,YAAY,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,MAAM,EACpE,KAAK,qBAAqB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACtC,SAAS,YAAY,CAAC,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAA;CAAE,KAChE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,eAAe,CAMxD,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { realizeHtml } from "@valancex/port-web/server";
2
+ import { Effect } from "effect";
3
+ import { runningOf } from "./internal.js";
4
+ import { start } from "./index.js";
5
+ /** Starts the application, renders it once, and ends it. No target object, no DOM. */
6
+ export const renderToHtml = (app, options) => Effect.scoped(Effect.gen(function* () {
7
+ const running = runningOf(yield* start(app, options));
8
+ const viewed = yield* running.render;
9
+ return { html: realizeHtml(viewed.render.tree, options.primitives), state: yield* running.state };
10
+ }));
11
+ //# sourceMappingURL=web-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-server.js","sourceRoot":"","sources":["../src/web-server.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAOnC,sFAAsF;AACtF,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,GAAsC,EACtC,OAAiE,EACJ,EAAE,CAC/D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAChC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAErC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;AACpG,CAAC,CAAC,CAAC,CAAC"}
package/dist/web.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The Web target for Valance: the only module that names `@valancex/port-web`.
3
+ * It adds nothing to PORT: it fixes `container` and `primitives` (the application's Web realization
4
+ * table, which is target configuration, not part of the application) and hands PORT the report callback.
5
+ */
6
+ import type { WebPort, WebPortOptions } from "@valancex/port-web";
7
+ import type { BoundaryValue } from "@valancex/mesh-runtime";
8
+ import type { ApplicationHandle, TargetFactory } from "./index.js";
9
+ import { Effect, Scope } from "effect";
10
+ export type { HydrationResult, WebPrimitives } from "@valancex/port-web";
11
+ export { attribute, booleanAttribute, property, textProperty } from "@valancex/port-web";
12
+ export declare const target: (options: Omit<WebPortOptions, "report">) => TargetFactory<WebPort>;
13
+ export interface HistoryOptions<S> {
14
+ /** The window whose URL and history are kept in step with the application (the container's own: `container.ownerDocument.defaultView`). */
15
+ readonly window: Window;
16
+ /** The URL (path and query) the application is shown at for `state`. What a URL means is the application's. */
17
+ readonly urlOf: (state: S) => string;
18
+ /** What a URL says about the application: the one argument of the navigate binding. The application's, too. */
19
+ readonly stateOf: (url: URL) => BoundaryValue;
20
+ /** The binding key of the application's navigate command, the same entry a MESH intent uses. */
21
+ readonly navigate: string;
22
+ }
23
+ /**
24
+ * Keeps `location` and the application in step, in both directions, until the caller's Scope closes.
25
+ *
26
+ * start the first state's `urlOf` is the baseline; nothing is written.
27
+ * later state `urlOf(state)` differs from the last synchronized `urlOf` → `history.pushState`, which becomes the baseline.
28
+ * popstate `running.invoke(navigate, [stateOf(location)])`, then the resulting state's `urlOf` becomes the baseline. Never a write.
29
+ *
30
+ * The question it answers is "did the application's URL change?", never "does the browser's URL equal the
31
+ * application's?": a page sitting at a noncanonical URL (a history entry the application did not write) is left
32
+ * alone, and an unrelated state change is not a navigation. Canonicalizing the URL is the application's, before start.
33
+ *
34
+ * A popstate whose navigation fails, or leaves the state unchanged, is not repaired: nothing is written, the browser
35
+ * stays at the URL history gave it, the baseline is the (unchanged) state's own URL, and the failure is only logged.
36
+ * Browser URL and application URL then differ until the next application navigation; restoring one is the application's.
37
+ *
38
+ * Popstate is handled by the same fiber that watches state, in order, so the commit a popstate causes is seen after
39
+ * the baseline has been updated for it, not as a new navigation. It reads and writes the URL and knows nothing of
40
+ * what a URL means. PORT Web has no history API (it touches nothing outside its container), so this is Valance's.
41
+ */
42
+ export declare const history: <S, E>(application: ApplicationHandle<S, E>, options: HistoryOptions<S>) => Effect.Effect<void, never, Scope.Scope>;
43
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAInE,OAAO,EAAE,MAAM,EAAgB,KAAK,EAAU,MAAM,QAAQ,CAAC;AAE7D,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEzF,eAAO,MAAM,MAAM,GAAI,SAAS,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,KAAG,aAAa,CAAC,OAAO,CAAsD,CAAC;AAE7I,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,2IAA2I;IAC3I,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+GAA+G;IAC/G,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC;IACrC,+GAA+G;IAC/G,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,aAAa,CAAC;IAC9C,gGAAgG;IAChG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,CAAC,EAAE,aAAa,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,cAAc,CAAC,CAAC,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CA4CnI,CAAC"}
package/dist/web.js ADDED
@@ -0,0 +1,57 @@
1
+ import { createWebPort } from "@valancex/port-web";
2
+ import { runningOf } from "./internal.js";
3
+ import { Effect, Fiber, Queue, Stream } from "effect";
4
+ export { attribute, booleanAttribute, property, textProperty } from "@valancex/port-web";
5
+ export const target = (options) => (report) => createWebPort({ ...options, report });
6
+ /**
7
+ * Keeps `location` and the application in step, in both directions, until the caller's Scope closes.
8
+ *
9
+ * start the first state's `urlOf` is the baseline; nothing is written.
10
+ * later state `urlOf(state)` differs from the last synchronized `urlOf` → `history.pushState`, which becomes the baseline.
11
+ * popstate `running.invoke(navigate, [stateOf(location)])`, then the resulting state's `urlOf` becomes the baseline. Never a write.
12
+ *
13
+ * The question it answers is "did the application's URL change?", never "does the browser's URL equal the
14
+ * application's?": a page sitting at a noncanonical URL (a history entry the application did not write) is left
15
+ * alone, and an unrelated state change is not a navigation. Canonicalizing the URL is the application's, before start.
16
+ *
17
+ * A popstate whose navigation fails, or leaves the state unchanged, is not repaired: nothing is written, the browser
18
+ * stays at the URL history gave it, the baseline is the (unchanged) state's own URL, and the failure is only logged.
19
+ * Browser URL and application URL then differ until the next application navigation; restoring one is the application's.
20
+ *
21
+ * Popstate is handled by the same fiber that watches state, in order, so the commit a popstate causes is seen after
22
+ * the baseline has been updated for it, not as a new navigation. It reads and writes the URL and knows nothing of
23
+ * what a URL means. PORT Web has no history API (it touches nothing outside its container), so this is Valance's.
24
+ */
25
+ export const history = (application, options) => Effect.gen(function* () {
26
+ const running = runningOf(application);
27
+ const scope = yield* Effect.scope;
28
+ const { window: win } = options;
29
+ const popped = yield* Queue.unbounded();
30
+ // The application URL of the last state this mechanism has accounted for. Unset until the first state: the baseline.
31
+ let last;
32
+ const follower = yield* Stream.runForEach(Stream.merge(Stream.map(running.states, (state) => ({ _tag: "state", state })), Stream.map(Stream.fromQueue(popped), (href) => ({ _tag: "popstate", href }))), (event) => event._tag === "state"
33
+ ? Effect.sync(() => {
34
+ const url = options.urlOf(event.state);
35
+ if (last === undefined) {
36
+ last = url;
37
+ }
38
+ else if (url !== last) {
39
+ last = url;
40
+ win.history.pushState(null, "", url);
41
+ }
42
+ })
43
+ : Effect.gen(function* () {
44
+ // Through the application's own entry: it runs in the application, and a failure or defect is logged, never the follower's.
45
+ yield* running.invoke(options.navigate, [{ value: options.stateOf(new URL(event.href)) }]).pipe(Effect.catchAllCause((cause) => Effect.logError("popstate navigation failed", cause)));
46
+ // The state the popstate produced is the new baseline, whatever URL history happens to hold for it.
47
+ last = options.urlOf(yield* running.state);
48
+ })).pipe(Effect.forkIn(scope));
49
+ const onPopState = () => { Queue.unsafeOffer(popped, win.location.href); };
50
+ win.addEventListener("popstate", onPopState);
51
+ // Reverse order of the scope: before the application ends.
52
+ yield* Effect.addFinalizer(() => Effect.gen(function* () {
53
+ yield* Effect.sync(() => { win.removeEventListener("popstate", onPopState); });
54
+ yield* Fiber.interrupt(follower);
55
+ }));
56
+ });
57
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAS,MAAM,EAAE,MAAM,QAAQ,CAAC;AAG7D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEzF,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAAuC,EAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AAa7I;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAO,WAAoC,EAAE,OAA0B,EAA2C,EAAE,CACzI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;IAClC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IAChC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,EAAU,CAAC;IAChD,qHAAqH;IACrH,IAAI,IAAwB,CAAC;IAE7B,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CACvC,MAAM,CAAC,KAAK,CACV,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAgB,EAAE,KAAK,EAAE,CAAC,CAAC,EAC1E,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,UAAmB,EAAE,IAAI,EAAE,CAAC,CAAC,CACtF,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO;QAC/B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YACjB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAEvC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,IAAI,GAAG,GAAG,CAAC;YACb,CAAC;iBAAM,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACxB,IAAI,GAAG,GAAG,CAAC;gBACX,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;QACF,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACpB,4HAA4H;YAC5H,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAC7F,MAAM,CAAC,aAAa,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC,CACtF,CAAC;YACF,oGAAoG;YACpG,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7C,CAAC,CAAC,CACL,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAE7B,MAAM,UAAU,GAAG,GAAS,EAAE,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjF,GAAG,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAE7C,2DAA2D;IAC3D,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACnD,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/E,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC,CAAC;AACN,CAAC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@valancex/valance",
3
+ "version": "0.1.0",
4
+ "description": "VALANCE application composition: starts a NEXUS application, renders it with MESH, and realizes it on a PORT target.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Jack Miller <jackmiller0899@gmail.com>",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/ValanceX/Valance.git",
11
+ "directory": "packages/valance"
12
+ },
13
+ "engines": {
14
+ "node": ">=22"
15
+ },
16
+ "sideEffects": false,
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.js"
21
+ },
22
+ "./web": {
23
+ "types": "./dist/web.d.ts",
24
+ "default": "./dist/web.js"
25
+ },
26
+ "./web/server": {
27
+ "types": "./dist/web-server.d.ts",
28
+ "default": "./dist/web-server.js"
29
+ },
30
+ "./internal": {
31
+ "types": "./dist/internal.d.ts",
32
+ "default": "./dist/internal.js"
33
+ },
34
+ "./package.json": "./package.json"
35
+ },
36
+ "types": "./dist/index.d.ts",
37
+ "files": [
38
+ "dist"
39
+ ],
40
+ "dependencies": {
41
+ "@valancex/nexus": "^0.10.1"
42
+ },
43
+ "peerDependencies": {
44
+ "@valancex/mesh-runtime": "^0.7.0",
45
+ "@valancex/port-web": "^0.2.2",
46
+ "effect": "^3.10.0"
47
+ },
48
+ "peerDependenciesMeta": {
49
+ "@valancex/port-web": {
50
+ "optional": true
51
+ }
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^22.0.0",
55
+ "@valancex/mesh-runtime": "^0.7.0",
56
+ "@valancex/port-web": "^0.2.2",
57
+ "effect": "^3.10.0",
58
+ "typescript": "^5.6.0",
59
+ "vitest": "^3.2.0"
60
+ },
61
+ "scripts": {
62
+ "build": "tsc -p tsconfig.json",
63
+ "typecheck": "tsc -p tsconfig.typecheck.json",
64
+ "test": "vitest run"
65
+ }
66
+ }