@phreshos/core 0.1.0 → 0.1.1
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/LICENSE +19 -0
- package/README.md +246 -75
- package/dist/askable.d.ts +5 -1
- package/dist/channel.d.ts +3 -2
- package/dist/client.d.ts +5 -5
- package/dist/color.d.ts +10 -0
- package/dist/color.js +14 -0
- package/dist/config.d.ts +22 -11
- package/dist/config.js +0 -6
- package/dist/endpoint.d.ts +6 -5
- package/dist/launch.d.ts +10 -2
- package/dist/main.d.ts +11 -4
- package/dist/main.js +8 -1
- package/dist/outcome.d.ts +4 -0
- package/dist/permissions.d.ts +34 -0
- package/dist/permissions.js +6 -0
- package/dist/process.d.ts +5 -9
- package/dist/program.d.ts +24 -14
- package/dist/publishable.d.ts +5 -1
- package/dist/scale.d.ts +12 -0
- package/dist/scale.js +29 -0
- package/dist/server.d.ts +4 -4
- package/dist/sql.d.ts +7 -0
- package/dist/storage.d.ts +10 -0
- package/dist/subscribable.d.ts +32 -3
- package/dist/theme.d.ts +132 -0
- package/dist/theme.js +34 -0
- package/dist/timeout.d.ts +5 -0
- package/dist/timeout.js +0 -0
- package/dist/value.d.ts +17 -0
- package/dist/value.js +118 -0
- package/dist/wallpaper.d.ts +30 -0
- package/dist/wallpaper.js +0 -0
- package/dist/window.d.ts +50 -12
- package/dist/window.js +0 -4
- package/package.json +35 -9
- package/source/askable.ts +0 -26
- package/source/channel.ts +0 -28
- package/source/client.ts +0 -29
- package/source/config.ts +0 -104
- package/source/endpoint.ts +0 -95
- package/source/launch.ts +0 -43
- package/source/main.ts +0 -65
- package/source/outcome.ts +0 -4
- package/source/process.ts +0 -77
- package/source/program.ts +0 -130
- package/source/publishable.ts +0 -33
- package/source/served-file.ts +0 -14
- package/source/server.ts +0 -58
- package/source/sql.ts +0 -36
- package/source/storage.ts +0 -66
- package/source/subscribable.ts +0 -94
- package/source/window.ts +0 -82
package/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2026 Zohayr SLILEH
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
14
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
15
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
16
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
17
|
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
18
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
|
19
|
+
OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,42 +1,131 @@
|
|
|
1
1
|
# `@phreshos/core`
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Environment-neutral contracts and domain objects for PhreshOS Programs. Core
|
|
4
|
+
is the common language shared by the Client, Server, React, CLI, and system
|
|
5
|
+
repositories; it contains no transport, persistence, or interface
|
|
6
|
+
implementation of its own.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
bun add @phreshos/core
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Import exclusively through the package's public root:
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { defineConfig, type Program } from "@phreshos/core"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The package exposes built JavaScript and declaration files as its only public
|
|
21
|
+
code. Its TypeScript source is repository material, not a runtime dependency
|
|
22
|
+
or a public import path.
|
|
5
23
|
|
|
6
24
|
## Package status
|
|
7
25
|
|
|
8
|
-
This package is one component of a larger architecture
|
|
9
|
-
|
|
10
|
-
|
|
26
|
+
This package is one component of a larger architecture currently under active
|
|
27
|
+
testing. The `0.x` line may change as its contracts and integrations are
|
|
28
|
+
verified.
|
|
11
29
|
|
|
12
30
|
`@phreshos/core` is not intended to be used on its own. It defines the shared
|
|
13
|
-
contracts consumed by the environment SDKs
|
|
31
|
+
contracts consumed by the environment SDKs, but does not provide a runtime
|
|
14
32
|
implementation by itself.
|
|
15
33
|
|
|
16
|
-
|
|
34
|
+
## Mental model
|
|
35
|
+
|
|
36
|
+
Programs use Core directly for `defineConfig()` and shared types. At runtime,
|
|
37
|
+
the Client and Server SDKs provide the real `Program`, `Process`, `Server`, and
|
|
38
|
+
`Client` handles backed by their environment boundaries. Core gives those
|
|
39
|
+
environments one vocabulary and stable runtime identity without implementing
|
|
40
|
+
their transport, storage, authority, or presentation.
|
|
41
|
+
|
|
42
|
+
## Permission names
|
|
43
|
+
|
|
44
|
+
Core owns the finite, system-wide permission registry. `permissionNames` is
|
|
45
|
+
its runtime value, `PermissionName` is the corresponding SDK type, and
|
|
46
|
+
`isPermissionName()` validates values arriving from untyped boundaries. Client
|
|
47
|
+
and Server SDK permission methods accept only this type, so Programs cannot
|
|
48
|
+
create private permission strings that the system does not understand.
|
|
49
|
+
|
|
50
|
+
The current registry contains `pointer`. Persistent snapshots use
|
|
51
|
+
`PermissionDecisions`, a partial map, since an absent permission simply has no
|
|
52
|
+
stored decision.
|
|
53
|
+
|
|
54
|
+
## Theme lifecycle
|
|
55
|
+
|
|
56
|
+
Core defines both `ThemeProperties` and the read-only `Theme` contract without
|
|
57
|
+
any knowledge of how a given interface renders them. `snapshot()` is an
|
|
58
|
+
explicit, asynchronous read of one complete, immutable value. `Theme` extends
|
|
59
|
+
the ordinary `Subscribable` capability with a `change` event; it has no
|
|
60
|
+
dedicated subscription shape of its own.
|
|
61
|
+
|
|
62
|
+
Theme properties are expressed as concrete default values. `themeLimits`
|
|
63
|
+
declares the system-owned customization bounds for spacing, corner radius, and
|
|
64
|
+
glass-material properties; implementing authorities validate replacements
|
|
65
|
+
against those bounds. Core defines one fixed numeric scale around any explicit
|
|
66
|
+
number and one fixed color scale around any explicit CSS color — it does not
|
|
67
|
+
prescribe which value an interface ultimately chooses to derive. Background,
|
|
68
|
+
foreground, and accent are independent CSS color sources, with standard values
|
|
69
|
+
of `#edf8fc`, `#183447`, and `#4c9cff` — the established pale surface, primary
|
|
70
|
+
ink, and original system blue, respectively. Core stores only those source
|
|
71
|
+
colors, never their derived treatments. The declared glass-opacity range ends
|
|
72
|
+
at `0.3`.
|
|
73
|
+
|
|
74
|
+
`standardTheme` is the single, complete initial value shared by every
|
|
75
|
+
environment; the running system remains the authority for its current value.
|
|
76
|
+
`createThemeSnapshot()` copies and freezes a complete replacement at the
|
|
77
|
+
contract boundary; validation remains the implementing authority's
|
|
78
|
+
responsibility.
|
|
79
|
+
|
|
80
|
+
Derived variants are calculations, not persisted `Theme` state. `numericScale()`
|
|
81
|
+
produces `xsmall`, `small`, `medium`, `large`, and `xlarge`, preserving the
|
|
82
|
+
supplied value exactly at `medium`. `color()` produces `subtle`, `soft`, `base`,
|
|
83
|
+
`strong`, and `intense`, preserving the supplied color exactly at `base`.
|
|
84
|
+
|
|
85
|
+
`subscribe("change", listener)` delivers only complete replacements published
|
|
86
|
+
after that registration exists. It never supplies an initial snapshot and
|
|
87
|
+
never replays a change published earlier; Programs request the current
|
|
88
|
+
snapshot explicitly when they need one. `WritableTheme` adds asynchronous
|
|
89
|
+
authority to replace the value — a read-only environment exposes `Theme`,
|
|
90
|
+
while an authorized environment may expose `WritableTheme` without altering
|
|
91
|
+
the shared lifecycle.
|
|
92
|
+
|
|
93
|
+
`Colorable`, `Sizable`, `Shapeable`, `Variantable`, and `Elevatable` are
|
|
94
|
+
independent element capabilities whose concrete value vocabularies are defined
|
|
95
|
+
separately. An element composes only the capabilities it actually supports.
|
|
96
|
+
|
|
97
|
+
These contracts contain no React types, component names, or runtime `Theme`
|
|
98
|
+
authority. Environment and interface SDKs build those concerns on top of the
|
|
99
|
+
same neutral lifecycle and derivations.
|
|
100
|
+
|
|
101
|
+
## Messaging primitives
|
|
102
|
+
|
|
103
|
+
`Subscribable` is the independent receiving capability, providing the
|
|
17
104
|
contracts for `subscribe()`, `waitFor()`, `events()`, and `observe()`.
|
|
18
105
|
`Publishable` independently provides `publish()`. `Askable` extends
|
|
19
|
-
`Publishable` with `ask()`,
|
|
20
|
-
published to.
|
|
21
|
-
|
|
106
|
+
`Publishable` with `ask()`, since every target that can be asked can also be
|
|
107
|
+
published to. Both operations accept a single payload, which is `undefined`
|
|
108
|
+
when omitted. A type may implement or compose only the capabilities it needs —
|
|
109
|
+
the ability to publish does not imply the ability to subscribe.
|
|
22
110
|
|
|
23
|
-
|
|
24
|
-
`Askable.timeout()` creates an immutable deadline view
|
|
25
|
-
`waitFor()` and `waitReady()` accept a deadline directly. `events()`
|
|
26
|
-
long-lived iterator with a
|
|
27
|
-
|
|
28
|
-
become ready and waiting for the eventual
|
|
111
|
+
The contracts specify a ten-second default SDK deadline for finite asynchronous
|
|
112
|
+
operations. `Askable.timeout()` creates an immutable deadline view scoped to
|
|
113
|
+
`ask()`; `waitFor()` and `waitReady()` accept a deadline directly. `events()`
|
|
114
|
+
is specified as a long-lived iterator with a queue capacity of `64` by default,
|
|
115
|
+
while `Infinity` removes that bound. A single ask deadline covers both waiting
|
|
116
|
+
for its current Server incarnation to become ready and waiting for the eventual
|
|
117
|
+
answer. Environment SDKs implement these guarantees.
|
|
29
118
|
|
|
30
|
-
Every persistent registration returns its
|
|
119
|
+
Every persistent registration returns its own cleanup function:
|
|
31
120
|
|
|
32
121
|
```ts
|
|
33
122
|
const stop = target.subscribe("event", handler)
|
|
34
123
|
stop()
|
|
35
124
|
```
|
|
36
125
|
|
|
37
|
-
There are no separate `unsubscribe()` or `unobserve()` methods and no
|
|
126
|
+
There are no separate `unsubscribe()` or `unobserve()` methods, and no
|
|
38
127
|
one-time subscription operation. Observation APIs such as `observeAsks()` and
|
|
39
|
-
`observeAnswers()` follow the same returned-cleanup
|
|
128
|
+
`observeAnswers()` follow the same returned-cleanup convention.
|
|
40
129
|
|
|
41
130
|
```ts
|
|
42
131
|
import type { Subscribable } from "@phreshos/core"
|
|
@@ -57,78 +146,143 @@ target.subscribe("exit", message => {
|
|
|
57
146
|
```
|
|
58
147
|
|
|
59
148
|
Known messages are inferred from the target. An explicit generic or callback
|
|
60
|
-
annotation may narrow that message, but an incompatible replacement is
|
|
61
|
-
error. `observe()` receives a `Capture` containing only the facts
|
|
62
|
-
every Subscribable
|
|
63
|
-
sender or destination.
|
|
64
|
-
|
|
65
|
-
An unparameterized Channel or traffic surface accepts
|
|
66
|
-
names with an `unknown` payload. Supplying an event
|
|
67
|
-
and their payloads
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
`
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
149
|
+
annotation may narrow that message further, but an incompatible replacement is
|
|
150
|
+
a type error. `observe()` receives a `Capture` containing only the facts
|
|
151
|
+
guaranteed by every `Subscribable`: `event` and `message`. It makes no
|
|
152
|
+
assumption about a sender or destination.
|
|
153
|
+
|
|
154
|
+
An unparameterized Endpoint, Channel, or traffic surface accepts
|
|
155
|
+
application-defined event names with an `unknown` payload. Supplying an event
|
|
156
|
+
map narrows both the names and their payloads, and names outside that map are
|
|
157
|
+
then rejected. `events()` applies the same message inference and narrowing
|
|
158
|
+
rules, exposing a named event as an `AsyncIterableIterator`.
|
|
159
|
+
|
|
160
|
+
## Endpoints, Channels, and traffic
|
|
161
|
+
|
|
162
|
+
`Endpoint` is the shared base of `Server` and `Client`. It functions as both
|
|
163
|
+
an address and a source: `endpoint.publish()` sends directly to it, while
|
|
164
|
+
`endpoint.subscribe()` and `endpoint.observe()` follow destinationless events
|
|
165
|
+
emitted by it. `Server` additionally composes `Askable`.
|
|
166
|
+
|
|
167
|
+
The contextual `Channel` is the executing Endpoint's inward boundary.
|
|
168
|
+
Subscriptions receive events explicitly addressed to it, delivered as a
|
|
169
|
+
`ChannelMessage` containing the otherwise unknown sender. `channel.publish()`
|
|
170
|
+
emits outward from that executing Endpoint without naming a destination.
|
|
171
|
+
|
|
172
|
+
Directed inspection remains deliberately separate, exposed as
|
|
173
|
+
`endpoint.traffic`. Because the Endpoint handle already identifies the source,
|
|
174
|
+
ordinary traffic messages contain only the destination and payload; Channel
|
|
175
|
+
emissions never enter this surface. Every traffic surface exposes
|
|
176
|
+
`observeAsks()`, since either Endpoint kind may originate a question. A
|
|
177
|
+
Server's traffic additionally exposes `observeAnswers()`, since only a Server
|
|
85
178
|
can originate an answer. These captures include their event, correlation ID,
|
|
86
179
|
destination, and question payload or answer `Outcome`.
|
|
87
180
|
|
|
88
181
|
Every Endpoint exposes `exists()`, `start()`, and `stop()`. Endpoint lifecycle
|
|
89
|
-
is observed through
|
|
90
|
-
|
|
91
|
-
|
|
182
|
+
is observed through `endpointStart` and `endpointStop` at Process, Program,
|
|
183
|
+
and Server Host scope. A start delivers the permanent `Server | Client`
|
|
184
|
+
handle; a stop delivers that same permanent handle directly. Every scope
|
|
185
|
+
receives the same canonical Endpoint instance, allowing comparison by
|
|
186
|
+
identity. Neither lifecycle event wraps the Endpoint or carries process-exit
|
|
187
|
+
details, and Endpoint subscriptions themselves carry only application events
|
|
188
|
+
emitted by that Endpoint.
|
|
92
189
|
|
|
93
190
|
`Server` and `Client` are public, logic-free Endpoint specializations. Server
|
|
94
|
-
adds
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
191
|
+
adds request-response `ask()` and answer-traffic observation. Client owns two
|
|
192
|
+
permanent, synchronous capability objects: `traffic` for communication and
|
|
193
|
+
`window` for presentation. Accessing either object performs no operation and
|
|
194
|
+
receives no data — their methods and subscriptions are the explicit
|
|
195
|
+
operations.
|
|
196
|
+
|
|
197
|
+
## Ownership hierarchy
|
|
198
|
+
|
|
199
|
+
`Program` and `Process` complete the ownership hierarchy. `Program`,
|
|
200
|
+
`Process`, `Endpoint`, `Server`, and `Client` are real runtime classes,
|
|
201
|
+
usable for identity and `instanceof` checks. Their capability properties are
|
|
202
|
+
interfaces: `client.traffic` and `client.window`, in particular, have no
|
|
203
|
+
runtime class identity of their own. Core domain constructors are protected —
|
|
204
|
+
environment SDKs supply the authoritative handles backed by their respective
|
|
205
|
+
boundaries while reusing these exact Core constructors.
|
|
206
|
+
|
|
207
|
+
Core also owns the common launch, geometry, lifecycle-message, `ChannelMessage`,
|
|
208
|
+
`ChannelCapture`, `TrafficMessage`, and `TrafficCapture` types used by both
|
|
105
209
|
environments.
|
|
106
210
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
211
|
+
## Window placement
|
|
212
|
+
|
|
213
|
+
Window placement is expressed through two deliberately separate contracts.
|
|
214
|
+
Authoring `Layer` contains only `under`, `window`, and `over`, so that
|
|
215
|
+
Program declarations and Client launch overrides cannot request system-owned
|
|
216
|
+
placement. Runtime `WindowLayer` adds `wallpaper`, allowing `window.layer()`
|
|
217
|
+
to report the truth for a wallpaper Window without making that layer
|
|
218
|
+
constructible from Program code. `Window` has no identity or lifecycle apart
|
|
219
|
+
from its Client; its stable capability addresses the Client's current, live
|
|
220
|
+
presentation state and rejects reads or mutations while that Client is
|
|
221
|
+
absent.
|
|
222
|
+
|
|
223
|
+
Core also defines the independent, environment-neutral `FileWallpaper` and
|
|
224
|
+
`DesktopWallpaper` contracts. The desktop variant additionally accepts a
|
|
225
|
+
Program and the deliberately narrow `WallpaperLaunch`, containing only `name`,
|
|
226
|
+
`server`, the Client's initial `location`, and immutable Process `options`.
|
|
227
|
+
These contracts describe capability and data shape only — they contain no
|
|
228
|
+
persistence, upload, Process creation, or rendering implementation.
|
|
229
|
+
|
|
230
|
+
## Window Surface
|
|
231
|
+
|
|
232
|
+
`client.window.surface` addresses the optional host-rendered material belonging
|
|
233
|
+
to one Window. Its source of truth is authoritative, server-owned Window state,
|
|
234
|
+
not iframe state. `snapshot()` explicitly reads the current target, while the
|
|
235
|
+
ordinary `change` subscription receives only replacements published after that
|
|
236
|
+
subscription exists. A `null` target means no Surface exists in the render
|
|
237
|
+
tree.
|
|
238
|
+
|
|
239
|
+
Only Windows currently occupying the `under` or `over` layer may call `set()`
|
|
240
|
+
or `remove()`; `window` and `wallpaper` layers reject those operations. Calling
|
|
241
|
+
`set()` without settings creates a sharp, fully opaque Surface. Settings may
|
|
242
|
+
select opacity from zero to one, a nonnegative pixel radius, a scale level, or
|
|
243
|
+
`"full"`, and an optional transaction containing a duration from zero through
|
|
244
|
+
60,000 milliseconds and a stable named or cubic Bézier easing. Zero opacity
|
|
245
|
+
retains the Surface node; only `remove()` returns the authoritative target
|
|
246
|
+
immediately to `null`. The server validates settings, and the desktop animates
|
|
247
|
+
from the rendered values to each new target.
|
|
248
|
+
|
|
249
|
+
## Window geometry
|
|
250
|
+
|
|
251
|
+
Window geometry follows one public grammar. A `Value` is either a finite
|
|
252
|
+
pixel number or a linear relative expression such as `"1/2"`, `"50% + 10"`, or
|
|
253
|
+
`"30% + 20 * 2"`. `isRelativeValue()` validates that grammar, and
|
|
254
|
+
`parseRelativeValue()` reduces it to a single relative coefficient and pixel
|
|
255
|
+
offset. The CLI, runtime validation, and desktop layout all consume this one
|
|
256
|
+
Core definition rather than maintaining separate parsers.
|
|
257
|
+
|
|
258
|
+
## Process parentage
|
|
259
|
+
|
|
260
|
+
Process parentage belongs to `Process`, not to contextual SDK state. Each
|
|
261
|
+
live Process retains only a handle to its immediate parent. `process.parent()`
|
|
262
|
+
returns `null` when no accessible parent handle exists, and does not preserve
|
|
263
|
+
historical lineage: calling it through an exited Process handle, or after the
|
|
264
|
+
retained parent has disappeared, rejects outright, since the represented
|
|
265
|
+
Process no longer exists. `current.parent()` flattens this operation
|
|
266
|
+
contextually but does not itself own the relationship.
|
|
114
267
|
|
|
115
268
|
Client traversal is structurally confined to its current Program. A
|
|
116
|
-
cross-Program parent handle is never supplied to the
|
|
117
|
-
at `null`. A fabricated or otherwise unauthorized Process handle is
|
|
118
|
-
indistinguishable from a nonexistent Process and every operation
|
|
119
|
-
rejects accordingly.
|
|
269
|
+
cross-Program parent handle is never supplied to the Client, so traversal
|
|
270
|
+
stops at `null`. A fabricated or otherwise unauthorized Process handle is
|
|
271
|
+
indistinguishable from a nonexistent Process, and every operation performed
|
|
272
|
+
through it rejects accordingly.
|
|
120
273
|
|
|
121
274
|
## Program configuration
|
|
122
275
|
|
|
123
|
-
Core is also the single source of truth for the authoring contract consumed
|
|
124
|
-
the CLI. `defineConfig()` provides contextual typing for
|
|
125
|
-
returns the description unchanged:
|
|
276
|
+
Core is also the single source of truth for the authoring contract consumed
|
|
277
|
+
by the CLI. `defineConfig()` provides contextual typing for
|
|
278
|
+
`phresh.config.ts` and returns the description unchanged:
|
|
126
279
|
|
|
127
280
|
```ts
|
|
128
281
|
import { defineConfig } from "@phreshos/core"
|
|
129
282
|
|
|
130
283
|
export default defineConfig({
|
|
131
284
|
identity: "my-program",
|
|
285
|
+
icon: "./icon.png",
|
|
132
286
|
server: {
|
|
133
287
|
location: "./dist/server",
|
|
134
288
|
startCommand: "node main.js",
|
|
@@ -146,9 +300,22 @@ export default defineConfig({
|
|
|
146
300
|
})
|
|
147
301
|
```
|
|
148
302
|
|
|
149
|
-
The declaration must
|
|
150
|
-
remain authoring metadata; the CLI derives the appropriate runtime
|
|
151
|
-
for each mode.
|
|
303
|
+
The declaration must include a Server, a Client, or both. Development
|
|
304
|
+
settings remain authoring metadata; the CLI derives the appropriate runtime
|
|
305
|
+
description for each mode. The optional `icon` field names a single PNG
|
|
306
|
+
source — packaging and installation normalize it to `icon.png`, while hosting
|
|
307
|
+
derives the system's fixed presentation sizes.
|
|
308
|
+
|
|
309
|
+
Every Program also exposes its guaranteed icon without revealing hosting or
|
|
310
|
+
filesystem details:
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
const icon = await program.icon() // medium PNG Blob
|
|
314
|
+
const large = await program.icon("large") // small, medium, or large
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
This method always returns an `image/png` `Blob`. When no icon has been
|
|
318
|
+
authored, the system returns its default through the same operation.
|
|
152
319
|
|
|
153
320
|
## Program-owned resources
|
|
154
321
|
|
|
@@ -157,3 +324,7 @@ filesystem-like `data` and `cache`, a key-value `store`, read-only SQL `logs`,
|
|
|
157
324
|
and a writable SQLite `database`. The Server SDK refines its filesystem areas
|
|
158
325
|
with `path()` and safe `resolve()` access; these host filesystem paths are
|
|
159
326
|
structurally absent from the Client SDK.
|
|
327
|
+
|
|
328
|
+
## License
|
|
329
|
+
|
|
330
|
+
Licensed under the [MIT License](LICENSE). Copyright © 2026 Zohayr SLILEH.
|
package/dist/askable.d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { Publishable } from "./publishable.js";
|
|
2
|
+
import type { Timeoutable } from "./timeout.js";
|
|
2
3
|
/** An immutable Askable view using one caller-selected deadline. */
|
|
3
4
|
export interface TimedAskable {
|
|
5
|
+
/** Sends a question with an `undefined` payload and waits within the selected deadline. */
|
|
6
|
+
ask<Answer = unknown>(event: string): Promise<Answer>;
|
|
4
7
|
/** Sends one question and waits within the selected deadline. */
|
|
5
8
|
ask<Answer = unknown, Payload = unknown>(event: string, payload: Payload): Promise<Answer>;
|
|
6
9
|
}
|
|
7
10
|
/** A publishing target that can also receive a question and return an answer. */
|
|
8
|
-
export interface Askable<Events extends object = {}, Fallback = unknown> extends Publishable<Events, Fallback> {
|
|
11
|
+
export interface Askable<Events extends object = {}, Fallback = unknown> extends Publishable<Events, Fallback>, Timeoutable<TimedAskable> {
|
|
9
12
|
/**
|
|
10
13
|
* Sends one question payload to this target and waits for its answer.
|
|
11
14
|
*
|
|
@@ -16,6 +19,7 @@ export interface Askable<Events extends object = {}, Fallback = unknown> extends
|
|
|
16
19
|
* readiness and the answer. The boundary cannot infer whether an answerer
|
|
17
20
|
* exists, so a ready unanswered question waits for that deadline.
|
|
18
21
|
*/
|
|
22
|
+
ask<Answer = unknown>(event: string): Promise<Answer>;
|
|
19
23
|
ask<Answer = unknown, Payload = unknown>(event: string, payload: Payload): Promise<Answer>;
|
|
20
24
|
/** Returns an immutable view whose `ask()` uses this deadline in milliseconds. */
|
|
21
25
|
timeout(milliseconds: number): TimedAskable;
|
package/dist/channel.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Endpoint } from "./endpoint.js";
|
|
2
|
+
import type { Publishable } from "./publishable.js";
|
|
2
3
|
import type { Captures, Subscribable } from "./subscribable.js";
|
|
3
4
|
/** One application value arriving through the current Endpoint's Channel. */
|
|
4
5
|
export type ChannelMessage<Payload = unknown, From = Endpoint> = Readonly<{
|
|
@@ -14,7 +15,7 @@ export type ChannelEvents<Events extends object, From = Endpoint> = {
|
|
|
14
15
|
type ChannelFallback<Events extends object, From> = keyof Events extends never ? ChannelMessage<unknown, From> : never;
|
|
15
16
|
/** Every application event observable through a Channel. */
|
|
16
17
|
export type ChannelCapture<Events extends object = {}, From = Endpoint> = Captures<ChannelEvents<Events, From>, ChannelFallback<Events, From>>;
|
|
17
|
-
/**
|
|
18
|
-
export interface Channel<Events extends object = {}, From = Endpoint> extends Subscribable<ChannelEvents<Events, From>, ChannelFallback<Events, From
|
|
18
|
+
/** Addressed input and destinationless output for the executing Endpoint. */
|
|
19
|
+
export interface Channel<Events extends object = {}, From = Endpoint> extends Subscribable<ChannelEvents<Events, From>, ChannelFallback<Events, From>>, Publishable {
|
|
19
20
|
}
|
|
20
21
|
export {};
|
package/dist/client.d.ts
CHANGED
|
@@ -2,18 +2,18 @@ import { Endpoint, type EndpointTraffic } from "./endpoint.js";
|
|
|
2
2
|
import type { LaunchClient } from "./launch.js";
|
|
3
3
|
import type { Server } from "./server.js";
|
|
4
4
|
import type { Window } from "./window.js";
|
|
5
|
-
/**
|
|
5
|
+
/** Directed communication originating from one Client. */
|
|
6
6
|
export interface ClientTraffic<Events extends object = {}, To = Endpoint, AskTo = Server> extends EndpointTraffic<Events, To, AskTo> {
|
|
7
7
|
}
|
|
8
8
|
/** The client Endpoint of a Process. */
|
|
9
9
|
export declare class Client<Events extends object = {}> extends Endpoint<Events> {
|
|
10
|
-
constructor();
|
|
10
|
+
protected constructor();
|
|
11
11
|
}
|
|
12
12
|
export interface Client<Events extends object = {}> {
|
|
13
|
-
/**
|
|
13
|
+
/** Directed communication originating from this Client. */
|
|
14
14
|
readonly traffic: ClientTraffic<Events>;
|
|
15
|
+
/** Presentation capability permanently owned by this Client handle. */
|
|
16
|
+
readonly window: Window;
|
|
15
17
|
/** Starts a fresh Client and Window using optional Process-local overrides. */
|
|
16
18
|
start(overrides?: LaunchClient): Promise<void>;
|
|
17
|
-
/** Returns the Window owned by this live Client. */
|
|
18
|
-
window(): Promise<Window>;
|
|
19
19
|
}
|
package/dist/color.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Semantic treatments derived from one explicit CSS color. */
|
|
2
|
+
export type ColorLevel = "subtle" | "soft" | "base" | "strong" | "intense";
|
|
3
|
+
/** Complete color scale derived from one explicit CSS color. */
|
|
4
|
+
export type ColorScale = Readonly<Record<ColorLevel, string>>;
|
|
5
|
+
/**
|
|
6
|
+
* Derives a balanced color scale while preserving the supplied color as its
|
|
7
|
+
* exact base. CSS performs the mixing in OKLCH, so every valid CSS color can be
|
|
8
|
+
* the source without the system maintaining a second palette.
|
|
9
|
+
*/
|
|
10
|
+
export declare function color(value: string): ColorScale;
|
package/dist/color.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derives a balanced color scale while preserving the supplied color as its
|
|
3
|
+
* exact base. CSS performs the mixing in OKLCH, so every valid CSS color can be
|
|
4
|
+
* the source without the system maintaining a second palette.
|
|
5
|
+
*/
|
|
6
|
+
export function color(value) {
|
|
7
|
+
return Object.freeze({
|
|
8
|
+
subtle: `color-mix(in oklch, ${value} 25%, white)`,
|
|
9
|
+
soft: `color-mix(in oklch, ${value} 60%, white)`,
|
|
10
|
+
base: value,
|
|
11
|
+
strong: `color-mix(in oklch, ${value} 82%, black)`,
|
|
12
|
+
intense: `color-mix(in oklch, ${value} 68%, black)`
|
|
13
|
+
});
|
|
14
|
+
}
|
package/dist/config.d.ts
CHANGED
|
@@ -52,30 +52,41 @@ type Description = Readonly<{
|
|
|
52
52
|
version?: string;
|
|
53
53
|
/** Short human-readable explanation of what the Program does. */
|
|
54
54
|
description?: string;
|
|
55
|
-
/**
|
|
55
|
+
/**
|
|
56
|
+
* Markdown file describing only the Program-owned API contract.
|
|
57
|
+
* System access, Endpoint, and event mechanics belong to system documentation.
|
|
58
|
+
*/
|
|
56
59
|
apiDocs?: string;
|
|
57
|
-
/**
|
|
58
|
-
|
|
60
|
+
/** PNG source between 128 and 2,048 pixels per side and no larger than 5 MiB. */
|
|
61
|
+
icon?: string;
|
|
59
62
|
/** Command run before production start, installation, and packaging. */
|
|
60
63
|
buildCommand?: string;
|
|
61
64
|
}>;
|
|
65
|
+
type ServerProgramConfig = Description & Readonly<{
|
|
66
|
+
/** Server declaration for this Program. */
|
|
67
|
+
server: ServerConfig;
|
|
68
|
+
/** Optional Client declaration for this Program. */
|
|
69
|
+
client?: ClientConfig;
|
|
70
|
+
}>;
|
|
71
|
+
type ClientProgramConfig = Description & Readonly<{
|
|
72
|
+
/** Optional Server declaration for this Program. */
|
|
73
|
+
server?: ServerConfig;
|
|
74
|
+
/** Client declaration for this Program. */
|
|
75
|
+
client: ClientConfig;
|
|
76
|
+
}>;
|
|
62
77
|
/**
|
|
63
78
|
* The authoring description read from `phresh.config.ts`.
|
|
64
79
|
*
|
|
65
80
|
* A Program must declare a Server, a Client, or both.
|
|
66
81
|
*/
|
|
67
|
-
export type Config =
|
|
68
|
-
server: ServerConfig;
|
|
69
|
-
client?: ClientConfig;
|
|
70
|
-
}> | Readonly<{
|
|
71
|
-
server?: ServerConfig;
|
|
72
|
-
client: ClientConfig;
|
|
73
|
-
}>);
|
|
82
|
+
export type Config = ServerProgramConfig | ClientProgramConfig;
|
|
74
83
|
/**
|
|
75
84
|
* Defines a Program authoring description with contextual typing.
|
|
76
85
|
*
|
|
77
86
|
* This helper performs no work and returns the supplied description unchanged.
|
|
78
87
|
* The CLI validates and derives it for development, production, or packaging.
|
|
79
88
|
*/
|
|
80
|
-
export declare function defineConfig
|
|
89
|
+
export declare function defineConfig(config: ServerProgramConfig): Config;
|
|
90
|
+
/** Defines a Program authoring description with contextual typing. */
|
|
91
|
+
export declare function defineConfig(config: ClientProgramConfig): Config;
|
|
81
92
|
export {};
|
package/dist/config.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Defines a Program authoring description with contextual typing.
|
|
3
|
-
*
|
|
4
|
-
* This helper performs no work and returns the supplied description unchanged.
|
|
5
|
-
* The CLI validates and derives it for development, production, or packaging.
|
|
6
|
-
*/
|
|
7
1
|
export function defineConfig(config) {
|
|
8
2
|
return config;
|
|
9
3
|
}
|
package/dist/endpoint.d.ts
CHANGED
|
@@ -34,20 +34,21 @@ export type AskCapture<Payload = unknown, To = Server> = Readonly<{
|
|
|
34
34
|
export type AskObserver<Payload = unknown, To = Server> = (capture: AskCapture<Payload, To>) => unknown;
|
|
35
35
|
/** Every ordinary publication observable in traffic from one Endpoint. */
|
|
36
36
|
export type TrafficCapture<Events extends object = {}, To = Endpoint> = Captures<TrafficEvents<Events, To>, TrafficFallback<Events, To>>;
|
|
37
|
-
/**
|
|
37
|
+
/** Directed communication originating from one Endpoint. */
|
|
38
38
|
export interface EndpointTraffic<Events extends object = {}, To = Endpoint, AskTo = Server> extends Subscribable<TrafficEvents<Events, To>, TrafficFallback<Events, To>> {
|
|
39
39
|
/** Observes questions originating from this Endpoint. */
|
|
40
40
|
observeAsks<Payload = unknown>(observer: AskObserver<Payload, AskTo>): Cleanup;
|
|
41
41
|
}
|
|
42
42
|
/** The shared Process endpoint represented by Server and Client. */
|
|
43
43
|
export declare class Endpoint<Events extends object = {}> {
|
|
44
|
-
constructor();
|
|
44
|
+
protected constructor();
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
/** An Endpoint address that can also be followed as a destinationless source. */
|
|
47
|
+
export interface Endpoint<Events extends object = {}> extends Publishable, Subscribable<Events, keyof Events extends never ? unknown : never> {
|
|
48
|
+
/** Directed communication originating from this Endpoint. */
|
|
48
49
|
readonly traffic: EndpointTraffic<Events>;
|
|
49
50
|
/** Returns the Process that owns this Endpoint. */
|
|
50
|
-
process(): Process
|
|
51
|
+
process(): Promise<Process>;
|
|
51
52
|
/** Returns whether this Endpoint currently has a live incarnation. */
|
|
52
53
|
exists(): Promise<boolean>;
|
|
53
54
|
/**
|
package/dist/launch.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export type Value = number | string;
|
|
1
|
+
import type { Value } from "./value.js";
|
|
3
2
|
/** A Window's top-left position. */
|
|
4
3
|
export type Position = Readonly<{
|
|
5
4
|
/** Horizontal position. */
|
|
@@ -20,16 +19,25 @@ export type Layer = "window" | "under" | "over";
|
|
|
20
19
|
export declare const layers: readonly Layer[];
|
|
21
20
|
/** Per-Process overrides used when starting a Client and its Window. */
|
|
22
21
|
export type LaunchClient = Readonly<{
|
|
22
|
+
/** Initial Window size for this Process. */
|
|
23
23
|
size?: Size;
|
|
24
|
+
/** Initial Window position for this Process. */
|
|
24
25
|
position?: Position;
|
|
26
|
+
/** Structurally isolated layer containing this Process's Window. */
|
|
25
27
|
layer?: Layer;
|
|
28
|
+
/** Initial page beneath the Client's declared location scope. */
|
|
26
29
|
location?: string;
|
|
30
|
+
/** Whether the Window initially opens minimized. */
|
|
27
31
|
minimize?: boolean;
|
|
28
32
|
}>;
|
|
29
33
|
/** Initial endpoint selection and immutable options for one Process. */
|
|
30
34
|
export type Launch = Readonly<{
|
|
35
|
+
/** Optional meaningful name unique among this Program's live Processes. */
|
|
31
36
|
name?: string;
|
|
37
|
+
/** Whether to start the declared Server. Uses its declaration when omitted. */
|
|
32
38
|
server?: boolean;
|
|
39
|
+
/** Whether and how to start the declared Client. Uses its declaration when omitted. */
|
|
33
40
|
client?: boolean | LaunchClient;
|
|
41
|
+
/** Immutable string options readable by the created Process. */
|
|
34
42
|
options?: Readonly<Record<string, string>>;
|
|
35
43
|
}>;
|