@monimesl/dot-cli 0.1.0-alpha.21 → 0.1.0-alpha.23

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 (44) hide show
  1. package/dist/cli.js +42 -25
  2. package/dist/cli.js.map +1 -1
  3. package/dist/{server-B9-F93mS.js → server-DMnWDdJ6.js} +47 -34
  4. package/dist/{server-B9-F93mS.js.map → server-DMnWDdJ6.js.map} +1 -1
  5. package/dist/templates/showcase/dot.ts +9 -1
  6. package/dist/templates/showcase/pages/basics/bars/controller.ts +13 -2
  7. package/dist/templates/showcase/pages/basics/bars/state.ts +1 -0
  8. package/dist/templates/showcase/pages/basics/bars/view.dml +8 -0
  9. package/dist/templates/showcase/pages/basics/colors/controller.ts +112 -0
  10. package/dist/templates/showcase/pages/basics/colors/state.ts +17 -0
  11. package/dist/templates/showcase/pages/basics/colors/view.dml +142 -0
  12. package/dist/templates/showcase/pages/basics/concert/controller.ts +16 -0
  13. package/dist/templates/showcase/pages/basics/concert/state.ts +7 -0
  14. package/dist/templates/showcase/pages/basics/concert/view.dml +20 -0
  15. package/dist/templates/showcase/pages/basics/pick-genre/controller.ts +7 -1
  16. package/dist/templates/showcase/pages/basics/pick-genre/view.dml +1 -0
  17. package/dist/templates/showcase/pages/basics/share/concerts.ts +31 -0
  18. package/dist/templates/showcase/pages/basics/share/controller.ts +12 -0
  19. package/dist/templates/showcase/pages/basics/share/state.ts +5 -0
  20. package/dist/templates/showcase/pages/basics/share/view.dml +21 -0
  21. package/dist/templates/showcase/pages/components/styles/view.dml +1 -1
  22. package/dist/templates/showcase/pages/dash/account/controller.ts +23 -0
  23. package/dist/templates/showcase/pages/dash/account/state.ts +7 -0
  24. package/dist/templates/showcase/pages/dash/account/view.dml +23 -0
  25. package/dist/templates/showcase/pages/dash/cache/controller.ts +2 -2
  26. package/dist/templates/showcase/pages/dash/cache/view.dml +1 -1
  27. package/dist/templates/showcase/pages/dash/calls/controller.ts +14 -0
  28. package/dist/templates/showcase/pages/dash/calls/state.ts +3 -0
  29. package/dist/templates/showcase/pages/dash/calls/view.dml +15 -0
  30. package/dist/templates/showcase/pages/dash/crypto/controller.ts +34 -0
  31. package/dist/templates/showcase/pages/dash/crypto/state.ts +10 -0
  32. package/dist/templates/showcase/pages/dash/crypto/view.dml +48 -0
  33. package/dist/templates/showcase/pages/dash/files/controller.ts +0 -20
  34. package/dist/templates/showcase/pages/dash/files/state.ts +1 -2
  35. package/dist/templates/showcase/pages/dash/files/view.dml +4 -5
  36. package/dist/templates/showcase/pages/dash/media/controller.ts +29 -0
  37. package/dist/templates/showcase/pages/dash/media/state.ts +4 -0
  38. package/dist/templates/showcase/pages/dash/media/view.dml +20 -1
  39. package/dist/templates/showcase/pages/dash/secrets/view.dml +1 -1
  40. package/dist/templates/showcase/pages/dash/system/controller.ts +3 -3
  41. package/dist/templates/showcase/pages/dash/system/state.ts +2 -2
  42. package/dist/templates/showcase/pages/dash/system/view.dml +1 -1
  43. package/dist/templates/showcase/pages/index/state.ts +28 -3
  44. package/package.json +6 -6
@@ -3,4 +3,7 @@ export default {
3
3
  // The last call's outcome: the DashError's code and message, or how it ended.
4
4
  code: '',
5
5
  message: '',
6
+ // What this Dash offers, for the supports section.
7
+ apiVersions: '',
8
+ picksPhones: false,
6
9
  };
@@ -34,6 +34,21 @@
34
34
  </View>
35
35
  </View>
36
36
 
37
+ <View gap="small">
38
+ <Text variant="subtitle">supports</Text>
39
+ <Text variant="caption" tone="muted">Each call's docs say which Dash API version it came in, and dot.json's dash.minApiVersion says which one the dot needs. To use a newer call and still open on older Dash, check this.dash.supports first.</Text>
40
+ <View variant="card" gap="none">
41
+ <DetailRow label="This Dash offers" value="Dash API {{ apiVersions }}" />
42
+ <DetailRow label="contacts.pickPhone" value="{{ picksPhones ? 'Supported' : 'Not on this Dash' }}" />
43
+ </View>
44
+ </View>
45
+
46
+ <View gap="small">
47
+ <Text variant="subtitle">dash.dot.close</Text>
48
+ <Text variant="caption" tone="muted">Closes the dot, as going back from its first page does, such as once a payment is done.</Text>
49
+ <Button variant="secondary" onClick="closeDot">Close the showcase</Button>
50
+ </View>
51
+
37
52
  <View gap="small">
38
53
  <Text variant="subtitle">The last call</Text>
39
54
  <View variant="card" gap="none">
@@ -0,0 +1,34 @@
1
+ import { errorMessage } from '@monimesl/dot-runtime';
2
+
3
+ import state from './state';
4
+
5
+ export default definePage({
6
+ initialState: state,
7
+ configs: { navigationBar: { title: 'dash.crypto' } },
8
+ mutations: {
9
+ setText: (_state, event: ValueEvent) => ({ text: event.detail.value }),
10
+ setKey: (_state, event: ValueEvent) => ({ key: event.detail.value }),
11
+ // dash.utils answers at once, so even a mutation can use it.
12
+ encode: (state) => ({ encoded: dash.utils.base64.encode(state.text) }),
13
+ },
14
+ actions: {
15
+ async hash(state) {
16
+ try {
17
+ const sha256 = await this.dash.crypto.sha256(state.text);
18
+ const hmac = await this.dash.crypto.hmac('sha256', state.key, state.text);
19
+ this.setState({ sha256, hmac, note: '' });
20
+ } catch (error) {
21
+ this.setState({ note: errorMessage(error) });
22
+ }
23
+ },
24
+ async makeRandom() {
25
+ try {
26
+ const random = await this.dash.crypto.randomBytes(16);
27
+ const uuid = await this.dash.crypto.randomUUID();
28
+ this.setState({ random, uuid, note: '' });
29
+ } catch (error) {
30
+ this.setState({ note: errorMessage(error) });
31
+ }
32
+ },
33
+ },
34
+ });
@@ -0,0 +1,10 @@
1
+ export default {
2
+ text: 'Salone Sounds Live, Freetown',
3
+ key: 'shared secret',
4
+ sha256: '',
5
+ hmac: '',
6
+ random: '',
7
+ uuid: '',
8
+ encoded: '',
9
+ note: '',
10
+ };
@@ -0,0 +1,48 @@
1
+ <View>
2
+ <Text variant="title">dash.crypto</Text>
3
+ <Text>Hashes, signatures and random values, worked out on the phone. Each gives hex, or base64 with { as: 'base64' }.</Text>
4
+
5
+ <View variant="card" gap="medium">
6
+ <Input label="Text" value="{{ text }}" onChange="setText" />
7
+ <Input label="HMAC key" value="{{ key }}" onChange="setKey" />
8
+ </View>
9
+
10
+ <View gap="small">
11
+ <Text variant="subtitle">sha256 and hmac</Text>
12
+ <Text variant="caption" tone="muted">sha512 works the same way. hmac signs with a key, such as to check a message from the dot's own server.</Text>
13
+ <Button variant="secondary" onClick="hash">Hash and sign the text</Button>
14
+ <If condition="{{ sha256 }}">
15
+ <View variant="card" gap="none">
16
+ <DetailRow label="sha256" value="{{ sha256 }}" />
17
+ <DetailRow label="hmac sha256" value="{{ hmac }}" />
18
+ </View>
19
+ </If>
20
+ </View>
21
+
22
+ <View gap="small">
23
+ <Text variant="subtitle">randomBytes and randomUUID</Text>
24
+ <Text variant="caption" tone="muted">From the phone's secure random source, such as for a nonce.</Text>
25
+ <Button variant="secondary" onClick="makeRandom">Make random values</Button>
26
+ <If condition="{{ uuid }}">
27
+ <View variant="card" gap="none">
28
+ <DetailRow label="16 random bytes" value="{{ random }}" />
29
+ <DetailRow label="randomUUID" value="{{ uuid }}" />
30
+ </View>
31
+ </If>
32
+ </View>
33
+
34
+ <View gap="small">
35
+ <Text variant="subtitle">dash.utils</Text>
36
+ <Text variant="caption" tone="muted">Not Dash calls: dash.utils.base64 and dash.utils.hex run in the dot and answer at once, without await, for UTF-8 text.</Text>
37
+ <Button variant="secondary" onClick="encode">Encode the text</Button>
38
+ <If condition="{{ encoded }}">
39
+ <View variant="card" gap="none">
40
+ <DetailRow label="utils.base64.encode" value="{{ encoded }}" />
41
+ </View>
42
+ </If>
43
+ </View>
44
+
45
+ <If condition="{{ note }}">
46
+ <Notice tone="danger">{{ note }}</Notice>
47
+ </If>
48
+ </View>
@@ -1,5 +1,3 @@
1
- import { errorMessage, unlessCancelled } from '@monimesl/dot-runtime';
2
-
3
1
  import type { Archive, Song } from './state';
4
2
  import state from './state';
5
3
 
@@ -65,24 +63,6 @@ export default definePage({
65
63
  await this.dash.storage.file.remove('setlist', { recursive: true });
66
64
  await this.actions.refresh();
67
65
  },
68
- // A picked file goes when the dot closes, so it's saved into the dot's own folder.
69
- async attach() {
70
- try {
71
- // Undefined when the person closes the picker, which isn't a problem.
72
- const file = await unlessCancelled(
73
- this.dash.storage.file.pick({ types: ['application/pdf', 'image/*'] }),
74
- );
75
- if (!file) {
76
- return;
77
- }
78
- await this.dash.storage.file.createFolder('documents');
79
- await this.dash.storage.file.save(file, `documents/${file.name}`, { overwrite: true });
80
- this.setState({ attachNote: '' });
81
- await this.actions.refresh();
82
- } catch (error) {
83
- this.setState({ attachNote: errorMessage(error) });
84
- }
85
- },
86
66
  async forgetPicture() {
87
67
  await this.dash.storage.file.remove(PICTURE);
88
68
  await this.actions.refresh();
@@ -18,7 +18,6 @@ export default {
18
18
  archives: [] as Archive[],
19
19
  usage: '',
20
20
  picture: '',
21
- // Files the person attached, kept in the dot's documents folder.
21
+ // Files saved into the dot's documents folder, such as a ticket from the dash.media page.
22
22
  documents: [] as FileEntry[],
23
- attachNote: '',
24
23
  };
@@ -42,18 +42,17 @@
42
42
  </View>
43
43
 
44
44
  <View gap="small">
45
- <Text variant="subtitle">pick and save</Text>
46
- <Text variant="caption" tone="muted">pick lets the person choose a file from the phone, with the files permission. A picked file goes when the dot closes, so save copies it into the dot's folder.</Text>
45
+ <Text variant="subtitle">save</Text>
46
+ <Text variant="caption" tone="muted">A picked photo or file, or a download, goes when the dot closes. save copies it into the dot's folder to keep it. These are the tickets kept on the dash.media page.</Text>
47
47
  <View variant="card" gap="small">
48
- <Button variant="secondary" onClick="attach">Attach your concert ticket</Button>
49
48
  <For each="{{ documents }}" item="document" key="path">
50
49
  <View gap="none">
51
50
  <Text>{{ document.name }}</Text>
52
51
  <Text variant="caption" tone="muted">{{ document.path }}</Text>
53
52
  </View>
54
53
  </For>
55
- <If condition="{{ attachNote }}">
56
- <Text variant="caption" tone="muted">{{ attachNote }}</Text>
54
+ <If condition="{{ documents.length === 0 }}">
55
+ <Text variant="caption" tone="muted">None yet. On the dash.media page, attach a ticket and tap Keep it.</Text>
57
56
  </If>
58
57
  </View>
59
58
  </View>
@@ -22,6 +22,35 @@ export default definePage({
22
22
  this.setState({ note: errorMessage(error) });
23
23
  }
24
24
  },
25
+ async pickTicket() {
26
+ try {
27
+ const ticket = await unlessCancelled(
28
+ this.dash.media.pickFile({ types: ['application/pdf', 'image/*'] }),
29
+ );
30
+ if (!ticket) {
31
+ return;
32
+ }
33
+ const ticketSize = `${Math.round(ticket.size / 1024)} KB`;
34
+ this.setState({ ticket, ticketSize, ticketKept: false, note: '' });
35
+ } catch (error) {
36
+ this.setState({ note: errorMessage(error) });
37
+ }
38
+ },
39
+ // A picked file goes when the dot closes, so it's saved into the dot's own folder.
40
+ async keepTicket(state) {
41
+ if (!state.ticket) {
42
+ return;
43
+ }
44
+ try {
45
+ await this.dash.storage.file.createFolder('documents');
46
+ await this.dash.storage.file.save(state.ticket, `documents/${state.ticket.name}`, {
47
+ overwrite: true,
48
+ });
49
+ this.setState({ ticketKept: true, note: '' });
50
+ } catch (error) {
51
+ this.setState({ note: errorMessage(error) });
52
+ }
53
+ },
25
54
  async scanTicket() {
26
55
  try {
27
56
  const scanned = await unlessCancelled(this.dash.media.scanCode());
@@ -3,6 +3,10 @@ import type { DotFile } from '@monimesl/dot-runtime';
3
3
  export default {
4
4
  photo: null as DotFile | null,
5
5
  photoDetails: '',
6
+ ticket: null as DotFile | null,
7
+ ticketSize: '',
8
+ // Whether the ticket was saved into the dot's documents folder.
9
+ ticketKept: false,
6
10
  scanned: '',
7
11
  note: '',
8
12
  };
@@ -1,6 +1,6 @@
1
1
  <View>
2
2
  <Text variant="title">dash.media</Text>
3
- <Text>Photos and codes from the camera. Each needs a permission in dot.json, which Dash asks the person for the first time.</Text>
3
+ <Text>Photos, files and codes from the phone. Each needs a permission in dot.json, which Dash asks the person for the first time.</Text>
4
4
 
5
5
  <View gap="small">
6
6
  <Text variant="subtitle">pickPhoto</Text>
@@ -17,6 +17,25 @@
17
17
  </View>
18
18
  </View>
19
19
 
20
+ <View gap="small">
21
+ <Text variant="subtitle">pickFile</Text>
22
+ <Text variant="caption" tone="muted">Lets the person choose a file from the phone, of at most 25 MB, with the files permission. types narrows what they can choose, here a PDF or a picture. Like a photo, it goes when the dot closes, so keep it with dash.storage.file.save.</Text>
23
+ <View variant="card" gap="small">
24
+ <Button variant="secondary" onClick="pickTicket">Attach your concert ticket</Button>
25
+ <If condition="{{ ticket }}">
26
+ <DetailRow label="Name" value="{{ ticket.name }}" />
27
+ <DetailRow label="Size" value="{{ ticketSize }}" />
28
+ <DetailRow label="Type" value="{{ ticket.contentType }}" />
29
+ <If condition="{{ ticketKept }}">
30
+ <Text variant="caption" tone="success">Kept in documents/. The dash.storage.file page lists it.</Text>
31
+ </If>
32
+ <Else>
33
+ <Button variant="secondary" onClick="keepTicket">Keep it</Button>
34
+ </Else>
35
+ </If>
36
+ </View>
37
+ </View>
38
+
20
39
  <View gap="small">
21
40
  <Text variant="subtitle">scanCode</Text>
22
41
  <Text variant="caption" tone="muted">Opens Dash's scanner until it reads a QR code. It needs the camera permission.</Text>
@@ -1,6 +1,6 @@
1
1
  <View>
2
2
  <Text variant="title">dash.storage.secret</Text>
3
- <Text>Secrets hold sign-in tokens from the dot's own server. Dash keeps them encrypted on the phone. A dot can keep up to 8, of up to 4 KB each.</Text>
3
+ <Text>Secrets hold sign-in tokens from the dot's own server. Dash keeps them encrypted on the phone. A dot can keep up to 32, of up to 4 KB each.</Text>
4
4
 
5
5
  <View gap="small">
6
6
  <Text variant="subtitle">set, get, remove and clear</Text>
@@ -77,10 +77,10 @@ export default definePage({
77
77
  }
78
78
  },
79
79
  async toggleTorch(state) {
80
- const next = state.torch === 'on' ? 'off' : 'on';
80
+ const torchOn = !state.torchOn;
81
81
  try {
82
- await this.dash.system.torch(next);
83
- this.setState({ torch: next, note: '' });
82
+ await this.dash.system.torch(torchOn);
83
+ this.setState({ torchOn, note: '' });
84
84
  } catch (error) {
85
85
  this.setState({ note: errorMessage(error) });
86
86
  }
@@ -1,8 +1,8 @@
1
- import type { SystemInfo, TorchState, VibrationStyle } from '@monimesl/dot-runtime';
1
+ import type { SystemInfo, VibrationStyle } from '@monimesl/dot-runtime';
2
2
 
3
3
  export default {
4
4
  styles: ['light', 'medium', 'heavy', 'success', 'warning', 'error'] as VibrationStyle[],
5
- torch: 'off' as TorchState,
5
+ torchOn: false,
6
6
  info: null as SystemInfo | null,
7
7
  // The ticket's QR code shows awake and bright, so a scanner at the door reads it.
8
8
  ticketShown: false,
@@ -86,7 +86,7 @@
86
86
  <Text variant="subtitle">torch</Text>
87
87
  <Text variant="caption" tone="muted">Turns the camera's light on or off.</Text>
88
88
  <View variant="card">
89
- <Button variant="secondary" onClick="toggleTorch">{{ torch === 'on' ? 'Turn the torch off' : 'Lights up for the slow song' }}</Button>
89
+ <Button variant="secondary" onClick="toggleTorch">{{ torchOn ? 'Turn the torch off' : 'Lights up for the slow song' }}</Button>
90
90
  </View>
91
91
  </View>
92
92
 
@@ -58,9 +58,21 @@ export default {
58
58
  {
59
59
  page: 'basics/bars',
60
60
  title: "Dash's bars",
61
- covers: 'configs, setNavigationBar, setTabBar',
61
+ covers: 'configs, setNavigationBar, setTabBar, setColors',
62
62
  icon: 'settings',
63
63
  },
64
+ {
65
+ page: 'basics/colors',
66
+ title: 'Page colours',
67
+ covers: 'configs.colors, setColors, background, primary, surfaces',
68
+ icon: 'water',
69
+ },
70
+ {
71
+ page: 'basics/share',
72
+ title: 'Share links',
73
+ covers: "share, opening a link, checking a link's options",
74
+ icon: 'share',
75
+ },
64
76
  ],
65
77
  },
66
78
  {
@@ -167,7 +179,7 @@ export default {
167
179
  {
168
180
  page: 'dash/media',
169
181
  title: 'dash.media',
170
- covers: 'pickPhoto, scanCode',
182
+ covers: 'pickPhoto, pickFile, scanCode',
171
183
  icon: 'image',
172
184
  },
173
185
  {
@@ -176,6 +188,19 @@ export default {
176
188
  covers: 'pickPhone',
177
189
  icon: 'users',
178
190
  },
191
+ {
192
+ page: 'dash/account',
193
+ title: 'dash.account',
194
+ covers: 'readProfile',
195
+ icon: 'user',
196
+ },
197
+ {
198
+ page: 'dash/crypto',
199
+ title: 'dash.crypto',
200
+ covers:
201
+ 'sha256, sha512, hmac, randomBytes, randomUUID, and dash.utils for base64 and hex',
202
+ icon: 'lock',
203
+ },
179
204
  {
180
205
  page: 'dash/network',
181
206
  title: 'dash.network',
@@ -185,7 +210,7 @@ export default {
185
210
  {
186
211
  page: 'dash/files',
187
212
  title: 'dash.storage.file',
188
- covers: 'write, read, list, move, copy, pick, save',
213
+ covers: 'write, read, list, move, copy, remove, save, stat, open, usage',
189
214
  icon: 'file',
190
215
  },
191
216
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monimesl/dot-cli",
3
- "version": "0.1.0-alpha.21",
3
+ "version": "0.1.0-alpha.23",
4
4
  "description": "The dotctl command: build mini apps and run them in the simulator",
5
5
  "type": "module",
6
6
  "repository": {
@@ -24,11 +24,11 @@
24
24
  "dependencies": {
25
25
  "typescript": "^5.9.3",
26
26
  "uqr": "^0.1.3",
27
- "@monimesl/dot-core": "0.1.0-alpha.21",
28
- "@monimesl/dot-compiler": "0.1.0-alpha.21",
29
- "@monimesl/dot-script-parser": "0.1.0-alpha.21",
30
- "@monimesl/dot-dml-parser": "0.1.0-alpha.21",
31
- "@monimesl/dot-simulator": "0.1.0-alpha.21"
27
+ "@monimesl/dot-compiler": "0.1.0-alpha.23",
28
+ "@monimesl/dot-core": "0.1.0-alpha.23",
29
+ "@monimesl/dot-dml-parser": "0.1.0-alpha.23",
30
+ "@monimesl/dot-script-parser": "0.1.0-alpha.23",
31
+ "@monimesl/dot-simulator": "0.1.0-alpha.23"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/node": "^22.20.4",