@wyndlass/app-sdk 0.0.0 → 1.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 (75) hide show
  1. package/README.md +212 -1
  2. package/cli/app-package.mjs +111 -0
  3. package/cli/commands.mjs +133 -0
  4. package/cli/main.mjs +73 -0
  5. package/cli/package.mjs +119 -0
  6. package/cli/preview.mjs +142 -0
  7. package/cli/zip.mjs +63 -0
  8. package/dist/contract/app-contract.d.ts +221 -0
  9. package/dist/contract/app-contract.js +6 -0
  10. package/dist/contract/app-definition.d.ts +155 -0
  11. package/dist/contract/app-definition.js +3 -0
  12. package/dist/contract/data-answer.d.ts +40 -0
  13. package/dist/contract/data-answer.js +3 -0
  14. package/dist/contract/data-calendar.d.ts +57 -0
  15. package/dist/contract/data-calendar.js +3 -0
  16. package/dist/contract/data-news.d.ts +29 -0
  17. package/dist/contract/data-news.js +3 -0
  18. package/dist/contract/data-quotes.d.ts +75 -0
  19. package/dist/contract/data-quotes.js +3 -0
  20. package/dist/contract/data-series.d.ts +51 -0
  21. package/dist/contract/data-series.js +3 -0
  22. package/dist/contract/data-snapshot.d.ts +30 -0
  23. package/dist/contract/data-snapshot.js +3 -0
  24. package/dist/contract/data-weather.d.ts +421 -0
  25. package/dist/contract/data-weather.js +3 -0
  26. package/dist/contract/player-api-event.d.ts +253 -0
  27. package/dist/contract/player-api-event.js +3 -0
  28. package/dist/contract/player-api-status.d.ts +178 -0
  29. package/dist/contract/player-api-status.js +3 -0
  30. package/dist/easing.d.ts +16 -0
  31. package/dist/easing.js +71 -0
  32. package/dist/index.d.ts +94 -0
  33. package/dist/index.js +218 -0
  34. package/dist/preview/frame/frame.js +2 -0
  35. package/dist/preview/frame/index.html +12 -0
  36. package/dist/preview/index.html +40 -0
  37. package/dist/preview/page.js +7 -0
  38. package/dist/qr.d.ts +5 -0
  39. package/dist/qr.js +14 -0
  40. package/dist/react.d.ts +52 -0
  41. package/dist/react.js +149 -0
  42. package/package.json +83 -4
  43. package/protocol/app-definition.schema.json +435 -0
  44. package/protocol/app-packages.json +172 -0
  45. package/protocol/common.schema.json +197 -0
  46. package/protocol/samples/calendar.json +63 -0
  47. package/protocol/samples/events/app.command.json +14 -0
  48. package/protocol/samples/events/item.end.json +13 -0
  49. package/protocol/samples/events/item.start.json +18 -0
  50. package/protocol/samples/events/state.changed.json +11 -0
  51. package/protocol/samples/news.json +37 -0
  52. package/protocol/samples/player-status.json +58 -0
  53. package/protocol/samples/weather.json +59 -0
  54. package/skill/wyndlass-app/SKILL.md +90 -0
  55. package/skill/wyndlass-app/references/contract.md +91 -0
  56. package/skill/wyndlass-app/references/mcp.md +79 -0
  57. package/skill/wyndlass-app/references/templates.md +38 -0
  58. package/templates/react/AGENTS.md +17 -0
  59. package/templates/react/README.md +23 -0
  60. package/templates/react/app.json +14 -0
  61. package/templates/react/gitignore +2 -0
  62. package/templates/react/package.json +22 -0
  63. package/templates/react/src/app.css +7 -0
  64. package/templates/react/src/app.tsx +39 -0
  65. package/templates/react/src/env.d.ts +13 -0
  66. package/templates/react/tsconfig.json +13 -0
  67. package/templates/vanilla/AGENTS.md +17 -0
  68. package/templates/vanilla/README.md +23 -0
  69. package/templates/vanilla/app.json +14 -0
  70. package/templates/vanilla/gitignore +2 -0
  71. package/templates/vanilla/package.json +18 -0
  72. package/templates/vanilla/src/app.css +7 -0
  73. package/templates/vanilla/src/app.ts +59 -0
  74. package/templates/vanilla/src/env.d.ts +13 -0
  75. package/templates/vanilla/tsconfig.json +12 -0
package/package.json CHANGED
@@ -1,8 +1,87 @@
1
1
  {
2
2
  "name": "@wyndlass/app-sdk",
3
- "version": "0.0.0",
4
- "description": "A placeholder for Wyndlass's app SDK. Its first release is 1.0.0.",
3
+ "version": "1.1.0",
4
+ "description": "Build apps for Wyndlass's screens: web components on the app contract (Player API 2), with the runtime Wyndlass's own apps use.",
5
+ "keywords": [
6
+ "wyndlass",
7
+ "digital-signage",
8
+ "signage",
9
+ "web-components"
10
+ ],
5
11
  "license": "MIT",
6
12
  "author": "Northwynd Labs LLC",
7
- "files": ["README.md", "LICENSE"]
8
- }
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/NorthwyndLabs/wyndlass.git",
16
+ "directory": "app-sdk"
17
+ },
18
+ "type": "module",
19
+ "sideEffects": false,
20
+ "bin": {
21
+ "wyndlass-app": "./cli/main.mjs"
22
+ },
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.js"
27
+ },
28
+ "./qr": {
29
+ "types": "./dist/qr.d.ts",
30
+ "import": "./dist/qr.js"
31
+ },
32
+ "./react": {
33
+ "types": "./dist/react.d.ts",
34
+ "import": "./dist/react.js"
35
+ },
36
+ "./app-definition.schema.json": "./protocol/app-definition.schema.json",
37
+ "./common.schema.json": "./protocol/common.schema.json"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "cli",
42
+ "templates",
43
+ "skill",
44
+ "protocol",
45
+ "README.md",
46
+ "LICENSE"
47
+ ],
48
+ "engines": {
49
+ "node": ">=20"
50
+ },
51
+ "dependencies": {
52
+ "acorn": "8.19.0",
53
+ "ajv": "8.17.1",
54
+ "ajv-formats": "3.0.1",
55
+ "esbuild": "^0.28.2",
56
+ "qrcode-generator": "2.0.4"
57
+ },
58
+ "peerDependencies": {
59
+ "react": ">=18",
60
+ "react-dom": ">=18"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "react": {
64
+ "optional": true
65
+ },
66
+ "react-dom": {
67
+ "optional": true
68
+ }
69
+ },
70
+ "devDependencies": {
71
+ "@types/node": "22",
72
+ "@types/react": "19.3.0",
73
+ "@types/react-dom": "19.3.0",
74
+ "playwright-core": "1.63.0",
75
+ "react": "19.3.0",
76
+ "react-dom": "19.3.0",
77
+ "tsx": "^4.23.15",
78
+ "typescript": "5.9.3"
79
+ },
80
+ "scripts": {
81
+ "copy-protocol": "node scripts/copy-protocol.mjs",
82
+ "typecheck": "tsc -p tsconfig.json && tsc -p preview/tsconfig.json",
83
+ "build": "node scripts/copy-protocol.mjs --check && tsc -p tsconfig.build.json && node scripts/build-preview.mjs",
84
+ "test": "pnpm build && node --import tsx --test --test-force-exit test/*.test.ts",
85
+ "check": "node scripts/copy-protocol.mjs --check && pnpm typecheck"
86
+ }
87
+ }
@@ -0,0 +1,435 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.wyndlass.ai/protocol/v0/app-definition.schema.json",
4
+ "title": "App definition",
5
+ "description": "The YAML definition of a web component app (scoping doc 7.8). Drives the designer's property panel, the catalog and the MCP tools.",
6
+ "type": "object",
7
+ "required": [
8
+ "id",
9
+ "version",
10
+ "name",
11
+ "element"
12
+ ],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "id": {
16
+ "type": "string",
17
+ "pattern": "^[a-z][a-z0-9]*(\\.[a-z][a-z0-9-]*)+$",
18
+ "description": "Reverse-domain id, e.g. com.wyndlass.weather. com.wyndlass. is Wyndlass's own: an app an organization imports may not use it (WP-0100)."
19
+ },
20
+ "version": {
21
+ "$ref": "common.schema.json#/$defs/semver"
22
+ },
23
+ "name": {
24
+ "type": "string",
25
+ "minLength": 1,
26
+ "maxLength": 80
27
+ },
28
+ "description": {
29
+ "type": "string",
30
+ "maxLength": 500
31
+ },
32
+ "element": {
33
+ "type": "string",
34
+ "pattern": "^[a-z][a-z0-9]*-[a-z0-9-]+$",
35
+ "description": "The element's name. From Player API 2 (WP-0100) the host defines the module's default export under this name, a hyphen and a suffix of its own, so it is the readable part of the tag. Wyndlass's apps also define it themselves, for players older than that."
36
+ },
37
+ "params": {
38
+ "type": "object",
39
+ "propertyNames": {
40
+ "pattern": "^[a-z][a-zA-Z0-9]*$"
41
+ },
42
+ "additionalProperties": {
43
+ "$ref": "#/$defs/param"
44
+ }
45
+ },
46
+ "properties": {
47
+ "type": "object",
48
+ "additionalProperties": false,
49
+ "properties": {
50
+ "resizable": {
51
+ "type": "boolean"
52
+ },
53
+ "minDuration": {
54
+ "type": "string",
55
+ "pattern": "^[0-9]+(ms|s|m)$"
56
+ },
57
+ "offline": {
58
+ "type": "boolean"
59
+ },
60
+ "transparent": {
61
+ "type": "boolean"
62
+ },
63
+ "aspectRatio": {
64
+ "type": "string",
65
+ "pattern": "^[0-9]+:[0-9]+$"
66
+ }
67
+ }
68
+ },
69
+ "capabilities": {
70
+ "type": "object",
71
+ "additionalProperties": false,
72
+ "properties": {
73
+ "network": {
74
+ "type": "array",
75
+ "items": {
76
+ "type": "string",
77
+ "maxLength": 253
78
+ }
79
+ },
80
+ "sensors": {
81
+ "description": "Sensors the app reads on the screen. `impressions`: the live, anonymous feed of the people at the screen, where its site measures them (WP-0105): context.impressions.",
82
+ "type": "array",
83
+ "items": {
84
+ "type": "string",
85
+ "maxLength": 64
86
+ }
87
+ },
88
+ "audio": {
89
+ "type": "boolean"
90
+ },
91
+ "peers": {
92
+ "type": "boolean"
93
+ },
94
+ "player": {
95
+ "enum": [
96
+ "read",
97
+ "control"
98
+ ],
99
+ "description": "What the app may do with the player's controller (ADR 0050): read its properties and events (read, the default), or also command playback, audio and display (control). The CMS shows it when the app is added."
100
+ }
101
+ }
102
+ },
103
+ "bindings": {
104
+ "type": "array",
105
+ "items": {
106
+ "type": "string",
107
+ "maxLength": 256
108
+ }
109
+ },
110
+ "slots": {
111
+ "type": "object",
112
+ "description": "Named binding slots (ADR 0053, decision 8; DES-AP-01): each a field the app shows, mapped to a table column in a layout's binding. A layout's binding.fields names these.",
113
+ "propertyNames": {
114
+ "pattern": "^[a-z][a-zA-Z0-9]*$"
115
+ },
116
+ "additionalProperties": {
117
+ "type": "object",
118
+ "required": [
119
+ "label",
120
+ "type"
121
+ ],
122
+ "additionalProperties": false,
123
+ "properties": {
124
+ "label": {
125
+ "type": "string",
126
+ "maxLength": 80
127
+ },
128
+ "type": {
129
+ "enum": [
130
+ "text",
131
+ "number",
132
+ "currency",
133
+ "date",
134
+ "datetime",
135
+ "image",
136
+ "url",
137
+ "boolean"
138
+ ],
139
+ "description": "What the column must hold."
140
+ },
141
+ "required": {
142
+ "type": "boolean"
143
+ },
144
+ "help": {
145
+ "type": "string",
146
+ "maxLength": 300
147
+ }
148
+ }
149
+ }
150
+ },
151
+ "animation": {
152
+ "type": "object",
153
+ "additionalProperties": false,
154
+ "description": "The presets the app's enter and exit hooks take (ADR 0053, decision 8; DES-AH-01 to 07). An app without them is animated as one box.",
155
+ "properties": {
156
+ "enter": {
157
+ "type": "array",
158
+ "items": {
159
+ "type": "string",
160
+ "pattern": "^[a-z][a-z0-9-]{0,31}$"
161
+ },
162
+ "uniqueItems": true,
163
+ "description": "Presets its enter hook plays (fade, slide, typewriter...)."
164
+ },
165
+ "exit": {
166
+ "type": "array",
167
+ "items": {
168
+ "type": "string",
169
+ "pattern": "^[a-z][a-z0-9-]{0,31}$"
170
+ },
171
+ "uniqueItems": true,
172
+ "description": "Presets its exit hook plays."
173
+ },
174
+ "stagger": {
175
+ "type": "boolean",
176
+ "description": "Its items can enter one after another (DES-AN-06)."
177
+ },
178
+ "pages": {
179
+ "type": "boolean",
180
+ "description": "It pages through its items, playing exit and enter at each page (DES-DB-13): its page count comes from the snapshot the layout started with."
181
+ }
182
+ }
183
+ },
184
+ "data": {
185
+ "type": "array",
186
+ "uniqueItems": true,
187
+ "description": "The data service's sources it reads (ADR 0069): weather, news.",
188
+ "items": {
189
+ "type": "string",
190
+ "pattern": "^[a-z][a-z0-9-]{0,31}$"
191
+ }
192
+ },
193
+ "events": {
194
+ "type": "object",
195
+ "additionalProperties": false,
196
+ "properties": {
197
+ "emits": {
198
+ "type": "array",
199
+ "items": {
200
+ "type": "string",
201
+ "maxLength": 128
202
+ }
203
+ },
204
+ "consumes": {
205
+ "type": "array",
206
+ "items": {
207
+ "type": "string",
208
+ "maxLength": 128
209
+ }
210
+ }
211
+ }
212
+ },
213
+ "mobile": {
214
+ "type": "object",
215
+ "additionalProperties": false,
216
+ "properties": {
217
+ "mode": {
218
+ "enum": [
219
+ "render",
220
+ "snapshot",
221
+ "hidden"
222
+ ]
223
+ }
224
+ }
225
+ },
226
+ "locales": {
227
+ "type": "array",
228
+ "items": {
229
+ "$ref": "common.schema.json#/$defs/locale"
230
+ }
231
+ }
232
+ },
233
+ "$defs": {
234
+ "param": {
235
+ "type": "object",
236
+ "required": [
237
+ "type"
238
+ ],
239
+ "additionalProperties": false,
240
+ "properties": {
241
+ "type": {
242
+ "enum": [
243
+ "string",
244
+ "text",
245
+ "number",
246
+ "boolean",
247
+ "enum",
248
+ "color",
249
+ "font",
250
+ "media",
251
+ "location",
252
+ "datetime",
253
+ "duration",
254
+ "url",
255
+ "datatable",
256
+ "column",
257
+ "secret",
258
+ "json"
259
+ ],
260
+ "description": "A param's kind. A font param's value is a typography object (layout.schema.json#/$defs/typography): a family with its weight, style, decoration, letter case and spacing, line height, shadow and scale."
261
+ },
262
+ "label": {
263
+ "type": "string",
264
+ "maxLength": 80
265
+ },
266
+ "default": {},
267
+ "values": {
268
+ "type": "array",
269
+ "minItems": 1,
270
+ "items": {
271
+ "$ref": "#/$defs/paramValue"
272
+ },
273
+ "description": "On an enum, its choices. On any other type, suggestions the designer offers, while any valid value is still allowed (WP-0098). Each is a plain value, or labeled: shown by its label, under its group."
274
+ },
275
+ "group": {
276
+ "type": "string",
277
+ "maxLength": 64
278
+ },
279
+ "required": {
280
+ "type": "boolean"
281
+ },
282
+ "min": {
283
+ "type": "number"
284
+ },
285
+ "max": {
286
+ "type": "number"
287
+ },
288
+ "step": {
289
+ "type": "number",
290
+ "exclusiveMinimum": 0
291
+ },
292
+ "help": {
293
+ "type": "string",
294
+ "maxLength": 300
295
+ },
296
+ "advanced": {
297
+ "type": "boolean"
298
+ },
299
+ "when": {
300
+ "type": "object",
301
+ "minProperties": 1,
302
+ "maxProperties": 8,
303
+ "propertyNames": {
304
+ "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
305
+ },
306
+ "additionalProperties": {
307
+ "$ref": "#/$defs/paramTest"
308
+ },
309
+ "description": "When the param applies (WP-0068 part f, after gadget.yaml's depends): each key names another param of this app, and its test must hold. A param that does not apply is not shown in the designer and is not required; its value is kept."
310
+ }
311
+ },
312
+ "if": {
313
+ "properties": {
314
+ "type": {
315
+ "const": "enum"
316
+ }
317
+ }
318
+ },
319
+ "then": {
320
+ "required": [
321
+ "values"
322
+ ]
323
+ }
324
+ },
325
+ "paramValue": {
326
+ "description": "A value as a param's values list it (WP-0098): a string, number or boolean, or labeled ({ value, label, group }) for the designer to show by its label, under its group.",
327
+ "if": {
328
+ "type": "object"
329
+ },
330
+ "then": {
331
+ "type": "object",
332
+ "required": [
333
+ "value",
334
+ "label"
335
+ ],
336
+ "additionalProperties": false,
337
+ "properties": {
338
+ "value": {
339
+ "anyOf": [
340
+ { "type": "string" },
341
+ { "type": "number" },
342
+ { "type": "boolean" }
343
+ ]
344
+ },
345
+ "label": {
346
+ "type": "string",
347
+ "minLength": 1,
348
+ "maxLength": 80
349
+ },
350
+ "group": {
351
+ "type": "string",
352
+ "minLength": 1,
353
+ "maxLength": 64
354
+ }
355
+ }
356
+ },
357
+ "else": {
358
+ "anyOf": [
359
+ { "type": "string" },
360
+ { "type": "number" },
361
+ { "type": "boolean" }
362
+ ]
363
+ }
364
+ },
365
+ "paramTest": {
366
+ "type": "object",
367
+ "additionalProperties": false,
368
+ "minProperties": 1,
369
+ "description": "A test of another param's value (WP-0068 part f): every one given must hold. Values compare as text.",
370
+ "properties": {
371
+ "anyOf": {
372
+ "type": "array",
373
+ "minItems": 1,
374
+ "maxItems": 50,
375
+ "items": {
376
+ "anyOf": [
377
+ {
378
+ "type": "string"
379
+ },
380
+ {
381
+ "type": "number"
382
+ },
383
+ {
384
+ "type": "boolean"
385
+ }
386
+ ]
387
+ },
388
+ "description": "Its value is one of these."
389
+ },
390
+ "allOf": {
391
+ "type": "array",
392
+ "minItems": 1,
393
+ "maxItems": 50,
394
+ "items": {
395
+ "anyOf": [
396
+ {
397
+ "type": "string"
398
+ },
399
+ {
400
+ "type": "number"
401
+ },
402
+ {
403
+ "type": "boolean"
404
+ }
405
+ ]
406
+ },
407
+ "description": "Its value, a list, holds every one of these."
408
+ },
409
+ "noneOf": {
410
+ "type": "array",
411
+ "minItems": 1,
412
+ "maxItems": 50,
413
+ "items": {
414
+ "anyOf": [
415
+ {
416
+ "type": "string"
417
+ },
418
+ {
419
+ "type": "number"
420
+ },
421
+ {
422
+ "type": "boolean"
423
+ }
424
+ ]
425
+ },
426
+ "description": "Its value is none of these."
427
+ },
428
+ "set": {
429
+ "type": "boolean",
430
+ "description": "true: it has a value; false: it has none (absent, empty text, or an empty list)."
431
+ }
432
+ }
433
+ }
434
+ }
435
+ }