@appstrata/dev 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +164 -0
  2. package/dist/completion-notification.d.ts +22 -0
  3. package/dist/completion-notification.d.ts.map +1 -0
  4. package/dist/completion-notification.js +184 -0
  5. package/dist/completion-notification.js.map +1 -0
  6. package/dist/dev-overlay.css +450 -0
  7. package/dist/dev-overlay.d.ts +56 -0
  8. package/dist/dev-overlay.d.ts.map +1 -0
  9. package/dist/dev-overlay.js +371 -0
  10. package/dist/dev-overlay.js.map +1 -0
  11. package/dist/index.d.ts +16 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +22 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/intercepting-transport.d.ts +11 -0
  16. package/dist/intercepting-transport.d.ts.map +1 -0
  17. package/dist/intercepting-transport.js +31 -0
  18. package/dist/intercepting-transport.js.map +1 -0
  19. package/dist/load-config.d.ts +42 -0
  20. package/dist/load-config.d.ts.map +1 -0
  21. package/dist/load-config.js +87 -0
  22. package/dist/load-config.js.map +1 -0
  23. package/dist/logging-hmr.d.ts +20 -0
  24. package/dist/logging-hmr.d.ts.map +1 -0
  25. package/dist/logging-hmr.js +28 -0
  26. package/dist/logging-hmr.js.map +1 -0
  27. package/dist/mock-init.d.ts +9 -0
  28. package/dist/mock-init.d.ts.map +1 -0
  29. package/dist/mock-init.js +171 -0
  30. package/dist/mock-init.js.map +1 -0
  31. package/dist/mock-player.d.ts +117 -0
  32. package/dist/mock-player.d.ts.map +1 -0
  33. package/dist/mock-player.js +132 -0
  34. package/dist/mock-player.js.map +1 -0
  35. package/dist/mock-services.d.ts +32 -0
  36. package/dist/mock-services.d.ts.map +1 -0
  37. package/dist/mock-services.js +141 -0
  38. package/dist/mock-services.js.map +1 -0
  39. package/dist/player/index.html +22 -0
  40. package/dist/player/main.d.ts +10 -0
  41. package/dist/player/main.d.ts.map +1 -0
  42. package/dist/player/main.js +352 -0
  43. package/dist/player/main.js.map +1 -0
  44. package/dist/player/styles.css +80 -0
  45. package/dist/plugin.d.ts +103 -0
  46. package/dist/plugin.d.ts.map +1 -0
  47. package/dist/plugin.js +292 -0
  48. package/dist/plugin.js.map +1 -0
  49. package/dist/types.d.ts +376 -0
  50. package/dist/types.d.ts.map +1 -0
  51. package/dist/types.js +75 -0
  52. package/dist/types.js.map +1 -0
  53. package/package.json +50 -0
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # @appstrata/dev
2
+
3
+ Development tools for AppStrata Digital Signage SDK.
4
+
5
+ ## Features
6
+
7
+ - **Vite Plugin**: Automatically injects a mock player into your development environment
8
+ - **Standalone Dev Player**: HTML mock player that can host an Appstrata App in an iframe
9
+ - **Type-safe Config**: Full TypeScript support for `appstrata.config.ts`
10
+ - **HMR Support**: Config changes trigger `onContextChange` without page reload
11
+
12
+ ## Installation
13
+
14
+ > **Note:** This is a private npm package. Requires an npm access token — contact the AppStrata team to get one, then add it to your `~/.npmrc`:
15
+ >
16
+ > ```
17
+ > //registry.npmjs.org/:_authToken=YOUR_TOKEN
18
+ > ```
19
+
20
+ ```bash
21
+ npm install -D @appstrata/dev
22
+ # or
23
+ pnpm add -D @appstrata/dev
24
+ ```
25
+
26
+ ## Usage as a Vite Plugin
27
+
28
+ ### 1. Add the Vite Plugin
29
+
30
+ ```typescript
31
+ // vite.config.ts
32
+ import { defineConfig } from "vite";
33
+ import react from "@vitejs/plugin-react";
34
+ import { appstrata } from "@appstrata/dev";
35
+
36
+ export default defineConfig({
37
+ plugins: [
38
+ react(),
39
+ appstrata(),
40
+ ],
41
+ });
42
+ ```
43
+
44
+ ### 2. Create Configuration File
45
+
46
+ TypeScript (recommended — provides IDE autocomplete and type checking):
47
+
48
+ ```typescript
49
+ // appstrata.config.ts
50
+ import { defineConfig } from "@appstrata/dev";
51
+
52
+ export default defineConfig({
53
+ app: {
54
+ id: "my-signage-app",
55
+ name: "My Signage App",
56
+ version: "1.0.0",
57
+ },
58
+ dev: {
59
+ context: {
60
+ config: {
61
+ title: "Hello World",
62
+ backgroundColor: "#1a1a2e",
63
+ },
64
+ viewportWidth: 1920,
65
+ viewportHeight: 1080,
66
+ device: {
67
+ name: "Dev Display",
68
+ locale: "en-US",
69
+ },
70
+ },
71
+ capabilities: ["storage", "proxy"],
72
+ },
73
+ });
74
+ ```
75
+
76
+ Or JSON (zero setup, no dependencies needed):
77
+
78
+ ```json
79
+ // appstrata.config.json
80
+ {
81
+ "app": {
82
+ "id": "my-signage-app",
83
+ "name": "My Signage App",
84
+ "version": "1.0.0"
85
+ },
86
+ "dev": {
87
+ "context": {
88
+ "config": {
89
+ "title": "Hello World",
90
+ "backgroundColor": "#1a1a2e"
91
+ },
92
+ "viewportWidth": 1920,
93
+ "viewportHeight": 1080
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ ### 3. Run Dev Server
100
+
101
+ ```bash
102
+ npm run dev
103
+ ```
104
+
105
+ ## How It Works
106
+
107
+ The Vite plugin injects the following into your app's HTML `<head>` (via `transformIndexHtml`):
108
+
109
+ 1. **Logging IIFE** — a self-contained ES5 `<script>` that runs synchronously before any ES modules load. It reads `?log=` URL params and `<meta>` tags, configures the logging system (sinks, levels), registers global error handlers (`window.onerror`, `unhandledrejection`), and exposes `globalThis.AppStrata.createLogger`. This is the safety net: even if your app bundle fails to load, errors are visible on screen (when the overlay sink is active).
110
+
111
+ 2. **Logging meta tags** — `<meta name="appstrata:log">` (from `dev.logging` in your config) and `<meta name="appstrata:logging">` (from `app.logging.sinks`). These configure log level, active sinks, and namespace filters for the IIFE.
112
+
113
+ 3. **Mock player module** (dev server only) — `<script type="module">` that imports `mock-init.js`, which fetches your `appstrata.config.ts` context, creates a mock player via `createAppHost`, and drives the lifecycle events.
114
+
115
+ Your app's `getPlayer()` then connects to the mock player via postMessage in the same window.
116
+
117
+ ## Usage as a Standalone Player
118
+
119
+ The standalone player loads your app in an iframe, similar to how production web players work. Use this mode when you want to test the real Player-App communication boundary.
120
+
121
+ **Important:** Do not use the Vite plugin and the standalone player at the same time. The plugin injects an embedded mock player; running the standalone player on top of that would create two players competing for the same app. Either use the plugin (embedded mode) or remove/comment it out and use the standalone player.
122
+
123
+ When using the standalone player without the Vite plugin, you must include the logging IIFE in your app's HTML manually. See the [`@appstrata/web` README](../web/README.md#without-the-vite-plugin) for instructions.
124
+
125
+ ### Via CLI
126
+
127
+ ```bash
128
+ npx appstrata dev --url <app-url>
129
+ ```
130
+
131
+ This will:
132
+ 1. Start a mock player server
133
+ 2. Load your app in an iframe from the specified URL (with `?log=` params from your config)
134
+ 3. Provide the same mock capabilities as the Vite plugin
135
+ 4. Support HMR for config changes
136
+
137
+ **Options:**
138
+ - `--url <url>` - URL of your app's dev server (required)
139
+ - `--port <number>` - Port for the player server
140
+ - `--config <path>` - Path to config file (default: appstrata.config.ts)
141
+ - `--host` - Expose server on network
142
+
143
+
144
+
145
+ ## HMR (Hot Module Reload)
146
+
147
+ When you edit `appstrata.config.ts`:
148
+ 1. The player detects the change
149
+ 2. A custom HMR event is sent to the browser
150
+ 3. `host.updateContext()` is called with the new config
151
+ 4. Your app's `onContextChange` handlers fire
152
+
153
+ This lets you tweak mock config and see changes instantly.
154
+
155
+ Your app will receive:
156
+ - `context.mode === "development"`
157
+ - Mock `onInit`, `onShow`, `onStart` lifecycle events
158
+ - In-memory storage API
159
+ - Passthrough proxy API
160
+
161
+ ## License
162
+
163
+ MIT
164
+
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Shared completion notification component.
3
+ *
4
+ * Creates a dismissible notification overlay that appears when notifyComplete is called.
5
+ * Used by both the standalone player and vite plugin modes.
6
+ */
7
+ /**
8
+ * Show a completion notification.
9
+ *
10
+ * Creates and injects a notification element into the DOM that:
11
+ * - Appears in the bottom-right corner
12
+ * - Shows a checkmark, "Completed!" message, and timestamp
13
+ * - Must be manually dismissed with the close button
14
+ * - Uses inline styles to avoid conflicts with app styles
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * showCompletionNotification();
19
+ * ```
20
+ */
21
+ export declare function showCompletionNotification(): void;
22
+ //# sourceMappingURL=completion-notification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion-notification.d.ts","sourceRoot":"","sources":["../src/completion-notification.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAgLjD"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Shared completion notification component.
3
+ *
4
+ * Creates a dismissible notification overlay that appears when notifyComplete is called.
5
+ * Used by both the standalone player and vite plugin modes.
6
+ */
7
+ /**
8
+ * Show a completion notification.
9
+ *
10
+ * Creates and injects a notification element into the DOM that:
11
+ * - Appears in the bottom-right corner
12
+ * - Shows a checkmark, "Completed!" message, and timestamp
13
+ * - Must be manually dismissed with the close button
14
+ * - Uses inline styles to avoid conflicts with app styles
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * showCompletionNotification();
19
+ * ```
20
+ */
21
+ export function showCompletionNotification() {
22
+ // Check if notification already exists
23
+ const existingNotification = document.getElementById("appstrata-completion-notification");
24
+ if (existingNotification) {
25
+ // Re-trigger animation
26
+ existingNotification.style.animation = "none";
27
+ setTimeout(() => {
28
+ existingNotification.style.animation = "";
29
+ }, 10);
30
+ return;
31
+ }
32
+ // Get current time
33
+ const now = new Date();
34
+ const timeString = now.toLocaleTimeString("en-US", {
35
+ hour12: false,
36
+ hour: "2-digit",
37
+ minute: "2-digit",
38
+ second: "2-digit"
39
+ });
40
+ // Create notification container
41
+ const notification = document.createElement("div");
42
+ notification.id = "appstrata-completion-notification";
43
+ // Inline styles to avoid conflicts with app
44
+ Object.assign(notification.style, {
45
+ position: "fixed",
46
+ bottom: "20px",
47
+ right: "20px",
48
+ backgroundColor: "#16213e",
49
+ color: "#ffffff",
50
+ padding: "16px 20px",
51
+ borderRadius: "8px",
52
+ boxShadow: "0 4px 20px rgba(0, 0, 0, 0.5)",
53
+ zIndex: "999999",
54
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif",
55
+ fontSize: "14px",
56
+ display: "flex",
57
+ flexDirection: "column",
58
+ gap: "8px",
59
+ minWidth: "200px",
60
+ animation: "appstrata-notification-slide-in 0.3s ease-out",
61
+ border: "1px solid rgba(0, 212, 255, 0.2)",
62
+ });
63
+ // Create content container
64
+ const content = document.createElement("div");
65
+ Object.assign(content.style, {
66
+ display: "flex",
67
+ alignItems: "center",
68
+ gap: "12px",
69
+ });
70
+ // Checkmark icon
71
+ const icon = document.createElement("div");
72
+ icon.textContent = "✓";
73
+ Object.assign(icon.style, {
74
+ width: "24px",
75
+ height: "24px",
76
+ backgroundColor: "#00ff88",
77
+ color: "#0f0f1e",
78
+ borderRadius: "50%",
79
+ display: "flex",
80
+ alignItems: "center",
81
+ justifyContent: "center",
82
+ fontWeight: "bold",
83
+ fontSize: "16px",
84
+ flexShrink: "0",
85
+ });
86
+ // Message container
87
+ const messageContainer = document.createElement("div");
88
+ Object.assign(messageContainer.style, {
89
+ display: "flex",
90
+ flexDirection: "column",
91
+ gap: "4px",
92
+ flex: "1",
93
+ });
94
+ // Message text
95
+ const message = document.createElement("div");
96
+ message.textContent = "App completed";
97
+ Object.assign(message.style, {
98
+ fontWeight: "600",
99
+ color: "#00d4ff",
100
+ });
101
+ // Timestamp
102
+ const timestamp = document.createElement("div");
103
+ timestamp.textContent = timeString;
104
+ Object.assign(timestamp.style, {
105
+ fontSize: "12px",
106
+ opacity: "0.6",
107
+ });
108
+ // Close button
109
+ const closeButton = document.createElement("button");
110
+ closeButton.textContent = "×";
111
+ closeButton.setAttribute("aria-label", "Dismiss notification");
112
+ Object.assign(closeButton.style, {
113
+ position: "absolute",
114
+ top: "8px",
115
+ right: "8px",
116
+ background: "transparent",
117
+ border: "none",
118
+ color: "#ffffff",
119
+ fontSize: "20px",
120
+ cursor: "pointer",
121
+ padding: "0",
122
+ width: "20px",
123
+ height: "20px",
124
+ display: "flex",
125
+ alignItems: "center",
126
+ justifyContent: "center",
127
+ opacity: "0.5",
128
+ transition: "opacity 0.2s",
129
+ });
130
+ // Close button hover effect
131
+ closeButton.addEventListener("mouseenter", () => {
132
+ closeButton.style.opacity = "1";
133
+ });
134
+ closeButton.addEventListener("mouseleave", () => {
135
+ closeButton.style.opacity = "0.5";
136
+ });
137
+ // Close button click handler
138
+ const dismiss = () => {
139
+ notification.style.animation = "appstrata-notification-slide-out 0.3s ease-in";
140
+ setTimeout(() => {
141
+ notification.remove();
142
+ }, 300);
143
+ };
144
+ closeButton.addEventListener("click", dismiss);
145
+ // Assemble the notification
146
+ messageContainer.appendChild(message);
147
+ messageContainer.appendChild(timestamp);
148
+ content.appendChild(icon);
149
+ content.appendChild(messageContainer);
150
+ notification.appendChild(content);
151
+ notification.appendChild(closeButton);
152
+ // Inject CSS animations if not already present
153
+ if (!document.getElementById("appstrata-notification-styles")) {
154
+ const style = document.createElement("style");
155
+ style.id = "appstrata-notification-styles";
156
+ style.textContent = `
157
+ @keyframes appstrata-notification-slide-in {
158
+ from {
159
+ transform: translateX(400px);
160
+ opacity: 0;
161
+ }
162
+ to {
163
+ transform: translateX(0);
164
+ opacity: 1;
165
+ }
166
+ }
167
+
168
+ @keyframes appstrata-notification-slide-out {
169
+ from {
170
+ transform: translateX(0);
171
+ opacity: 1;
172
+ }
173
+ to {
174
+ transform: translateX(400px);
175
+ opacity: 0;
176
+ }
177
+ }
178
+ `;
179
+ document.head.appendChild(style);
180
+ }
181
+ // Add to DOM
182
+ document.body.appendChild(notification);
183
+ }
184
+ //# sourceMappingURL=completion-notification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion-notification.js","sourceRoot":"","sources":["../src/completion-notification.ts"],"names":[],"mappings":"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"}