@monimesl/dot-core 0.1.0-alpha.2

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 @@
1
+ # @monimesl/dot-core
@@ -0,0 +1,427 @@
1
+ //#region src/event/core.d.ts
2
+ interface DotEvent<Detail = unknown> {
3
+ readonly type: string;
4
+ readonly detail: Detail;
5
+ }
6
+ export declare function createEvent<Detail = Record<string, never>>(type: string, detail?: Detail): DotEvent<Detail>;
7
+ //#endregion
8
+ //#region src/view/component.d.ts
9
+ interface PropTypes {
10
+ string: string;
11
+ number: number;
12
+ boolean: boolean;
13
+ any: unknown;
14
+ }
15
+ type PropType = keyof PropTypes | readonly string[];
16
+ type PropValue<T extends PropType> = T extends readonly string[] ? T[number] : T extends keyof PropTypes ? PropTypes[T] : never;
17
+ /**
18
+ * - `none`: no children
19
+ * - `text`: text and inline components (such as `Text`).
20
+ * - `elements`: any components, but raw text must be wrapped in an inline component.
21
+ */
22
+ type ChildrenType = 'none' | 'text' | 'elements';
23
+ /**
24
+ * Describes a UI component independently of any renderer. The compiler checks `.dml` markup
25
+ * against it, and each renderer maps it to its own elements.
26
+ */
27
+ interface ComponentManifest<Name extends string = string, Props extends Record<string, PropType> = Record<string, PropType>, Events extends string = string, Children extends ChildrenType = ChildrenType> {
28
+ readonly name: Name;
29
+ readonly props: Props;
30
+ readonly events: readonly Events[];
31
+ readonly children: Children;
32
+ readonly inline?: boolean;
33
+ }
34
+ export declare function defineComponent<const Name extends string, const Props extends Record<string, PropType> = Record<never, PropType>, const Events extends string = never, const Children extends ChildrenType = ChildrenType>(manifest: {
35
+ name: Name;
36
+ props?: Props;
37
+ events?: readonly Events[];
38
+ children: Children;
39
+ inline?: boolean;
40
+ }): ComponentManifest<Name, Props, Events, Children>;
41
+ type EventProp<Event extends string> = `on${Capitalize<Event>}`;
42
+ export declare function eventProp<Event extends string>(event: Event): EventProp<Event>;
43
+ export declare function isEventProp(name: string): boolean;
44
+ export declare function eventName(prop: string): string;
45
+ /**
46
+ * The props a renderer's implementation of `M` receives, with `Children` as its node type. Every
47
+ * prop is optional and may be `undefined`: markup can omit it, and a binding can evaluate to
48
+ * `undefined` at runtime.
49
+ */
50
+ type PropsOf<M extends ComponentManifest, Children = never> = { [K in keyof M['props']]?: PropValue<M['props'][K]> | undefined; } & { [E in M['events'][number] as EventProp<E>]?: ((event: DotEvent) => void) | undefined; } & (M['children'] extends 'none' ? unknown : {
51
+ children?: Children | undefined;
52
+ });
53
+ type ComponentRegistry = Readonly<Record<string, ComponentManifest>>;
54
+ export declare function componentRegistry(manifests: Iterable<ComponentManifest>): ComponentRegistry;
55
+ //#endregion
56
+ //#region src/view/components/button.d.ts
57
+ export declare const Button: ComponentManifest<"Button", {
58
+ readonly variant: readonly ["primary", "secondary"];
59
+ readonly disabled: "boolean";
60
+ }, "click", "text">;
61
+ //#endregion
62
+ //#region src/view/components/image.d.ts
63
+ export declare const Image: ComponentManifest<"Image", {
64
+ readonly src: "string";
65
+ readonly alt: "string";
66
+ readonly width: "number";
67
+ readonly height: "number";
68
+ }, "load" | "error", "none">;
69
+ //#endregion
70
+ //#region src/view/components/input.d.ts
71
+ export declare const Input: ComponentManifest<"Input", {
72
+ readonly value: "string";
73
+ readonly placeholder: "string";
74
+ readonly label: "string";
75
+ readonly type: readonly ["text", "number", "email", "phone", "password"];
76
+ readonly maxLength: "number";
77
+ readonly disabled: "boolean";
78
+ }, "change" | "submit", "none">;
79
+ //#endregion
80
+ //#region src/view/components/text.d.ts
81
+ export declare const Text: ComponentManifest<"Text", {
82
+ readonly variant: readonly ["title", "body", "caption"];
83
+ }, never, "text">;
84
+ //#endregion
85
+ //#region src/view/components/view.d.ts
86
+ export declare const View: ComponentManifest<"View", {
87
+ readonly direction: readonly ["column", "row"];
88
+ readonly gap: readonly ["none", "small", "medium", "large"];
89
+ readonly align: readonly ["stretch", "start", "center", "end"];
90
+ readonly variant: readonly ["plain", "card"];
91
+ }, "tap", "elements">;
92
+ //#endregion
93
+ //#region src/view/components/index.d.ts
94
+ export declare const builtinComponents: {
95
+ readonly Button: ComponentManifest<"Button", {
96
+ readonly variant: readonly ["primary", "secondary"];
97
+ readonly disabled: "boolean";
98
+ }, "click", "text">;
99
+ readonly Image: ComponentManifest<"Image", {
100
+ readonly src: "string";
101
+ readonly alt: "string";
102
+ readonly width: "number";
103
+ readonly height: "number";
104
+ }, "load" | "error", "none">;
105
+ readonly Input: ComponentManifest<"Input", {
106
+ readonly value: "string";
107
+ readonly placeholder: "string";
108
+ readonly label: "string";
109
+ readonly type: readonly ["text", "number", "email", "phone", "password"];
110
+ readonly maxLength: "number";
111
+ readonly disabled: "boolean";
112
+ }, "change" | "submit", "none">;
113
+ readonly Text: ComponentManifest<"Text", {
114
+ readonly variant: readonly ["title", "body", "caption"];
115
+ }, never, "text">;
116
+ readonly View: ComponentManifest<"View", {
117
+ readonly direction: readonly ["column", "row"];
118
+ readonly gap: readonly ["none", "small", "medium", "large"];
119
+ readonly align: readonly ["stretch", "start", "center", "end"];
120
+ readonly variant: readonly ["plain", "card"];
121
+ }, "tap", "elements">;
122
+ };
123
+ type BuiltinComponents = typeof builtinComponents;
124
+ export declare const builtinRegistry: Readonly<Record<string, ComponentManifest<string, Record<string, PropType>, string, ChildrenType>>>;
125
+ //#endregion
126
+ //#region src/theme/theme.d.ts
127
+ /**
128
+ * Dot-wide design tokens, set in `defineDot`.
129
+ * Themes cross from the service to the webview as
130
+ * messages, so they must be serializable.
131
+ */
132
+ interface Theme {
133
+ scheme?: ColorScheme | 'system' | undefined;
134
+ colors?: ThemeColors | undefined;
135
+ radius?: number | undefined;
136
+ }
137
+ interface ThemeColors {
138
+ primary?: SchemeColor | undefined;
139
+ background?: SchemeColor | undefined;
140
+ surface?: SchemeColor | undefined;
141
+ text?: SchemeColor | undefined;
142
+ }
143
+ interface SchemeColor {
144
+ light: string;
145
+ dark: string;
146
+ }
147
+ type ColorScheme = 'light' | 'dark';
148
+ //#endregion
149
+ //#region src/host/context.d.ts
150
+ type AppState = 'active' | 'background';
151
+ interface SystemContext {
152
+ readonly scheme: ColorScheme;
153
+ readonly appState: AppState;
154
+ }
155
+ export declare const DEFAULT_SYSTEM_CONTEXT: SystemContext;
156
+ //#endregion
157
+ //#region src/host/calls.d.ts
158
+ type HostErrorCode = 'unsupported' | 'denied' | 'cancelled' | 'timeout' | 'invalid' | 'failed';
159
+ export declare class HostError extends Error {
160
+ readonly name = "HostError";
161
+ readonly code: HostErrorCode;
162
+ constructor(code: HostErrorCode, message: string);
163
+ }
164
+ interface HostCallOptions {
165
+ timeout?: number | undefined;
166
+ }
167
+ interface HostRequest<T> extends Promise<T> {
168
+ cancel(): void;
169
+ }
170
+ type HostCaller = (method: string, params: unknown, options: HostCallOptions) => HostRequest<unknown>;
171
+ export declare function connectHost(caller: HostCaller | null): void;
172
+ export declare function callHost<Result>(method: string, params: unknown, options?: HostCallOptions): HostRequest<Result>;
173
+ export declare function createHostRequest<Result>(promise: Promise<Result>, cancel?: () => void): HostRequest<Result>;
174
+ //#endregion
175
+ //#region src/page/navigation.d.ts
176
+ export declare const MAX_STACK_DEPTH = 8;
177
+ export declare function isPageId(value: string): boolean;
178
+ type PageLaunchOptions = Readonly<Record<string, string>>;
179
+ type Navigation = {
180
+ readonly action: 'push' | 'replace' | 'reset';
181
+ readonly page: string;
182
+ readonly options: PageLaunchOptions;
183
+ } | {
184
+ readonly action: 'back';
185
+ readonly delta: number;
186
+ };
187
+ interface StackEntry {
188
+ readonly instanceId: number;
189
+ readonly page: string;
190
+ readonly options: PageLaunchOptions;
191
+ }
192
+ export declare class NavigationStack {
193
+ #private;
194
+ readonly limit: number;
195
+ constructor(limit?: number);
196
+ get pages(): readonly StackEntry[];
197
+ get top(): StackEntry | undefined;
198
+ /**
199
+ * Applies a navigation, or refuses it and returns false: a push onto a full stack, or going back
200
+ * from the first page (which the host handles itself, e.g. by closing the dot).
201
+ */
202
+ apply(navigation: Navigation): boolean;
203
+ }
204
+ //#endregion
205
+ //#region src/protocol/core.d.ts
206
+ type PageState = Record<string, unknown>;
207
+ interface UILayerMessages {
208
+ connect: Record<string, never>;
209
+ load: {
210
+ instanceId: number;
211
+ page: string;
212
+ options: PageLaunchOptions;
213
+ };
214
+ unload: {
215
+ instanceId: number;
216
+ };
217
+ show: {
218
+ instanceId: number;
219
+ };
220
+ hide: {
221
+ instanceId: number;
222
+ };
223
+ event: {
224
+ instanceId: number;
225
+ handler: string;
226
+ event: DotEvent;
227
+ };
228
+ }
229
+ interface LogicLayerMessages {
230
+ setTheme: {
231
+ theme: Theme;
232
+ };
233
+ initPageState: {
234
+ instanceId: number;
235
+ state: PageState;
236
+ };
237
+ setPageState: {
238
+ instanceId: number;
239
+ patchState: PageState;
240
+ };
241
+ error: {
242
+ instanceId?: number;
243
+ message: string;
244
+ };
245
+ navigate: Navigation & {
246
+ from: number;
247
+ };
248
+ hostCall: {
249
+ id: number;
250
+ method: string;
251
+ params: unknown;
252
+ timeout?: number;
253
+ };
254
+ hostCancel: {
255
+ id: number;
256
+ };
257
+ }
258
+ interface HostLayerMessages {
259
+ syncStack: {
260
+ pages: readonly StackEntry[];
261
+ limit: number;
262
+ };
263
+ syncSystemContext: SystemContext;
264
+ hostResult: HostResult;
265
+ }
266
+ type HostResult = {
267
+ id: number;
268
+ value: unknown;
269
+ } | {
270
+ id: number;
271
+ error: {
272
+ code: HostErrorCode;
273
+ message: string;
274
+ };
275
+ };
276
+ interface Envelope<Type extends string = string, Payload = unknown> {
277
+ readonly type: Type;
278
+ readonly payload: Payload;
279
+ }
280
+ type MessageMap = object;
281
+ type MessageType<M extends MessageMap> = keyof M & string;
282
+ //#endregion
283
+ //#region src/view/renderer.d.ts
284
+ /**
285
+ * What a renderer provides to a compiled view.
286
+ * `Node` represents the target renderer's native element type (e.g., React elements).
287
+ */
288
+ interface RenderContext<Node> {
289
+ /**
290
+ * Creates the element for a component type (e.g., `<View>`, `<Text>`).
291
+ */
292
+ readonly h: (type: string, props: Record<string, unknown> | null, ...children: (Node | string)[]) => Node;
293
+ /**
294
+ * Returns a stable event callback that forwards UI events
295
+ * to the named handler defined in `controller.ts`.
296
+ */
297
+ readonly on: (handler: string) => (event: DotEvent) => void;
298
+ /**
299
+ * Converts a bound value to the text to display.
300
+ */
301
+ readonly text: (value: unknown) => string;
302
+ /**
303
+ * Renders a `<For>` control flow loop.
304
+ * - `render` produces the virtual nodes for each item in the list.
305
+ * - `key` provides a stable identity for list diffing where applicable.
306
+ */
307
+ readonly each: (items: unknown, render: (item: unknown, index: number) => (Node | string)[], key?: (item: unknown, index: number) => unknown) => Node;
308
+ }
309
+ /**
310
+ * The export of a compiled view file: a pure function of the page state that imports no renderer
311
+ * code, so any renderer can run it.
312
+ */
313
+ type ViewRender = <Node>(state: PageState, context: RenderContext<Node>) => Node[];
314
+ //#endregion
315
+ //#region src/view/values.d.ts
316
+ export declare function toText(value: unknown): string;
317
+ export declare function toList(value: unknown): readonly unknown[];
318
+ //#endregion
319
+ //#region src/source/location.d.ts
320
+ interface SourceLocation {
321
+ readonly line: number;
322
+ readonly column: number;
323
+ readonly offset: number;
324
+ }
325
+ export declare function createLocator(source: string): (offset: number) => SourceLocation;
326
+ export declare function locationAt(source: string, offset: number): SourceLocation;
327
+ export declare function locatedMessage(message: string, file?: string, location?: SourceLocation): string;
328
+ //#endregion
329
+ //#region src/source/error.d.ts
330
+ export declare class SourceError extends Error {
331
+ readonly reason: string;
332
+ readonly file: string | undefined;
333
+ readonly loc: SourceLocation | undefined;
334
+ constructor(reason: string, file?: string, location?: SourceLocation);
335
+ }
336
+ //#endregion
337
+ //#region src/event/emitter.d.ts
338
+ type Listener = (...args: never[]) => void;
339
+ export declare class EventEmitter<Events extends { [K in keyof Events]: Listener; }> {
340
+ #private;
341
+ on<K extends keyof Events>(name: K, listener: Events[K]): () => void;
342
+ emit<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): void;
343
+ }
344
+ //#endregion
345
+ //#region src/protocol/transport.d.ts
346
+ /**
347
+ * A universal bridge for sending and receiving messages,
348
+ * whether across web workers, message ports, or native app boundaries.
349
+ */
350
+ interface Transport {
351
+ post(message: unknown): void;
352
+ listen(listener: (message: unknown) => void): () => void;
353
+ }
354
+ /**
355
+ * Adapter interface for anything that acts like
356
+ * 1. a MessagePort (https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) or
357
+ * 2. a Web Worker (https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)
358
+ */
359
+ interface TransportAdapter {
360
+ postMessage(message: unknown): void;
361
+ addEventListener(type: 'message', listener: (event: {
362
+ data: unknown;
363
+ }) => void): void;
364
+ removeEventListener(type: 'message', listener: (event: {
365
+ data: unknown;
366
+ }) => void): void;
367
+ }
368
+ export declare function createAdaptorTransport(adapter: TransportAdapter): Transport;
369
+ export declare function createTransportPair(): [Transport, Transport];
370
+ //#endregion
371
+ //#region src/host/host.d.ts
372
+ declare global {
373
+ var __hostTransport: Transport | undefined;
374
+ }
375
+ export declare function hostTransport(): Transport;
376
+ //#endregion
377
+ //#region src/host/permissions.d.ts
378
+ export declare const PERMISSIONS: readonly ["account"];
379
+ type DotPermission = (typeof PERMISSIONS)[number];
380
+ export declare function isPermission(value: string): value is DotPermission;
381
+ //#endregion
382
+ //#region src/host/react.d.ts
383
+ export declare const REACT_HOST_PATH = "/__dot/react/";
384
+ export declare const REACT_HOST_MODULES: {
385
+ readonly react: "react.js";
386
+ readonly 'react/jsx-runtime': "react-jsx-runtime.js";
387
+ readonly 'react-dom/client': "react-dom-client.js";
388
+ };
389
+ export declare function reactHostUrl(dotReactVersion: string, file: string): string;
390
+ export declare function isReactCompatible(hostVersion: string, dotVersion: string): boolean;
391
+ export declare function newestReactOfMajor(versions: readonly string[], major: number): string | undefined;
392
+ //#endregion
393
+ //#region src/page/lifecycle.d.ts
394
+ interface PageHooks {
395
+ onLoad(options: PageLaunchOptions): void | Promise<void>;
396
+ onShow(): void | Promise<void>;
397
+ onHide(): void | Promise<void>;
398
+ onUnload(): void | Promise<void>;
399
+ }
400
+ interface DotHooks {
401
+ onLaunch(): void | Promise<void>;
402
+ onError(error: Error): void;
403
+ }
404
+ export declare const PAGE_HOOKS: readonly (keyof PageHooks)[];
405
+ //#endregion
406
+ //#region src/page/state.d.ts
407
+ export declare function applyChanges<T>(state: T, changes: Partial<T>): T;
408
+ //#endregion
409
+ //#region src/version/semantic-version.d.ts
410
+ export declare const SEMVER_PATTERN: RegExp;
411
+ export declare function isSemanticVersion(value: unknown): value is string;
412
+ export declare function majorVersion(version: string): number;
413
+ export declare function isVersionAtLeast(version: string, minimum: string): boolean;
414
+ export declare function compareVersions(left: string, right: string): number;
415
+ //#endregion
416
+ //#region src/messageChannel.d.ts
417
+ type MessageHandler<Payload> = (payload: Payload) => void;
418
+ export declare class MessageChannel<Outgoing extends MessageMap, Incoming extends MessageMap> {
419
+ #private;
420
+ constructor(transport: Transport);
421
+ send<T extends MessageType<Outgoing>>(type: T, payload: Outgoing[T]): void;
422
+ handle<T extends MessageType<Incoming>>(type: T, handler: MessageHandler<Incoming[T]>): MessageHandler<Incoming[T]> | undefined;
423
+ listen(onError: (error: unknown, message: Envelope) => void): () => void;
424
+ }
425
+ //#endregion
426
+ export type { AppState, BuiltinComponents, ChildrenType, ColorScheme, ComponentManifest, ComponentRegistry, DotEvent, DotHooks, DotPermission, Envelope, EventProp, HostCallOptions, HostCaller, HostErrorCode, HostLayerMessages, HostRequest, HostResult, LogicLayerMessages, MessageHandler, MessageMap, MessageType, Navigation, PageHooks, PageLaunchOptions, PageState, PropType, PropTypes, PropValue, PropsOf, RenderContext, SchemeColor, SourceLocation, StackEntry, SystemContext, Theme, ThemeColors, Transport, TransportAdapter, UILayerMessages, ViewRender };
427
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/event/core.ts","../src/view/component.ts","../src/view/components/button.ts","../src/view/components/image.ts","../src/view/components/input.ts","../src/view/components/text.ts","../src/view/components/view.ts","../src/view/components/index.ts","../src/theme/theme.ts","../src/host/context.ts","../src/host/calls.ts","../src/page/navigation.ts","../src/protocol/core.ts","../src/view/renderer.ts","../src/view/values.ts","../src/source/location.ts","../src/source/error.ts","../src/event/emitter.ts","../src/protocol/transport.ts","../src/host/host.ts","../src/host/permissions.ts","../src/host/react.ts","../src/page/lifecycle.ts","../src/page/state.ts","../src/version/semantic-version.ts","../src/messageChannel.ts"],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,445 @@
1
+ //#region src/view/component.ts
2
+ function defineComponent(manifest) {
3
+ return {
4
+ props: {},
5
+ events: [],
6
+ ...manifest
7
+ };
8
+ }
9
+ function eventProp(event) {
10
+ return `on${event.charAt(0).toUpperCase()}${event.slice(1)}`;
11
+ }
12
+ function isEventProp(name) {
13
+ const letterAfterOn = name.charAt(2);
14
+ return name.startsWith("on") && letterAfterOn >= "A" && letterAfterOn <= "Z";
15
+ }
16
+ function eventName(prop) {
17
+ const name = prop.slice(2);
18
+ return name.charAt(0).toLowerCase() + name.slice(1);
19
+ }
20
+ function componentRegistry(manifests) {
21
+ const registry = {};
22
+ for (const manifest of manifests) {
23
+ if (manifest.name in registry) throw new Error(`Component <${manifest.name}> is defined twice`);
24
+ registry[manifest.name] = manifest;
25
+ }
26
+ return registry;
27
+ }
28
+ //#endregion
29
+ //#region src/view/values.ts
30
+ function toText(value) {
31
+ switch (typeof value) {
32
+ case "string": return value;
33
+ case "number":
34
+ case "boolean":
35
+ case "bigint": return String(value);
36
+ case "object": return value === null ? "" : JSON.stringify(value);
37
+ default: return "";
38
+ }
39
+ }
40
+ function toList(value) {
41
+ if (Array.isArray(value)) return value;
42
+ if (typeof value === "object" && value !== null && Symbol.iterator in value) return Array.from(value);
43
+ return [];
44
+ }
45
+ //#endregion
46
+ //#region src/source/location.ts
47
+ function createLocator(source) {
48
+ const lineStarts = [0];
49
+ for (let index = 0; index < source.length; index++) if (source[index] === "\n") lineStarts.push(index + 1);
50
+ return (offset) => {
51
+ let low = 0;
52
+ let high = lineStarts.length - 1;
53
+ while (low < high) {
54
+ const middle = Math.floor((low + high + 1) / 2);
55
+ if (lineStarts[middle] <= offset) low = middle;
56
+ else high = middle - 1;
57
+ }
58
+ return {
59
+ line: low + 1,
60
+ column: offset - lineStarts[low] + 1,
61
+ offset
62
+ };
63
+ };
64
+ }
65
+ function locationAt(source, offset) {
66
+ return createLocator(source)(offset);
67
+ }
68
+ function locatedMessage(message, file, location) {
69
+ const where = [
70
+ file,
71
+ location?.line,
72
+ location?.column
73
+ ].filter((part) => part !== void 0).join(":");
74
+ return where ? `${where}: ${message}` : message;
75
+ }
76
+ //#endregion
77
+ //#region src/source/error.ts
78
+ var SourceError = class extends Error {
79
+ reason;
80
+ file;
81
+ loc;
82
+ constructor(reason, file, location) {
83
+ super(locatedMessage(reason, file, location));
84
+ this.reason = reason;
85
+ this.file = file;
86
+ this.loc = location;
87
+ }
88
+ };
89
+ //#endregion
90
+ //#region src/view/components/button.ts
91
+ const Button = defineComponent({
92
+ name: "Button",
93
+ props: {
94
+ variant: ["primary", "secondary"],
95
+ disabled: "boolean"
96
+ },
97
+ events: ["click"],
98
+ children: "text"
99
+ });
100
+ //#endregion
101
+ //#region src/view/components/image.ts
102
+ const Image = defineComponent({
103
+ name: "Image",
104
+ props: {
105
+ src: "string",
106
+ alt: "string",
107
+ width: "number",
108
+ height: "number"
109
+ },
110
+ events: ["load", "error"],
111
+ children: "none"
112
+ });
113
+ //#endregion
114
+ //#region src/view/components/input.ts
115
+ const Input = defineComponent({
116
+ name: "Input",
117
+ props: {
118
+ value: "string",
119
+ placeholder: "string",
120
+ label: "string",
121
+ type: [
122
+ "text",
123
+ "number",
124
+ "email",
125
+ "phone",
126
+ "password"
127
+ ],
128
+ maxLength: "number",
129
+ disabled: "boolean"
130
+ },
131
+ events: ["change", "submit"],
132
+ children: "none"
133
+ });
134
+ //#endregion
135
+ //#region src/view/components/text.ts
136
+ const Text = defineComponent({
137
+ name: "Text",
138
+ props: { variant: [
139
+ "title",
140
+ "body",
141
+ "caption"
142
+ ] },
143
+ children: "text",
144
+ inline: true
145
+ });
146
+ //#endregion
147
+ //#region src/view/components/view.ts
148
+ const View = defineComponent({
149
+ name: "View",
150
+ props: {
151
+ direction: ["column", "row"],
152
+ gap: [
153
+ "none",
154
+ "small",
155
+ "medium",
156
+ "large"
157
+ ],
158
+ align: [
159
+ "stretch",
160
+ "start",
161
+ "center",
162
+ "end"
163
+ ],
164
+ variant: ["plain", "card"]
165
+ },
166
+ events: ["tap"],
167
+ children: "elements"
168
+ });
169
+ //#endregion
170
+ //#region src/view/components/index.ts
171
+ const builtinComponents = {
172
+ Button,
173
+ Image,
174
+ Input,
175
+ Text,
176
+ View
177
+ };
178
+ const builtinRegistry = componentRegistry(Object.values(builtinComponents));
179
+ //#endregion
180
+ //#region src/event/emitter.ts
181
+ var EventEmitter = class {
182
+ #listeners = /* @__PURE__ */ new Map();
183
+ on(name, listener) {
184
+ const listeners = this.#listeners.get(name) ?? /* @__PURE__ */ new Set();
185
+ this.#listeners.set(name, listeners);
186
+ listeners.add(listener);
187
+ return () => listeners.delete(listener);
188
+ }
189
+ emit(name, ...args) {
190
+ this.#listeners.get(name)?.forEach((listener) => listener(...args));
191
+ }
192
+ };
193
+ //#endregion
194
+ //#region src/event/core.ts
195
+ function createEvent(type, detail = {}) {
196
+ return {
197
+ type,
198
+ detail
199
+ };
200
+ }
201
+ //#endregion
202
+ //#region src/host/host.ts
203
+ function hostTransport() {
204
+ const transport = globalThis.__hostTransport;
205
+ if (!transport) throw new Error("No Dot host found: expected `globalThis.__hostTransport` to be available at runtime. Dots run inside the Dash App, or a simulator via `dotctl dev`.");
206
+ return transport;
207
+ }
208
+ //#endregion
209
+ //#region src/host/context.ts
210
+ const DEFAULT_SYSTEM_CONTEXT = {
211
+ scheme: "light",
212
+ appState: "active"
213
+ };
214
+ //#endregion
215
+ //#region src/host/calls.ts
216
+ var HostError = class extends Error {
217
+ name = "HostError";
218
+ code;
219
+ constructor(code, message) {
220
+ super(message);
221
+ this.code = code;
222
+ }
223
+ };
224
+ let connectedCaller = null;
225
+ function connectHost(caller) {
226
+ connectedCaller = caller;
227
+ }
228
+ function callHost(method, params, options = {}) {
229
+ if (!connectedCaller) {
230
+ const error = new HostError("unsupported", `No host to run "${method}": host calls run in the service`);
231
+ return createHostRequest(Promise.reject(error));
232
+ }
233
+ return connectedCaller(method, params, options);
234
+ }
235
+ function createHostRequest(promise, cancel = () => {}) {
236
+ const request = promise;
237
+ request.cancel = cancel;
238
+ return request;
239
+ }
240
+ //#endregion
241
+ //#region src/host/permissions.ts
242
+ const PERMISSIONS = ["account"];
243
+ function isPermission(value) {
244
+ return PERMISSIONS.includes(value);
245
+ }
246
+ //#endregion
247
+ //#region src/version/semantic-version.ts
248
+ const SEMVER_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
249
+ function isSemanticVersion(value) {
250
+ return typeof value === "string" && SEMVER_PATTERN.test(value);
251
+ }
252
+ function majorVersion(version) {
253
+ return parseVersion(version).major;
254
+ }
255
+ function isVersionAtLeast(version, minimum) {
256
+ return compareVersions(version, minimum) >= 0;
257
+ }
258
+ function compareVersions(left, right) {
259
+ const leftVersion = parseVersion(left);
260
+ const rightVersion = parseVersion(right);
261
+ const differences = [
262
+ leftVersion.major - rightVersion.major,
263
+ leftVersion.minor - rightVersion.minor,
264
+ leftVersion.patch - rightVersion.patch
265
+ ];
266
+ for (const difference of differences) if (difference !== 0) return difference;
267
+ return comparePrereleases(leftVersion.prerelease, rightVersion.prerelease);
268
+ }
269
+ function parseVersion(version) {
270
+ const match = SEMVER_PATTERN.exec(version);
271
+ if (!match) throw new Error(`"${version}" is not a semantic version`);
272
+ const [, major, minor, patch, prerelease] = match;
273
+ return {
274
+ major: Number(major),
275
+ minor: Number(minor),
276
+ patch: Number(patch),
277
+ prerelease: prerelease === void 0 ? [] : prerelease.split(".")
278
+ };
279
+ }
280
+ function comparePrereleases(left, right) {
281
+ if (left.length === 0 || right.length === 0) return right.length - left.length;
282
+ const shared = Math.min(left.length, right.length);
283
+ for (let index = 0; index < shared; index++) {
284
+ const order = compareIdentifiers(left[index], right[index]);
285
+ if (order !== 0) return order;
286
+ }
287
+ return left.length - right.length;
288
+ }
289
+ function compareIdentifiers(left, right) {
290
+ const leftIsNumber = /^\d+$/.test(left);
291
+ const rightIsNumber = /^\d+$/.test(right);
292
+ if (leftIsNumber && rightIsNumber) return Number(left) - Number(right);
293
+ if (leftIsNumber) return -1;
294
+ if (rightIsNumber) return 1;
295
+ if (left < right) return -1;
296
+ if (left > right) return 1;
297
+ return 0;
298
+ }
299
+ //#endregion
300
+ //#region src/host/react.ts
301
+ const REACT_HOST_PATH = "/__dot/react/";
302
+ const REACT_HOST_MODULES = {
303
+ react: "react.js",
304
+ "react/jsx-runtime": "react-jsx-runtime.js",
305
+ "react-dom/client": "react-dom-client.js"
306
+ };
307
+ function reactHostUrl(dotReactVersion, file) {
308
+ return `${REACT_HOST_PATH}${majorVersion(dotReactVersion)}/${file}`;
309
+ }
310
+ function isReactCompatible(hostVersion, dotVersion) {
311
+ return majorVersion(hostVersion) === majorVersion(dotVersion) && isVersionAtLeast(hostVersion, dotVersion);
312
+ }
313
+ function newestReactOfMajor(versions, major) {
314
+ return versions.filter((version) => majorVersion(version) === major).sort(compareVersions).at(-1);
315
+ }
316
+ //#endregion
317
+ //#region src/protocol/transport.ts
318
+ function createAdaptorTransport(adapter) {
319
+ return {
320
+ post: (message) => adapter.postMessage(message),
321
+ listen(listener) {
322
+ const onMessage = (event) => listener(event.data);
323
+ adapter.addEventListener("message", onMessage);
324
+ return () => adapter.removeEventListener("message", onMessage);
325
+ }
326
+ };
327
+ }
328
+ function createTransportPair() {
329
+ const firstListeners = /* @__PURE__ */ new Set();
330
+ const secondListeners = /* @__PURE__ */ new Set();
331
+ const createSide = (ownListeners, otherListeners) => ({
332
+ post: (message) => {
333
+ const copy = JSON.parse(JSON.stringify(message));
334
+ otherListeners.forEach((listener) => listener(copy));
335
+ },
336
+ listen(listener) {
337
+ ownListeners.add(listener);
338
+ return () => ownListeners.delete(listener);
339
+ }
340
+ });
341
+ return [createSide(firstListeners, secondListeners), createSide(secondListeners, firstListeners)];
342
+ }
343
+ const PAGE_HOOKS = Object.keys({
344
+ onLoad: true,
345
+ onShow: true,
346
+ onHide: true,
347
+ onUnload: true
348
+ });
349
+ //#endregion
350
+ //#region src/page/navigation.ts
351
+ const MAX_STACK_DEPTH = 8;
352
+ const PAGE_ID = /^[A-Za-z0-9_-]+(?:\/[A-Za-z0-9_-]+)*$/;
353
+ function isPageId(value) {
354
+ return PAGE_ID.test(value);
355
+ }
356
+ var NavigationStack = class {
357
+ limit;
358
+ #pages = [];
359
+ #nextInstanceId = 1;
360
+ constructor(limit = 8) {
361
+ this.limit = limit;
362
+ }
363
+ get pages() {
364
+ return this.#pages;
365
+ }
366
+ get top() {
367
+ return this.#pages.at(-1);
368
+ }
369
+ /**
370
+ * Applies a navigation, or refuses it and returns false: a push onto a full stack, or going back
371
+ * from the first page (which the host handles itself, e.g. by closing the dot).
372
+ */
373
+ apply(navigation) {
374
+ switch (navigation.action) {
375
+ case "push":
376
+ if (this.#pages.length >= this.limit) return false;
377
+ break;
378
+ case "replace":
379
+ this.#pages.pop();
380
+ break;
381
+ case "reset":
382
+ this.#pages = [];
383
+ break;
384
+ case "back": {
385
+ const count = Math.min(navigation.delta, this.#pages.length - 1);
386
+ if (count < 1) return false;
387
+ this.#pages = this.#pages.slice(0, -count);
388
+ return true;
389
+ }
390
+ }
391
+ const { page, options } = navigation;
392
+ this.#pages = [...this.#pages, {
393
+ instanceId: this.#nextInstanceId++,
394
+ page,
395
+ options
396
+ }];
397
+ return true;
398
+ }
399
+ };
400
+ //#endregion
401
+ //#region src/page/state.ts
402
+ function applyChanges(state, changes) {
403
+ const next = { ...state };
404
+ for (const [key, value] of Object.entries(changes)) if (value !== void 0) next[key] = value;
405
+ return next;
406
+ }
407
+ //#endregion
408
+ //#region src/messageChannel.ts
409
+ var MessageChannel = class {
410
+ #transport;
411
+ #handlers = /* @__PURE__ */ new Map();
412
+ constructor(transport) {
413
+ this.#transport = transport;
414
+ }
415
+ send(type, payload) {
416
+ this.#transport.post({
417
+ type,
418
+ payload
419
+ });
420
+ }
421
+ handle(type, handler) {
422
+ const previous = this.#handlers.get(type);
423
+ this.#handlers.set(type, handler);
424
+ return previous;
425
+ }
426
+ listen(onError) {
427
+ return this.#transport.listen((rawMessage) => {
428
+ const message = rawMessage;
429
+ const handler = this.#handlers.get(message.type);
430
+ if (!handler) {
431
+ onError(/* @__PURE__ */ new Error(`No handler registered for message "${message.type}"`), message);
432
+ return;
433
+ }
434
+ try {
435
+ handler(message.payload);
436
+ } catch (error) {
437
+ onError(error, message);
438
+ }
439
+ });
440
+ }
441
+ };
442
+ //#endregion
443
+ export { Button, DEFAULT_SYSTEM_CONTEXT, EventEmitter, HostError, Image, Input, MAX_STACK_DEPTH, MessageChannel, NavigationStack, PAGE_HOOKS, PERMISSIONS, REACT_HOST_MODULES, REACT_HOST_PATH, SEMVER_PATTERN, SourceError, Text, View, applyChanges, builtinComponents, builtinRegistry, callHost, compareVersions, componentRegistry, connectHost, createAdaptorTransport, createEvent, createHostRequest, createLocator, createTransportPair, defineComponent, eventName, eventProp, hostTransport, isEventProp, isPageId, isPermission, isReactCompatible, isSemanticVersion, isVersionAtLeast, locatedMessage, locationAt, majorVersion, newestReactOfMajor, reactHostUrl, toList, toText };
444
+
445
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/view/component.ts","../src/view/values.ts","../src/source/location.ts","../src/source/error.ts","../src/view/components/button.ts","../src/view/components/image.ts","../src/view/components/input.ts","../src/view/components/text.ts","../src/view/components/view.ts","../src/view/components/index.ts","../src/event/emitter.ts","../src/event/core.ts","../src/host/host.ts","../src/host/context.ts","../src/host/calls.ts","../src/host/permissions.ts","../src/version/semantic-version.ts","../src/host/react.ts","../src/protocol/transport.ts","../src/page/lifecycle.ts","../src/page/navigation.ts","../src/page/state.ts","../src/messageChannel.ts"],"sourcesContent":["import type { DotEvent } from '../event/core';\n\nexport interface PropTypes {\n string: string;\n number: number;\n boolean: boolean;\n any: unknown;\n}\n\nexport type PropType = keyof PropTypes | readonly string[];\n\nexport type PropValue<T extends PropType> = T extends readonly string[]\n ? T[number]\n : T extends keyof PropTypes\n ? PropTypes[T]\n : never;\n\n/**\n * - `none`: no children\n * - `text`: text and inline components (such as `Text`).\n * - `elements`: any components, but raw text must be wrapped in an inline component.\n */\nexport type ChildrenType = 'none' | 'text' | 'elements';\n\n/**\n * Describes a UI component independently of any renderer. The compiler checks `.dml` markup\n * against it, and each renderer maps it to its own elements.\n */\nexport interface ComponentManifest<\n Name extends string = string,\n Props extends Record<string, PropType> = Record<string, PropType>,\n Events extends string = string,\n Children extends ChildrenType = ChildrenType,\n> {\n readonly name: Name;\n readonly props: Props;\n // Supported event names; `click` is written `onClick` in markup and received as the `onClick` prop.\n readonly events: readonly Events[];\n readonly children: Children;\n readonly inline?: boolean;\n}\n\nexport function defineComponent<\n const Name extends string,\n const Props extends Record<string, PropType> = Record<never, PropType>,\n const Events extends string = never,\n const Children extends ChildrenType = ChildrenType,\n>(manifest: {\n name: Name;\n props?: Props;\n events?: readonly Events[];\n children: Children;\n inline?: boolean;\n}): ComponentManifest<Name, Props, Events, Children> {\n return { props: {} as Props, events: [], ...manifest };\n}\n\nexport type EventProp<Event extends string> = `on${Capitalize<Event>}`;\n\nexport function eventProp<Event extends string>(event: Event): EventProp<Event> {\n return `on${event.charAt(0).toUpperCase()}${event.slice(1)}` as EventProp<Event>;\n}\n\n// Event props are `on` followed by a capital letter, like `onClick`.\nexport function isEventProp(name: string): boolean {\n const letterAfterOn = name.charAt('on'.length);\n return name.startsWith('on') && letterAfterOn >= 'A' && letterAfterOn <= 'Z';\n}\n\n// The reverse of eventProp: `onClick` -> `click`.\nexport function eventName(prop: string): string {\n const name = prop.slice('on'.length);\n return name.charAt(0).toLowerCase() + name.slice(1);\n}\n\n/**\n * The props a renderer's implementation of `M` receives, with `Children` as its node type. Every\n * prop is optional and may be `undefined`: markup can omit it, and a binding can evaluate to\n * `undefined` at runtime.\n */\nexport type PropsOf<M extends ComponentManifest, Children = never> = {\n [K in keyof M['props']]?: PropValue<M['props'][K]> | undefined;\n} & {\n [E in M['events'][number] as EventProp<E>]?: ((event: DotEvent) => void) | undefined;\n} & (M['children'] extends 'none' ? unknown : { children?: Children | undefined });\n\nexport type ComponentRegistry = Readonly<Record<string, ComponentManifest>>;\n\nexport function componentRegistry(manifests: Iterable<ComponentManifest>): ComponentRegistry {\n const registry: Record<string, ComponentManifest> = {};\n for (const manifest of manifests) {\n if (manifest.name in registry) {\n throw new Error(`Component <${manifest.name}> is defined twice`);\n }\n registry[manifest.name] = manifest;\n }\n return registry;\n}\n","export function toText(value: unknown): string {\n switch (typeof value) {\n case 'string':\n return value;\n case 'number':\n case 'boolean':\n case 'bigint':\n return String(value);\n case 'object':\n return value === null ? '' : JSON.stringify(value);\n default:\n return '';\n }\n}\n\nexport function toList(value: unknown): readonly unknown[] {\n if (Array.isArray(value)) {\n return value;\n }\n if (typeof value === 'object' && value !== null && Symbol.iterator in value) {\n return Array.from(value as Iterable<unknown>);\n }\n return [];\n}\n","export interface SourceLocation {\n readonly line: number;\n readonly column: number;\n readonly offset: number;\n}\n\n// Finds lines by binary search over their start offsets, computed once per source.\nexport function createLocator(source: string): (offset: number) => SourceLocation {\n const lineStarts = [0];\n for (let index = 0; index < source.length; index++) {\n if (source[index] === '\\n') {\n lineStarts.push(index + 1);\n }\n }\n return (offset) => {\n let low = 0;\n let high = lineStarts.length - 1;\n while (low < high) {\n const middle = Math.floor((low + high + 1) / 2);\n if (lineStarts[middle]! <= offset) {\n low = middle;\n } else {\n high = middle - 1;\n }\n }\n return { line: low + 1, column: offset - lineStarts[low]! + 1, offset };\n };\n}\n\nexport function locationAt(source: string, offset: number): SourceLocation {\n return createLocator(source)(offset);\n}\n\nexport function locatedMessage(message: string, file?: string, location?: SourceLocation): string {\n const where = [file, location?.line, location?.column]\n .filter((part) => part !== undefined)\n .join(':');\n return where ? `${where}: ${message}` : message;\n}\n","import type { SourceLocation } from './location';\nimport { locatedMessage } from './location';\n\n// A problem at a place in a source file. The message starts with `file:line:column:`\nexport class SourceError extends Error {\n readonly reason: string;\n readonly file: string | undefined;\n readonly loc: SourceLocation | undefined;\n\n constructor(reason: string, file?: string, location?: SourceLocation) {\n super(locatedMessage(reason, file, location));\n this.reason = reason;\n this.file = file;\n this.loc = location;\n }\n}\n","import { defineComponent } from '../component';\n\nexport const Button = defineComponent({\n name: 'Button',\n props: { variant: ['primary', 'secondary'], disabled: 'boolean' },\n events: ['click'],\n children: 'text',\n});\n","import { defineComponent } from '../component';\n\nexport const Image = defineComponent({\n name: 'Image',\n props: { src: 'string', alt: 'string', width: 'number', height: 'number' },\n events: ['load', 'error'],\n children: 'none',\n});\n","import { defineComponent } from '../component';\n\nexport const Input = defineComponent({\n name: 'Input',\n props: {\n value: 'string',\n placeholder: 'string',\n label: 'string',\n type: ['text', 'number', 'email', 'phone', 'password'],\n maxLength: 'number',\n disabled: 'boolean',\n },\n events: ['change', 'submit'],\n children: 'none',\n});\n","import { defineComponent } from '../component';\n\nexport const Text = defineComponent({\n name: 'Text',\n props: {\n variant: ['title', 'body', 'caption'],\n },\n children: 'text',\n inline: true,\n});\n","import { defineComponent } from '../component';\n\nexport const View = defineComponent({\n name: 'View',\n props: {\n direction: ['column', 'row'],\n gap: ['none', 'small', 'medium', 'large'],\n align: ['stretch', 'start', 'center', 'end'],\n variant: ['plain', 'card'],\n },\n events: ['tap'],\n children: 'elements',\n});\n","import { componentRegistry } from '../component';\nimport { Button } from './button';\nimport { Image } from './image';\nimport { Input } from './input';\nimport { Text } from './text';\nimport { View } from './view';\n\nexport { Button, Image, Input, Text, View };\n\nexport const builtinComponents = { Button, Image, Input, Text, View } as const;\n\nexport type BuiltinComponents = typeof builtinComponents;\n\nexport const builtinRegistry = componentRegistry(Object.values(builtinComponents));\n","type Listener = (...args: never[]) => void;\n\nexport class EventEmitter<Events extends { [K in keyof Events]: Listener }> {\n readonly #listeners = new Map<keyof Events, Set<Listener>>();\n\n on<K extends keyof Events>(name: K, listener: Events[K]): () => void {\n const listeners = this.#listeners.get(name) ?? new Set();\n this.#listeners.set(name, listeners);\n listeners.add(listener);\n return () => listeners.delete(listener);\n }\n\n emit<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): void {\n const listeners = this.#listeners.get(name) as Set<Events[K]> | undefined;\n listeners?.forEach((listener) => listener(...args));\n }\n}\n","export interface DotEvent<Detail = unknown> {\n readonly type: string;\n readonly detail: Detail;\n}\n\nexport function createEvent<Detail = Record<string, never>>(\n type: string,\n detail: Detail = {} as Detail,\n): DotEvent<Detail> {\n return { type, detail };\n}\n","import type { Transport } from '../protocol/transport';\n\ndeclare global {\n // Installed by the host (the iOS or Android app, or the browser simulator) before Dot starts.\n // noinspection ES6ConvertVarToLetConst\n var __hostTransport: Transport | undefined;\n}\n\n// The transport the host installed. Messages crossing it must be JSON-serializable.\nexport function hostTransport(): Transport {\n const transport = globalThis.__hostTransport;\n if (!transport) {\n throw new Error(\n 'No Dot host found: expected `globalThis.__hostTransport` to be available at runtime. ' +\n 'Dots run inside the Dash App, or a simulator via `dotctl dev`.',\n );\n }\n return transport;\n}\n","import type { ColorScheme } from '../theme/theme';\n\n// `background` while the person is away from Dash: in another app, on the home screen, or with the\n// phone locked.\nexport type AppState = 'active' | 'background';\n\nexport interface SystemContext {\n readonly scheme: ColorScheme;\n readonly appState: AppState;\n}\n\nexport const DEFAULT_SYSTEM_CONTEXT: SystemContext = { scheme: 'light', appState: 'active' };\n","export type HostErrorCode =\n 'unsupported' | 'denied' | 'cancelled' | 'timeout' | 'invalid' | 'failed';\n\nexport class HostError extends Error {\n override readonly name = 'HostError';\n readonly code: HostErrorCode;\n\n constructor(code: HostErrorCode, message: string) {\n super(message);\n this.code = code;\n }\n}\n\nexport interface HostCallOptions {\n timeout?: number | undefined;\n}\n\nexport interface HostRequest<T> extends Promise<T> {\n // Stops waiting: the promise rejects with `cancelled`, and the host stops the work.\n cancel(): void;\n}\n\nexport type HostCaller = (\n method: string,\n params: unknown,\n options: HostCallOptions,\n) => HostRequest<unknown>;\n\nlet connectedCaller: HostCaller | null = null;\n\n// The service connects itself when it starts\nexport function connectHost(caller: HostCaller | null): void {\n connectedCaller = caller;\n}\n\nexport function callHost<Result>(\n method: string,\n params: unknown,\n options: HostCallOptions = {},\n): HostRequest<Result> {\n if (!connectedCaller) {\n const error = new HostError(\n 'unsupported',\n `No host to run \"${method}\": host calls run in the service`,\n );\n return createHostRequest(Promise.reject(error));\n }\n return connectedCaller(method, params, options) as HostRequest<Result>;\n}\n\nexport function createHostRequest<Result>(\n promise: Promise<Result>,\n cancel: () => void = () => {},\n): HostRequest<Result> {\n const request = promise as HostRequest<Result>;\n request.cancel = cancel;\n return request;\n}\n","// What a dot may ask the person for. A dot declares each one it uses in dot.json, with the reason\n// Dash shows the person; a host method that needs one runs only once the person allows it.\n// - `account`: the Dash account the person is logged into: their username (email or phone) and\n// full name.\nexport const PERMISSIONS = ['account'] as const;\n\nexport type DotPermission = (typeof PERMISSIONS)[number];\n\nexport function isPermission(value: string): value is DotPermission {\n return (PERMISSIONS as readonly string[]).includes(value);\n}\n","// A semantic version, as https://semver.org defines it: `1.4.0`, `2.0.0-beta.1`, `1.0.0+build.7`.\nexport const SEMVER_PATTERN =\n /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$/;\n\ninterface SemanticVersion {\n readonly major: number;\n readonly minor: number;\n readonly patch: number;\n // `[\"beta\", \"1\"]` for `1.0.0-beta.1`; empty for a release.\n readonly prerelease: readonly string[];\n}\n\nexport function isSemanticVersion(value: unknown): value is string {\n return typeof value === 'string' && SEMVER_PATTERN.test(value);\n}\n\nexport function majorVersion(version: string): number {\n return parseVersion(version).major;\n}\n\n// Whether `version` is `minimum` or a later one.\nexport function isVersionAtLeast(version: string, minimum: string): boolean {\n return compareVersions(version, minimum) >= 0;\n}\n\n// Negative when `left` comes before `right`, positive when after, and 0 for the same release.\n// Build metadata, the part after `+`, does not count.\nexport function compareVersions(left: string, right: string): number {\n const leftVersion = parseVersion(left);\n const rightVersion = parseVersion(right);\n const differences = [\n leftVersion.major - rightVersion.major,\n leftVersion.minor - rightVersion.minor,\n leftVersion.patch - rightVersion.patch,\n ];\n for (const difference of differences) {\n if (difference !== 0) {\n return difference;\n }\n }\n return comparePrereleases(leftVersion.prerelease, rightVersion.prerelease);\n}\n\nfunction parseVersion(version: string): SemanticVersion {\n const match = SEMVER_PATTERN.exec(version);\n if (!match) {\n throw new Error(`\"${version}\" is not a semantic version`);\n }\n const [, major, minor, patch, prerelease] = match;\n return {\n major: Number(major),\n minor: Number(minor),\n patch: Number(patch),\n prerelease: prerelease === undefined ? [] : prerelease.split('.'),\n };\n}\n\n// A release comes after its pre-releases (`1.0.0-beta` < `1.0.0`). Between pre-releases, the first\n// identifier that differs decides; if all match, the one with fewer identifiers comes first.\nfunction comparePrereleases(left: readonly string[], right: readonly string[]): number {\n if (left.length === 0 || right.length === 0) {\n return right.length - left.length;\n }\n const shared = Math.min(left.length, right.length);\n for (let index = 0; index < shared; index++) {\n const order = compareIdentifiers(left[index]!, right[index]!);\n if (order !== 0) {\n return order;\n }\n }\n return left.length - right.length;\n}\n\n// Numbers compare as numbers and come before words, which compare as text.\nfunction compareIdentifiers(left: string, right: string): number {\n const leftIsNumber = /^\\d+$/.test(left);\n const rightIsNumber = /^\\d+$/.test(right);\n if (leftIsNumber && rightIsNumber) {\n return Number(left) - Number(right);\n }\n if (leftIsNumber) {\n return -1;\n }\n if (rightIsNumber) {\n return 1;\n }\n if (left < right) {\n return -1;\n }\n if (left > right) {\n return 1;\n }\n return 0;\n}\n","import { compareVersions, isVersionAtLeast, majorVersion } from '../version/semantic-version';\n\n// The host ships React, not each dot: every dot's webview imports these names, and an import map in\n// its index.html points them at the host's copies under `/__dot/react/<major>/`.\nexport const REACT_HOST_PATH = '/__dot/react/';\n\n// Each name a dot's webview imports React by, and the host's file for it.\nexport const REACT_HOST_MODULES = {\n react: 'react.js',\n 'react/jsx-runtime': 'react-jsx-runtime.js',\n 'react-dom/client': 'react-dom-client.js',\n} as const;\n\n// By major version only: the host serves the newest React it has with that major, so it can update\n// React within a major without dots being rebuilt.\nexport function reactHostUrl(dotReactVersion: string, file: string): string {\n return `${REACT_HOST_PATH}${majorVersion(dotReactVersion)}/${file}`;\n}\n\n// A React release only adds to its major version, so a dot runs on the same major at or above the\n// version it was built with. A different major can change or remove what the dot relies on.\nexport function isReactCompatible(hostVersion: string, dotVersion: string): boolean {\n return (\n majorVersion(hostVersion) === majorVersion(dotVersion) &&\n isVersionAtLeast(hostVersion, dotVersion)\n );\n}\n\n// The newest of `versions` with `major`, or undefined when there is none.\nexport function newestReactOfMajor(versions: readonly string[], major: number): string | undefined {\n const matching = versions.filter((version) => majorVersion(version) === major);\n return matching.sort(compareVersions).at(-1);\n}\n","/**\n * A universal bridge for sending and receiving messages,\n * whether across web workers, message ports, or native app boundaries.\n */\nexport interface Transport {\n post(message: unknown): void;\n // Returns a function that removes the listener.\n listen(listener: (message: unknown) => void): () => void;\n}\n\n/**\n * Adapter interface for anything that acts like\n * 1. a MessagePort (https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) or\n * 2. a Web Worker (https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)\n */\nexport interface TransportAdapter {\n postMessage(message: unknown): void;\n addEventListener(type: 'message', listener: (event: { data: unknown }) => void): void;\n removeEventListener(type: 'message', listener: (event: { data: unknown }) => void): void;\n}\n\nexport function createAdaptorTransport(adapter: TransportAdapter): Transport {\n return {\n post: (message) => adapter.postMessage(message),\n listen(listener) {\n const onMessage = (event: { data: unknown }) => listener(event.data);\n adapter.addEventListener('message', onMessage);\n return () => adapter.removeEventListener('message', onMessage);\n },\n };\n}\n\n// Two transports connected to each other in the same thread, for tests and single-thread setups.\nexport function createTransportPair(): [Transport, Transport] {\n type Listeners = Set<(message: unknown) => void>;\n const firstListeners: Listeners = new Set();\n const secondListeners: Listeners = new Set();\n const createSide = (ownListeners: Listeners, otherListeners: Listeners): Transport => ({\n post: (message) => {\n // Simulate cross-thread memory isolation by cloning the payload\n const copy: unknown = JSON.parse(JSON.stringify(message));\n otherListeners.forEach((listener) => listener(copy));\n },\n listen(listener) {\n ownListeners.add(listener);\n return () => ownListeners.delete(listener);\n },\n });\n return [createSide(firstListeners, secondListeners), createSide(secondListeners, firstListeners)];\n}\n","import type { PageLaunchOptions } from './navigation';\n\nexport interface PageHooks {\n onLoad(options: PageLaunchOptions): void | Promise<void>;\n onShow(): void | Promise<void>;\n onHide(): void | Promise<void>;\n onUnload(): void | Promise<void>;\n}\n\nexport interface DotHooks {\n onLaunch(): void | Promise<void>;\n onError(error: Error): void;\n}\n\n// A record rather than a list, so adding a hook to PageHooks without listing it is a type error.\nconst pageHooks: Record<keyof PageHooks, true> = {\n onLoad: true,\n onShow: true,\n onHide: true,\n onUnload: true,\n};\n\nexport const PAGE_HOOKS = Object.keys(pageHooks) as readonly (keyof PageHooks)[];\n","export const MAX_STACK_DEPTH = 8;\n\nconst PAGE_ID = /^[A-Za-z0-9_-]+(?:\\/[A-Za-z0-9_-]+)*$/;\n\nexport function isPageId(value: string): boolean {\n return PAGE_ID.test(value);\n}\n\nexport type PageLaunchOptions = Readonly<Record<string, string>>;\n\nexport type Navigation =\n | {\n readonly action: 'push' | 'replace' | 'reset';\n readonly page: string;\n readonly options: PageLaunchOptions;\n }\n | { readonly action: 'back'; readonly delta: number };\n\nexport interface StackEntry {\n readonly instanceId: number;\n readonly page: string;\n readonly options: PageLaunchOptions;\n}\n\nexport class NavigationStack {\n readonly limit: number;\n #pages: StackEntry[] = [];\n #nextInstanceId = 1;\n\n constructor(limit = MAX_STACK_DEPTH) {\n this.limit = limit;\n }\n\n get pages(): readonly StackEntry[] {\n return this.#pages;\n }\n\n get top(): StackEntry | undefined {\n return this.#pages.at(-1);\n }\n\n /**\n * Applies a navigation, or refuses it and returns false: a push onto a full stack, or going back\n * from the first page (which the host handles itself, e.g. by closing the dot).\n */\n apply(navigation: Navigation): boolean {\n switch (navigation.action) {\n case 'push':\n if (this.#pages.length >= this.limit) {\n return false;\n }\n break;\n case 'replace':\n this.#pages.pop();\n break;\n case 'reset':\n this.#pages = [];\n break;\n case 'back': {\n const count = Math.min(navigation.delta, this.#pages.length - 1);\n if (count < 1) {\n return false;\n }\n this.#pages = this.#pages.slice(0, -count);\n return true;\n }\n }\n const { page, options } = navigation;\n this.#pages = [...this.#pages, { instanceId: this.#nextInstanceId++, page, options }];\n return true;\n }\n}\n","export function applyChanges<T>(state: T, changes: Partial<T>): T {\n const next = { ...state } as Record<string, unknown>;\n for (const [key, value] of Object.entries(changes)) {\n if (value !== undefined) {\n next[key] = value;\n }\n }\n return next as T;\n}\n","import type { Transport } from './protocol/transport';\nimport type { Envelope, MessageMap, MessageType } from './protocol/core';\n\nexport type MessageHandler<Payload> = (payload: Payload) => void;\n\nexport class MessageChannel<Outgoing extends MessageMap, Incoming extends MessageMap> {\n readonly #transport: Transport;\n readonly #handlers = new Map<string, MessageHandler<never>>();\n\n constructor(transport: Transport) {\n this.#transport = transport;\n }\n\n send<T extends MessageType<Outgoing>>(type: T, payload: Outgoing[T]): void {\n this.#transport.post({ type, payload } satisfies Envelope);\n }\n\n handle<T extends MessageType<Incoming>>(\n type: T,\n handler: MessageHandler<Incoming[T]>,\n ): MessageHandler<Incoming[T]> | undefined {\n const previous = this.#handlers.get(type) as MessageHandler<Incoming[T]> | undefined;\n this.#handlers.set(type, handler);\n return previous;\n }\n\n listen(onError: (error: unknown, message: Envelope) => void): () => void {\n return this.#transport.listen((rawMessage) => {\n const message = rawMessage as Envelope;\n const handler = this.#handlers.get(message.type) as MessageHandler<unknown> | undefined;\n if (!handler) {\n onError(new Error(`No handler registered for message \"${message.type}\"`), message);\n return;\n }\n try {\n handler(message.payload);\n } catch (error) {\n onError(error, message);\n }\n });\n }\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@monimesl/dot-core",
3
+ "version": "0.1.0-alpha.2",
4
+ "description": "Dot contracts shared by every layer: protocol, transports, component manifests, view renderer",
5
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "directory": "packages/core",
9
+ "url": "git+https://github.com/monime-lab/dot.git"
10
+ },
11
+ "sideEffects": false,
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "exports": {
16
+ ".": {
17
+ "@monimesl/dot-source": "./src/index.ts",
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js",
20
+ "default": "./dist/index.js"
21
+ },
22
+ "./package.json": "./package.json"
23
+ },
24
+ "main": "./dist/index.js",
25
+ "types": "./dist/index.d.ts",
26
+ "devDependencies": {
27
+ "publint": "^0.3.24",
28
+ "rimraf": "^6.1.3",
29
+ "tsdown": "^0.23.0",
30
+ "typescript": "^5.9.3",
31
+ "vitest": "^5.0.1"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "scripts": {
37
+ "build": "tsdown",
38
+ "dev": "tsdown --watch",
39
+ "typecheck": "tsc --noEmit -p tsconfig.json",
40
+ "test": "vitest run",
41
+ "clean": "rimraf dist *.tsbuildinfo"
42
+ }
43
+ }