quote0 1.0.0-alpha.7 → 1.0.0-alpha.8

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 (56) hide show
  1. package/dist/api/base.d.mts +2 -4
  2. package/dist/api/base.d.mts.map +1 -1
  3. package/dist/api/base.mjs.map +1 -1
  4. package/dist/api/index.d.mts +8 -5
  5. package/dist/api/index.d.mts.map +1 -1
  6. package/dist/api/index.mjs +1 -1
  7. package/dist/api/index.mjs.map +1 -1
  8. package/dist/api/modules/canvas.d.mts +26 -0
  9. package/dist/api/modules/canvas.d.mts.map +1 -0
  10. package/dist/api/modules/canvas.mjs +2 -0
  11. package/dist/api/modules/canvas.mjs.map +1 -0
  12. package/dist/api/modules/content.d.mts +45 -42
  13. package/dist/api/modules/content.d.mts.map +1 -1
  14. package/dist/api/modules/content.mjs +1 -1
  15. package/dist/api/modules/content.mjs.map +1 -1
  16. package/dist/api/modules/device.d.mts +31 -9
  17. package/dist/api/modules/device.d.mts.map +1 -1
  18. package/dist/api/modules/device.mjs +1 -1
  19. package/dist/api/modules/device.mjs.map +1 -1
  20. package/dist/api/modules/timezone.d.mts +14 -0
  21. package/dist/api/modules/timezone.d.mts.map +1 -0
  22. package/dist/api/modules/timezone.mjs +2 -0
  23. package/dist/api/modules/timezone.mjs.map +1 -0
  24. package/dist/cli/app.mjs +2 -0
  25. package/dist/cli/app.mjs.map +1 -0
  26. package/dist/cli/commands/auth.mjs +2 -0
  27. package/dist/cli/commands/auth.mjs.map +1 -0
  28. package/dist/cli/commands/content.mjs +2 -0
  29. package/dist/cli/commands/content.mjs.map +1 -0
  30. package/dist/cli/commands/device.mjs +2 -0
  31. package/dist/cli/commands/device.mjs.map +1 -0
  32. package/dist/cli/commands/timezone.mjs +2 -0
  33. package/dist/cli/commands/timezone.mjs.map +1 -0
  34. package/dist/cli/context.mjs +2 -0
  35. package/dist/cli/context.mjs.map +1 -0
  36. package/dist/cli/errors.mjs +2 -0
  37. package/dist/cli/errors.mjs.map +1 -0
  38. package/dist/cli/index.mjs +2 -0
  39. package/dist/cli/index.mjs.map +1 -0
  40. package/dist/cli/output.mjs +4 -0
  41. package/dist/cli/output.mjs.map +1 -0
  42. package/dist/cli/views/AuthPrompt.mjs +2 -0
  43. package/dist/cli/views/AuthPrompt.mjs.map +1 -0
  44. package/dist/cli/views/ResultView.mjs +2 -0
  45. package/dist/cli/views/ResultView.mjs.map +1 -0
  46. package/dist/components/Container.mjs.map +1 -1
  47. package/dist/components/ListItem.mjs.map +1 -1
  48. package/dist/components/Section.mjs +1 -1
  49. package/dist/components/Section.mjs.map +1 -1
  50. package/dist/config.mjs.map +1 -1
  51. package/dist/index.d.mts +1 -1
  52. package/dist/index.mjs +1 -1
  53. package/dist/index.mjs.map +1 -1
  54. package/dist/package.mjs +1 -1
  55. package/dist/utils/ink-props-helpers.mjs.map +1 -1
  56. package/package.json +17 -15
@@ -4,9 +4,7 @@ interface BaseClientArgs {
4
4
  }
5
5
  declare class BaseClient {
6
6
  protected apiKey: string;
7
- constructor({
8
- apiKey
9
- }: BaseClientArgs);
7
+ constructor({ apiKey }: BaseClientArgs);
10
8
  static readonly API_ENDPOINT = "https://dot.mindreset.tech/api";
11
9
  protected readonly apiEndpoint = "https://dot.mindreset.tech/api";
12
10
  static readonly DISPLAY: {
@@ -17,5 +15,5 @@ declare class BaseClient {
17
15
  protected fetchApi(path: string, options?: RequestInit): Promise<unknown>;
18
16
  }
19
17
  //#endregion
20
- export { BaseClient, BaseClientArgs };
18
+ export { BaseClientArgs, BaseClient as default };
21
19
  //# sourceMappingURL=base.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.mts","names":[],"sources":["../../src/api/base.ts"],"mappings":";UAAiB,cAAA;EACf,MAAA;AAAA;AAAA,cAGI,UAAA;EAAA,UACM,MAAA;;IACI;EAAA,GAAU,cAAA;EAAA,gBAIR,YAAA;EAAA,mBACG,WAAA;EAAA,gBAEH,OAAA;;;;YAEN,aAAA,CAAc,IAAA;EAAA,UAIR,QAAA,CAAS,IAAA,UAAc,OAAA,GAAU,WAAA,GAAW,OAAA;AAAA"}
1
+ {"version":3,"file":"base.d.mts","names":[],"sources":["../../src/api/base.ts"],"mappings":";UAAiB;EACf;;cAGI;YACM;EACE,cAAE,UAAU;kBAIR;qBACG;kBAEH;;;;YAEN,cAAc;YAIR,SAAS,cAAc,UAAU,cAAW"}
@@ -1 +1 @@
1
- {"version":3,"file":"base.mjs","names":[],"sources":["../../src/api/base.ts"],"sourcesContent":["export interface BaseClientArgs {\n apiKey: string\n}\n\nclass BaseClient {\n protected apiKey: string\n constructor({ apiKey }: BaseClientArgs) {\n this.apiKey = apiKey\n }\n\n static readonly API_ENDPOINT = 'https://dot.mindreset.tech/api'\n protected readonly apiEndpoint = BaseClient.API_ENDPOINT\n\n static readonly DISPLAY = { width: 296, height: 152 }\n\n protected composeApiUrl(path: string) {\n return path.startsWith('/') ? this.apiEndpoint + path : this.apiEndpoint + '/' + path\n }\n\n protected async fetchApi(path: string, options?: RequestInit) {\n const url = this.composeApiUrl(path)\n const mergedOptions = Object.assign(\n {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + this.apiKey,\n },\n },\n options ?? {},\n )\n\n try {\n const response = await fetch(url, mergedOptions)\n\n if (response.ok) {\n return await response.json()\n } else {\n throw new Error(`API request failed with status ${response.status}: ${response.statusText}`)\n }\n } catch (error) {\n throw error\n }\n }\n}\n\nexport default BaseClient\n"],"mappings":"AAIA,IAAM,EAAN,MAAM,CAAW,CACf,OACA,YAAY,CAAE,UAA0B,CACtC,KAAK,OAAS,EAGhB,OAAgB,aAAe,iCAC/B,YAAiC,EAAW,aAE5C,OAAgB,QAAU,CAAE,MAAO,IAAK,OAAQ,IAAK,CAErD,cAAwB,EAAc,CACpC,OAAO,EAAK,WAAW,IAAI,CAAG,KAAK,YAAc,EAAO,KAAK,YAAc,IAAM,EAGnF,MAAgB,SAAS,EAAc,EAAuB,CAC5D,IAAM,EAAM,KAAK,cAAc,EAAK,CAC9B,EAAgB,OAAO,OAC3B,CACE,OAAQ,MACR,QAAS,CACP,eAAgB,mBAChB,cAAe,UAAY,KAAK,OACjC,CACF,CACD,GAAW,EAAE,CACd,CAED,GAAI,CACF,IAAM,EAAW,MAAM,MAAM,EAAK,EAAc,CAEhD,GAAI,EAAS,GACX,OAAO,MAAM,EAAS,MAAM,CAE5B,MAAU,MAAM,kCAAkC,EAAS,OAAO,IAAI,EAAS,aAAa,OAEvF,EAAO,CACd,MAAM"}
1
+ {"version":3,"file":"base.mjs","names":[],"sources":["../../src/api/base.ts"],"sourcesContent":["export interface BaseClientArgs {\n apiKey: string\n}\n\nclass BaseClient {\n protected apiKey: string\n constructor({ apiKey }: BaseClientArgs) {\n this.apiKey = apiKey\n }\n\n static readonly API_ENDPOINT = 'https://dot.mindreset.tech/api'\n protected readonly apiEndpoint = BaseClient.API_ENDPOINT\n\n static readonly DISPLAY = { width: 296, height: 152 }\n\n protected composeApiUrl(path: string) {\n return path.startsWith('/') ? this.apiEndpoint + path : this.apiEndpoint + '/' + path\n }\n\n protected async fetchApi(path: string, options?: RequestInit) {\n const url = this.composeApiUrl(path)\n const mergedOptions = Object.assign(\n {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + this.apiKey,\n },\n },\n options ?? {},\n )\n\n try {\n const response = await fetch(url, mergedOptions)\n\n if (response.ok) {\n return await response.json()\n } else {\n throw new Error(`API request failed with status ${response.status}: ${response.statusText}`)\n }\n } catch (error) {\n throw error\n }\n }\n}\n\nexport default BaseClient\n"],"mappings":"AAIA,IAAM,EAAN,MAAM,CAAW,CACf,OACA,YAAY,CAAE,UAA0B,CACtC,KAAK,OAAS,CAChB,CAEA,OAAgB,aAAe,iCAC/B,YAAiC,EAAW,aAE5C,OAAgB,QAAU,CAAE,MAAO,IAAK,OAAQ,GAAI,EAEpD,cAAwB,EAAc,CACpC,OAAO,EAAK,WAAW,GAAG,EAAI,KAAK,YAAc,EAAO,KAAK,YAAc,IAAM,CACnF,CAEA,MAAgB,SAAS,EAAc,EAAuB,CAC5D,IAAM,EAAM,KAAK,cAAc,CAAI,EAC7B,EAAgB,OAAO,OAC3B,CACE,OAAQ,MACR,QAAS,CACP,eAAgB,mBAChB,cAAe,UAAY,KAAK,MAClC,CACF,EACA,GAAW,CAAC,CACd,EAEA,GAAI,CACF,IAAM,EAAW,MAAM,MAAM,EAAK,CAAa,EAE/C,GAAI,EAAS,GACX,OAAO,MAAM,EAAS,KAAK,EAE3B,MAAU,MAAM,kCAAkC,EAAS,OAAO,IAAI,EAAS,YAAY,CAE/F,OAAS,EAAO,CACd,MAAM,CACR,CACF,CACF"}
@@ -1,11 +1,14 @@
1
- import { BaseClient, BaseClientArgs } from "./base.mjs";
2
- import { BORDER, Border, ContentModule, DITHER_KERNELS, DITHER_TYPES, DitherKernel, DitherType } from "./modules/content.mjs";
3
- import { DeviceModule } from "./modules/device.mjs";
4
-
1
+ import BaseClient, { BaseClientArgs } from "./base.mjs";
2
+ import ContentModule, { BORDER, Border, DITHER_KERNELS, DITHER_TYPES, DitherKernel, DitherType, MessageTextStyle, TASK_TYPES, TEXT_API_FONT_FAMILIES, TaskListItem, TaskType, TextApiFontFamily, TextStyle, TextStyles } from "./modules/content.mjs";
3
+ import CanvasModule, { PushCanvasOptions } from "./modules/canvas.mjs";
4
+ import DeviceModule, { DeviceSettings } from "./modules/device.mjs";
5
+ import TimezoneModule, { Timezone } from "./modules/timezone.mjs";
5
6
  //#region src/api/index.d.ts
6
7
  declare class Quote0 extends BaseClient {
7
8
  device: DeviceModule;
8
9
  content: ContentModule;
10
+ canvas: CanvasModule;
11
+ timezone: TimezoneModule;
9
12
  constructor(args: BaseClientArgs);
10
13
  readonly display: {
11
14
  width: number;
@@ -13,5 +16,5 @@ declare class Quote0 extends BaseClient {
13
16
  };
14
17
  }
15
18
  //#endregion
16
- export { BORDER, type Border, DITHER_KERNELS, DITHER_TYPES, type DitherKernel, type DitherType, Quote0 as default };
19
+ export { BORDER, type Border, DITHER_KERNELS, DITHER_TYPES, type DeviceSettings, type DitherKernel, type DitherType, type MessageTextStyle, type PushCanvasOptions, TASK_TYPES, TEXT_API_FONT_FAMILIES, type TaskListItem, type TaskType, type TextApiFontFamily, type TextStyle, type TextStyles, type Timezone, Quote0 as default };
17
20
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/api/index.ts"],"mappings":";;;;;cAIM,MAAA,SAAe,UAAA;EACnB,MAAA,EAAQ,YAAA;EACR,OAAA,EAAS,aAAA;cAEG,IAAA,EAAM,cAAA;EAAA,SAOT,OAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/api/index.ts"],"mappings":";;;;;;cAMM,eAAe;EACnB,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,UAAU;EAEE,YAAA,MAAM;WAST"}
@@ -1,2 +1,2 @@
1
- import e from"./base.mjs";import t,{BORDER as n,DITHER_KERNELS as r,DITHER_TYPES as i}from"./modules/content.mjs";import a from"./modules/device.mjs";var o=class extends e{device;content;constructor(e){super(e),this.device=new a(e),this.content=new t(e)}display=e.DISPLAY};export{n as BORDER,r as DITHER_KERNELS,i as DITHER_TYPES,o as default};
1
+ import e from"./base.mjs";import t from"./modules/canvas.mjs";import n,{BORDER as r,DITHER_KERNELS as i,DITHER_TYPES as a,TASK_TYPES as o,TEXT_API_FONT_FAMILIES as s}from"./modules/content.mjs";import c from"./modules/device.mjs";import l from"./modules/timezone.mjs";var u=class extends e{device;content;canvas;timezone;constructor(e){super(e),this.device=new c(e),this.content=new n(e),this.canvas=new t(e),this.timezone=new l(e)}display=e.DISPLAY};export{r as BORDER,i as DITHER_KERNELS,a as DITHER_TYPES,o as TASK_TYPES,s as TEXT_API_FONT_FAMILIES,u as default};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/api/index.ts"],"sourcesContent":["import BaseClient, { type BaseClientArgs } from './base'\nimport ContentModule from './modules/content'\nimport DeviceModule from './modules/device'\n\nclass Quote0 extends BaseClient {\n device: DeviceModule\n content: ContentModule\n\n constructor(args: BaseClientArgs) {\n super(args)\n\n this.device = new DeviceModule(args)\n this.content = new ContentModule(args)\n }\n\n readonly display = BaseClient.DISPLAY\n}\n\nexport default Quote0\n\nexport {\n BORDER,\n DITHER_TYPES,\n DITHER_KERNELS,\n type Border,\n type DitherType,\n type DitherKernel,\n} from './modules/content'\n"],"mappings":"sJAIA,IAAM,EAAN,cAAqB,CAAW,CAC9B,OACA,QAEA,YAAY,EAAsB,CAChC,MAAM,EAAK,CAEX,KAAK,OAAS,IAAI,EAAa,EAAK,CACpC,KAAK,QAAU,IAAI,EAAc,EAAK,CAGxC,QAAmB,EAAW"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/api/index.ts"],"sourcesContent":["import BaseClient, { type BaseClientArgs } from './base'\nimport CanvasModule from './modules/canvas'\nimport ContentModule from './modules/content'\nimport DeviceModule from './modules/device'\nimport TimezoneModule from './modules/timezone'\n\nclass Quote0 extends BaseClient {\n device: DeviceModule\n content: ContentModule\n canvas: CanvasModule\n timezone: TimezoneModule\n\n constructor(args: BaseClientArgs) {\n super(args)\n\n this.device = new DeviceModule(args)\n this.content = new ContentModule(args)\n this.canvas = new CanvasModule(args)\n this.timezone = new TimezoneModule(args)\n }\n\n readonly display = BaseClient.DISPLAY\n}\n\nexport default Quote0\n\nexport {\n BORDER,\n DITHER_TYPES,\n DITHER_KERNELS,\n TEXT_API_FONT_FAMILIES,\n TASK_TYPES,\n type Border,\n type DitherType,\n type DitherKernel,\n type TextApiFontFamily,\n type TextStyle,\n type MessageTextStyle,\n type TextStyles,\n type TaskType,\n type TaskListItem,\n} from './modules/content'\nexport { type PushCanvasOptions } from './modules/canvas'\nexport { type DeviceSettings } from './modules/device'\nexport { type Timezone } from './modules/timezone'\n"],"mappings":"4QAMA,IAAM,EAAN,cAAqB,CAAW,CAC9B,OACA,QACA,OACA,SAEA,YAAY,EAAsB,CAChC,MAAM,CAAI,EAEV,KAAK,OAAS,IAAI,EAAa,CAAI,EACnC,KAAK,QAAU,IAAI,EAAc,CAAI,EACrC,KAAK,OAAS,IAAI,EAAa,CAAI,EACnC,KAAK,SAAW,IAAI,EAAe,CAAI,CACzC,CAEA,QAAmB,EAAW,OAChC"}
@@ -0,0 +1,26 @@
1
+ import BaseClient from "../base.mjs";
2
+ import { Border } from "./content.mjs";
3
+ //#region src/api/modules/canvas.d.ts
4
+ interface PushCanvasOptions {
5
+ refreshNow?: boolean;
6
+ taskKey?: string;
7
+ taskAlias?: string;
8
+ data?: Record<string, unknown>;
9
+ windowData: Record<string, unknown>;
10
+ layoutFull?: {
11
+ tw?: string;
12
+ style?: Record<string, unknown>;
13
+ };
14
+ link?: string;
15
+ border?: Border;
16
+ }
17
+ declare class CanvasModule extends BaseClient {
18
+ pushCanvas({ deviceId }: {
19
+ deviceId: string;
20
+ }, options: PushCanvasOptions): Promise<{
21
+ message: string;
22
+ }>;
23
+ }
24
+ //#endregion
25
+ export { PushCanvasOptions, CanvasModule as default };
26
+ //# sourceMappingURL=canvas.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas.d.mts","names":[],"sources":["../../../src/api/modules/canvas.ts"],"mappings":";;;UAGiB;EACf;EACA;EACA;EACA,OAAO;EACP,YAAY;EACZ;IACE;IACA,QAAQ;;EAEV;EACA,SAAS;;cAGL,qBAAqB;EACnB,aAAa;IAAc;KAAoB,SAAS,oBAAiB;IAI3D"}
@@ -0,0 +1,2 @@
1
+ import e from"../base.mjs";var t=class extends e{async pushCanvas({deviceId:e},t){return await this.fetchApi(`/authV2/open/device/${e}/canvas`,{method:`POST`,body:JSON.stringify(t)})}};export{t as default};
2
+ //# sourceMappingURL=canvas.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas.mjs","names":[],"sources":["../../../src/api/modules/canvas.ts"],"sourcesContent":["import BaseClient from '../base'\nimport type { Border } from './content'\n\nexport interface PushCanvasOptions {\n refreshNow?: boolean\n taskKey?: string\n taskAlias?: string\n data?: Record<string, unknown>\n windowData: Record<string, unknown>\n layoutFull?: {\n tw?: string\n style?: Record<string, unknown>\n }\n link?: string\n border?: Border\n}\n\nclass CanvasModule extends BaseClient {\n async pushCanvas({ deviceId }: { deviceId: string }, options: PushCanvasOptions) {\n const response = (await this.fetchApi(`/authV2/open/device/${deviceId}/canvas`, {\n method: 'POST',\n body: JSON.stringify(options),\n })) as { message: string }\n\n return response\n }\n}\n\nexport default CanvasModule\n"],"mappings":"2BAiBA,IAAM,EAAN,cAA2B,CAAW,CACpC,MAAM,WAAW,CAAE,YAAkC,EAA4B,CAM/E,OAAO,MALiB,KAAK,SAAS,uBAAuB,EAAS,SAAU,CAC9E,OAAQ,OACR,KAAM,KAAK,UAAU,CAAO,CAC9B,CAAC,CAGH,CACF"}
@@ -1,5 +1,4 @@
1
- import { BaseClient } from "../base.mjs";
2
-
1
+ import BaseClient from "../base.mjs";
3
2
  //#region src/api/modules/content.d.ts
4
3
  declare const BORDER: readonly [0, 1];
5
4
  type Border = (typeof BORDER)[number];
@@ -7,40 +6,49 @@ declare const DITHER_TYPES: readonly ["DIFFUSION", "ORDERED", "NONE"];
7
6
  type DitherType = (typeof DITHER_TYPES)[number];
8
7
  declare const DITHER_KERNELS: readonly ["THRESHOLD", "ATKINSON", "BURKES", "FLOYD_STEINBERG", "SIERRA2", "STUCKI", "JARVIS_JUDICE_NINKE", "DIFFUSION_ROW", "DIFFUSION_COLUMN", "DIFFUSION_2D"];
9
8
  type DitherKernel = (typeof DITHER_KERNELS)[number];
9
+ declare const TEXT_API_FONT_FAMILIES: readonly ["ChillDuanSans", "ChillKSans", "ChillOrganic", "ChillRoundF", "ChillRoundGothic", "Cusong16", "DotGothic16", "FusionPixel8", "FusionPixel10", "FusionPixel12", "Liusong24", "LogoSCUnboundedSans", "MaokenYingBiKaiShuJ0.09", "PlayfairDisplay", "Quan8", "Unifont16", "UnifontExMono16", "XiaoyaPixel12", "Zihunzhoukesong", "Zpix12"];
10
+ type TextApiFontFamily = (typeof TEXT_API_FONT_FAMILIES)[number];
10
11
  declare const TASK_TYPES: readonly ["fixed", "loop"];
11
12
  type TaskType = (typeof TASK_TYPES)[number];
13
+ interface TaskListItem {
14
+ type: 'TEXT_API' | 'IMAGE_API' | 'CANVAS_API' | 'GENERAL';
15
+ key: string | null;
16
+ refreshNow?: boolean;
17
+ title?: string;
18
+ message?: string;
19
+ signature?: string;
20
+ icon?: string;
21
+ link?: string;
22
+ image?: string;
23
+ border?: Border;
24
+ ditherType?: string;
25
+ ditherKernel?: string;
26
+ }
27
+ interface TextStyle {
28
+ fontFamily?: TextApiFontFamily;
29
+ fontSize?: number;
30
+ fontWeight?: number;
31
+ }
32
+ interface MessageTextStyle extends TextStyle {
33
+ lineHeight?: number;
34
+ }
35
+ interface TextStyles {
36
+ title?: TextStyle;
37
+ message?: MessageTextStyle;
38
+ signature?: TextStyle;
39
+ }
40
+ type ApiResponse = {
41
+ message: string;
42
+ };
12
43
  declare class ContentModule extends BaseClient {
13
- next({
14
- deviceId
15
- }: {
44
+ next({ deviceId }: {
16
45
  deviceId: string;
17
- }): Promise<{
18
- code: number;
19
- message: string;
20
- }>;
21
- list({
22
- deviceId,
23
- taskType
24
- }: {
46
+ }): Promise<ApiResponse>;
47
+ list({ deviceId, taskType }: {
25
48
  deviceId: string;
26
49
  taskType: TaskType;
27
- }): Promise<{
28
- type: "TEXT_API" | "IMAGE_API" | "GENERAL";
29
- key: string | null;
30
- refreshNow?: boolean;
31
- title?: string;
32
- message?: string;
33
- signature?: string;
34
- icon?: string;
35
- link?: string;
36
- image?: string;
37
- border?: Border;
38
- ditherType?: string;
39
- ditherKernel?: string;
40
- }>;
41
- pushText({
42
- deviceId
43
- }: {
50
+ }): Promise<TaskListItem[]>;
51
+ pushText({ deviceId }: {
44
52
  deviceId: string;
45
53
  }, options: {
46
54
  refreshNow?: boolean;
@@ -50,13 +58,10 @@ declare class ContentModule extends BaseClient {
50
58
  icon?: string;
51
59
  link?: string;
52
60
  taskKey?: string;
53
- }): Promise<{
54
- code: number;
55
- message: string;
56
- }>;
57
- pushImage({
58
- deviceId
59
- }: {
61
+ taskAlias?: string | number;
62
+ styles?: TextStyles;
63
+ }): Promise<ApiResponse>;
64
+ pushImage({ deviceId }: {
60
65
  deviceId: string;
61
66
  }, options: {
62
67
  refreshNow?: boolean;
@@ -66,11 +71,9 @@ declare class ContentModule extends BaseClient {
66
71
  ditherType?: DitherType;
67
72
  ditherKernel?: DitherKernel;
68
73
  taskKey?: string;
69
- }): Promise<{
70
- code: number;
71
- message: string;
72
- }>;
74
+ taskAlias?: string | number;
75
+ }): Promise<ApiResponse>;
73
76
  }
74
77
  //#endregion
75
- export { BORDER, Border, ContentModule, DITHER_KERNELS, DITHER_TYPES, DitherKernel, DitherType };
78
+ export { BORDER, Border, DITHER_KERNELS, DITHER_TYPES, DitherKernel, DitherType, MessageTextStyle, TASK_TYPES, TEXT_API_FONT_FAMILIES, TaskListItem, TaskType, TextApiFontFamily, TextStyle, TextStyles, ContentModule as default };
76
79
  //# sourceMappingURL=content.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"content.d.mts","names":[],"sources":["../../../src/api/modules/content.ts"],"mappings":";;;cAEa,MAAA;AAAA,KACD,MAAA,WAAiB,MAAA;AAAA,cAEhB,YAAA;AAAA,KACD,UAAA,WAAqB,YAAA;AAAA,cAEpB,cAAA;AAAA,KAYD,YAAA,WAAuB,cAAA;AAAA,cAEtB,UAAA;AAAA,KACD,QAAA,WAAmB,UAAA;AAAA,cAEzB,aAAA,SAAsB,UAAA;EACpB,IAAA,CAAA;IAAO;EAAA;IAAc,QAAA;EAAA,IAAkB,OAAA;;;;EAQvC,IAAA,CAAA;IAAO,QAAA;IAAU;EAAA;IAAc,QAAA;IAAkB,QAAA,EAAU,QAAA;EAAA,IAAU,OAAA;;;;;;;;;;aAa9D,MAAA;;;;EAQP,QAAA,CAAA;IACF;EAAA;IAAc,QAAA;EAAA,GAChB,OAAA;IACE,UAAA;IACA,KAAA;IACA,OAAA;IACA,SAAA;IACA,IAAA;IACA,IAAA;IACA,OAAA;EAAA,IACD,OAAA;;;;EAUG,SAAA,CAAA;IACF;EAAA;IAAc,QAAA;EAAA,GAChB,OAAA;IACE,UAAA;IACA,KAAA;IACA,IAAA;IACA,MAAA,GAAS,MAAA;IACT,UAAA,GAAa,UAAA;IACb,YAAA,GAAe,YAAA;IACf,OAAA;EAAA,IACD,OAAA"}
1
+ {"version":3,"file":"content.d.mts","names":[],"sources":["../../../src/api/modules/content.ts"],"mappings":";;cAEa;KACD,iBAAiB;cAEhB;KACD,qBAAqB;cAEpB;KAYD,uBAAuB;cAEtB;KAsBD,4BAA4B;cAE3B;KACD,mBAAmB;UAEd;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,SAAS;EACT;EACA;;UAGe;EACf,aAAa;EACb;EACA;;UAGe,yBAAyB;EACxC;;UAGe;EACf,QAAQ;EACR,UAAU;EACV,YAAY;;KAGT;EAAgB;;cAEf,sBAAsB;EACpB,OAAO;IAAc;MAAkB,QAAA;EAQvC,OAAO,UAAU;IAAc;IAAkB,UAAU;MAAU,QAAA;EAQrE,WACF;IAAc;KAChB;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,SAAS;MACV,QAAA;EAUG,YACF;IAAc;KAChB;IACE;IACA;IACA;IACA,SAAS;IACT,aAAa;IACb,eAAe;IACf;IACA;MACD,QAAA"}
@@ -1,2 +1,2 @@
1
- import e from"../base.mjs";const t=[0,1],n=[`DIFFUSION`,`ORDERED`,`NONE`],r=[`THRESHOLD`,`ATKINSON`,`BURKES`,`FLOYD_STEINBERG`,`SIERRA2`,`STUCKI`,`JARVIS_JUDICE_NINKE`,`DIFFUSION_ROW`,`DIFFUSION_COLUMN`,`DIFFUSION_2D`];var i=class extends e{async next({deviceId:e}){return await this.fetchApi(`/authV2/open/device/${e}/next`,{method:`POST`})}async list({deviceId:e,taskType:t}){return await this.fetchApi(`/api/authV2/open/device/${e}/${t}/list`)}async pushText({deviceId:e},t){return await this.fetchApi(`/api/authV2/open/device/${e}/text`,{method:`POST`,body:JSON.stringify(t)})}async pushImage({deviceId:e},t){return await this.fetchApi(`/authV2/open/device/${e}/image`,{method:`POST`,body:JSON.stringify(t)})}};export{t as BORDER,r as DITHER_KERNELS,n as DITHER_TYPES,i as default};
1
+ import e from"../base.mjs";const t=[0,1],n=[`DIFFUSION`,`ORDERED`,`NONE`],r=[`THRESHOLD`,`ATKINSON`,`BURKES`,`FLOYD_STEINBERG`,`SIERRA2`,`STUCKI`,`JARVIS_JUDICE_NINKE`,`DIFFUSION_ROW`,`DIFFUSION_COLUMN`,`DIFFUSION_2D`],i=[`ChillDuanSans`,`ChillKSans`,`ChillOrganic`,`ChillRoundF`,`ChillRoundGothic`,`Cusong16`,`DotGothic16`,`FusionPixel8`,`FusionPixel10`,`FusionPixel12`,`Liusong24`,`LogoSCUnboundedSans`,`MaokenYingBiKaiShuJ0.09`,`PlayfairDisplay`,`Quan8`,`Unifont16`,`UnifontExMono16`,`XiaoyaPixel12`,`Zihunzhoukesong`,`Zpix12`],a=[`fixed`,`loop`];var o=class extends e{async next({deviceId:e}){return await this.fetchApi(`/authV2/open/device/${e}/next`,{method:`POST`})}async list({deviceId:e,taskType:t}){return await this.fetchApi(`/authV2/open/device/${e}/${t}/list`)}async pushText({deviceId:e},t){return await this.fetchApi(`/authV2/open/device/${e}/text`,{method:`POST`,body:JSON.stringify(t)})}async pushImage({deviceId:e},t){return await this.fetchApi(`/authV2/open/device/${e}/image`,{method:`POST`,body:JSON.stringify(t)})}};export{t as BORDER,r as DITHER_KERNELS,n as DITHER_TYPES,a as TASK_TYPES,i as TEXT_API_FONT_FAMILIES,o as default};
2
2
  //# sourceMappingURL=content.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"content.mjs","names":[],"sources":["../../../src/api/modules/content.ts"],"sourcesContent":["import BaseClient from '../base'\n\nexport const BORDER = [0, 1] as const\nexport type Border = (typeof BORDER)[number]\n\nexport const DITHER_TYPES = ['DIFFUSION', 'ORDERED', 'NONE'] as const\nexport type DitherType = (typeof DITHER_TYPES)[number]\n\nexport const DITHER_KERNELS = [\n 'THRESHOLD',\n 'ATKINSON',\n 'BURKES',\n 'FLOYD_STEINBERG',\n 'SIERRA2',\n 'STUCKI',\n 'JARVIS_JUDICE_NINKE',\n 'DIFFUSION_ROW',\n 'DIFFUSION_COLUMN',\n 'DIFFUSION_2D',\n] as const\nexport type DitherKernel = (typeof DITHER_KERNELS)[number]\n\nexport const TASK_TYPES = ['fixed', 'loop'] as const\nexport type TaskType = (typeof TASK_TYPES)[number]\n\nclass ContentModule extends BaseClient {\n async next({ deviceId }: { deviceId: string }) {\n const response = (await this.fetchApi(`/authV2/open/device/${deviceId}/next`, {\n method: 'POST',\n })) as { code: number; message: string }\n\n return response\n }\n\n async list({ deviceId, taskType }: { deviceId: string; taskType: TaskType }) {\n const response = (await this.fetchApi(\n `/api/authV2/open/device/${deviceId}/${taskType}/list`,\n )) as {\n type: 'TEXT_API' | 'IMAGE_API' | 'GENERAL'\n key: string | null\n refreshNow?: boolean\n title?: string\n message?: string\n signature?: string\n icon?: string\n link?: string\n image?: string\n border?: Border\n ditherType?: string\n ditherKernel?: string\n }\n\n return response\n }\n\n async pushText(\n { deviceId }: { deviceId: string },\n options: {\n refreshNow?: boolean\n title?: string\n message?: string\n signature?: string\n icon?: string\n link?: string\n taskKey?: string\n },\n ) {\n const response = (await this.fetchApi(`/api/authV2/open/device/${deviceId}/text`, {\n method: 'POST',\n body: JSON.stringify(options),\n })) as { code: number; message: string }\n\n return response\n }\n\n async pushImage(\n { deviceId }: { deviceId: string },\n options: {\n refreshNow?: boolean\n image: string\n link?: string\n border?: Border\n ditherType?: DitherType\n ditherKernel?: DitherKernel\n taskKey?: string\n },\n ) {\n const response = (await this.fetchApi(`/authV2/open/device/${deviceId}/image`, {\n method: 'POST',\n body: JSON.stringify(options),\n })) as { code: number; message: string }\n\n return response\n }\n}\n\nexport default ContentModule\n"],"mappings":"2BAEA,MAAa,EAAS,CAAC,EAAG,EAAE,CAGf,EAAe,CAAC,YAAa,UAAW,OAAO,CAG/C,EAAiB,CAC5B,YACA,WACA,SACA,kBACA,UACA,SACA,sBACA,gBACA,mBACA,eACD,CAMD,IAAM,EAAN,cAA4B,CAAW,CACrC,MAAM,KAAK,CAAE,YAAkC,CAK7C,OAJkB,MAAM,KAAK,SAAS,uBAAuB,EAAS,OAAQ,CAC5E,OAAQ,OACT,CAAC,CAKJ,MAAM,KAAK,CAAE,WAAU,YAAsD,CAkB3E,OAjBkB,MAAM,KAAK,SAC3B,2BAA2B,EAAS,GAAG,EAAS,OACjD,CAkBH,MAAM,SACJ,CAAE,YACF,EASA,CAMA,OALkB,MAAM,KAAK,SAAS,2BAA2B,EAAS,OAAQ,CAChF,OAAQ,OACR,KAAM,KAAK,UAAU,EAAQ,CAC9B,CAAC,CAKJ,MAAM,UACJ,CAAE,YACF,EASA,CAMA,OALkB,MAAM,KAAK,SAAS,uBAAuB,EAAS,QAAS,CAC7E,OAAQ,OACR,KAAM,KAAK,UAAU,EAAQ,CAC9B,CAAC"}
1
+ {"version":3,"file":"content.mjs","names":[],"sources":["../../../src/api/modules/content.ts"],"sourcesContent":["import BaseClient from '../base'\n\nexport const BORDER = [0, 1] as const\nexport type Border = (typeof BORDER)[number]\n\nexport const DITHER_TYPES = ['DIFFUSION', 'ORDERED', 'NONE'] as const\nexport type DitherType = (typeof DITHER_TYPES)[number]\n\nexport const DITHER_KERNELS = [\n 'THRESHOLD',\n 'ATKINSON',\n 'BURKES',\n 'FLOYD_STEINBERG',\n 'SIERRA2',\n 'STUCKI',\n 'JARVIS_JUDICE_NINKE',\n 'DIFFUSION_ROW',\n 'DIFFUSION_COLUMN',\n 'DIFFUSION_2D',\n] as const\nexport type DitherKernel = (typeof DITHER_KERNELS)[number]\n\nexport const TEXT_API_FONT_FAMILIES = [\n 'ChillDuanSans',\n 'ChillKSans',\n 'ChillOrganic',\n 'ChillRoundF',\n 'ChillRoundGothic',\n 'Cusong16',\n 'DotGothic16',\n 'FusionPixel8',\n 'FusionPixel10',\n 'FusionPixel12',\n 'Liusong24',\n 'LogoSCUnboundedSans',\n 'MaokenYingBiKaiShuJ0.09',\n 'PlayfairDisplay',\n 'Quan8',\n 'Unifont16',\n 'UnifontExMono16',\n 'XiaoyaPixel12',\n 'Zihunzhoukesong',\n 'Zpix12',\n] as const\nexport type TextApiFontFamily = (typeof TEXT_API_FONT_FAMILIES)[number]\n\nexport const TASK_TYPES = ['fixed', 'loop'] as const\nexport type TaskType = (typeof TASK_TYPES)[number]\n\nexport interface TaskListItem {\n type: 'TEXT_API' | 'IMAGE_API' | 'CANVAS_API' | 'GENERAL'\n key: string | null\n refreshNow?: boolean\n title?: string\n message?: string\n signature?: string\n icon?: string\n link?: string\n image?: string\n border?: Border\n ditherType?: string\n ditherKernel?: string\n}\n\nexport interface TextStyle {\n fontFamily?: TextApiFontFamily\n fontSize?: number\n fontWeight?: number\n}\n\nexport interface MessageTextStyle extends TextStyle {\n lineHeight?: number\n}\n\nexport interface TextStyles {\n title?: TextStyle\n message?: MessageTextStyle\n signature?: TextStyle\n}\n\ntype ApiResponse = { message: string }\n\nclass ContentModule extends BaseClient {\n async next({ deviceId }: { deviceId: string }) {\n const response = (await this.fetchApi(`/authV2/open/device/${deviceId}/next`, {\n method: 'POST',\n })) as ApiResponse\n\n return response\n }\n\n async list({ deviceId, taskType }: { deviceId: string; taskType: TaskType }) {\n const response = (await this.fetchApi(\n `/authV2/open/device/${deviceId}/${taskType}/list`,\n )) as TaskListItem[]\n\n return response\n }\n\n async pushText(\n { deviceId }: { deviceId: string },\n options: {\n refreshNow?: boolean\n title?: string\n message?: string\n signature?: string\n icon?: string\n link?: string\n taskKey?: string\n taskAlias?: string | number\n styles?: TextStyles\n },\n ) {\n const response = (await this.fetchApi(`/authV2/open/device/${deviceId}/text`, {\n method: 'POST',\n body: JSON.stringify(options),\n })) as ApiResponse\n\n return response\n }\n\n async pushImage(\n { deviceId }: { deviceId: string },\n options: {\n refreshNow?: boolean\n image: string\n link?: string\n border?: Border\n ditherType?: DitherType\n ditherKernel?: DitherKernel\n taskKey?: string\n taskAlias?: string | number\n },\n ) {\n const response = (await this.fetchApi(`/authV2/open/device/${deviceId}/image`, {\n method: 'POST',\n body: JSON.stringify(options),\n })) as ApiResponse\n\n return response\n }\n}\n\nexport default ContentModule\n"],"mappings":"2BAEA,MAAa,EAAS,CAAC,EAAG,CAAC,EAGd,EAAe,CAAC,YAAa,UAAW,MAAM,EAG9C,EAAiB,CAC5B,YACA,WACA,SACA,kBACA,UACA,SACA,sBACA,gBACA,mBACA,cACF,EAGa,EAAyB,CACpC,gBACA,aACA,eACA,cACA,mBACA,WACA,cACA,eACA,gBACA,gBACA,YACA,sBACA,0BACA,kBACA,QACA,YACA,kBACA,gBACA,kBACA,QACF,EAGa,EAAa,CAAC,QAAS,MAAM,EAoC1C,IAAM,EAAN,cAA4B,CAAW,CACrC,MAAM,KAAK,CAAE,YAAkC,CAK7C,OAAO,MAJiB,KAAK,SAAS,uBAAuB,EAAS,OAAQ,CAC5E,OAAQ,MACV,CAAC,CAGH,CAEA,MAAM,KAAK,CAAE,WAAU,YAAsD,CAK3E,OAAO,MAJiB,KAAK,SAC3B,uBAAuB,EAAS,GAAG,EAAS,MAC9C,CAGF,CAEA,MAAM,SACJ,CAAE,YACF,EAWA,CAMA,OAAO,MALiB,KAAK,SAAS,uBAAuB,EAAS,OAAQ,CAC5E,OAAQ,OACR,KAAM,KAAK,UAAU,CAAO,CAC9B,CAAC,CAGH,CAEA,MAAM,UACJ,CAAE,YACF,EAUA,CAMA,OAAO,MALiB,KAAK,SAAS,uBAAuB,EAAS,QAAS,CAC7E,OAAQ,OACR,KAAM,KAAK,UAAU,CAAO,CAC9B,CAAC,CAGH,CACF"}
@@ -1,21 +1,35 @@
1
- import { BaseClient } from "../base.mjs";
2
-
1
+ import BaseClient from "../base.mjs";
3
2
  //#region src/api/modules/device.d.ts
3
+ interface DeviceSettings {
4
+ deviceId?: string;
5
+ alias?: string | null;
6
+ location?: string | null;
7
+ timezone?: string;
8
+ interval?: {
9
+ powerMs?: number;
10
+ batteryMs?: number;
11
+ };
12
+ sleep?: {
13
+ enabled: boolean;
14
+ start: string;
15
+ end: string;
16
+ };
17
+ }
4
18
  declare class DeviceModule extends BaseClient {
5
19
  list(): Promise<{
6
20
  id: string;
21
+ alias?: string | null;
22
+ location?: string | null;
7
23
  series: string;
8
24
  model: string;
9
25
  edition: 1 | 2;
10
26
  }[]>;
11
- status({
12
- deviceId
13
- }: {
27
+ status({ deviceId }: {
14
28
  deviceId: string;
15
29
  }): Promise<{
16
30
  deviceId: string;
17
- alias: string | null;
18
- location: string | null;
31
+ alias?: string | null;
32
+ location?: string | null;
19
33
  status: {
20
34
  version: string;
21
35
  current: string;
@@ -28,7 +42,7 @@ declare class DeviceModule extends BaseClient {
28
42
  current: {
29
43
  rotated: boolean;
30
44
  border: number;
31
- image: string[];
45
+ image?: string[] | null;
32
46
  };
33
47
  next: {
34
48
  battery: string;
@@ -36,7 +50,15 @@ declare class DeviceModule extends BaseClient {
36
50
  };
37
51
  };
38
52
  }>;
53
+ getSettings({ deviceId }: {
54
+ deviceId: string;
55
+ }): Promise<DeviceSettings>;
56
+ updateSettings({ deviceId }: {
57
+ deviceId: string;
58
+ }, settings: DeviceSettings): Promise<{
59
+ message: string;
60
+ }>;
39
61
  }
40
62
  //#endregion
41
- export { DeviceModule };
63
+ export { DeviceSettings, DeviceModule as default };
42
64
  //# sourceMappingURL=device.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"device.d.mts","names":[],"sources":["../../../src/api/modules/device.ts"],"mappings":";;;cAEM,YAAA,SAAqB,UAAA;EACnB,IAAA,CAAA,GAAI,OAAA;;;;;;EAWJ,MAAA,CAAA;IAAS;EAAA;IAAc,QAAA;EAAA,IAAkB,OAAA;;;;;MAMzC,OAAA;MACA,OAAA;MACA,WAAA;MACA,OAAA;MACA,IAAA;IAAA;;MAGA,IAAA;MACA,OAAA;QACE,OAAA;QACA,MAAA;QACA,KAAA;MAAA;MAEF,IAAA;QACE,OAAA;QACA,KAAA;MAAA;IAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"device.d.mts","names":[],"sources":["../../../src/api/modules/device.ts"],"mappings":";;UAEiB;EACf;EACA;EACA;EACA;EACA;IACE;IACA;;EAEF;IACE;IACA;IACA;;;cAIE,qBAAqB;EACnB,QAAI;IAEF;IACI;IACG;IACH;IACD;IACE;;EAMP,SAAS;IAAc;MAAkB;IAEjC;IACF;IACG;IACH;MACN;MACA;MACA;MACA;MACA;;IAEU;MACV;MACA;QACE;QACA;QACA;;MAEF;QACE;QACA;;;;EAQF,cAAc;IAAc;MAAkB,QAAA;EAQ9C,iBAAiB;IAAc;KAAoB,UAAU,iBAAc;IAI7D"}
@@ -1,2 +1,2 @@
1
- import e from"../base.mjs";var t=class extends e{async list(){return await this.fetchApi(`/authV2/open/devices`)}async status({deviceId:e}){return await this.fetchApi(`/authV2/open/device/${e}/status`)}};export{t as default};
1
+ import e from"../base.mjs";var t=class extends e{async list(){return await this.fetchApi(`/authV2/open/devices`)}async status({deviceId:e}){return await this.fetchApi(`/authV2/open/device/${e}/status`)}async getSettings({deviceId:e}){return await this.fetchApi(`/authV2/open/device/${e}/settings`)}async updateSettings({deviceId:e},t){return await this.fetchApi(`/authV2/open/device/${e}/settings`,{method:`POST`,body:JSON.stringify(t)})}};export{t as default};
2
2
  //# sourceMappingURL=device.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"device.mjs","names":[],"sources":["../../../src/api/modules/device.ts"],"sourcesContent":["import BaseClient from '../base'\n\nclass DeviceModule extends BaseClient {\n async list() {\n const response = (await this.fetchApi(`/authV2/open/devices`)) as {\n id: string\n series: string\n model: string\n edition: 1 | 2\n }[]\n\n return response\n }\n\n async status({ deviceId }: { deviceId: string }) {\n const response = (await this.fetchApi(`/authV2/open/device/${deviceId}/status`)) as {\n deviceId: string\n alias: string | null\n location: string | null\n status: {\n version: string\n current: string\n description: string\n battery: string\n wifi: string\n }\n renderInfo: {\n last: string\n current: {\n rotated: boolean\n border: number\n image: string[]\n }\n next: {\n battery: string\n power: string\n }\n }\n }\n\n return response\n }\n}\n\nexport default DeviceModule\n"],"mappings":"2BAEA,IAAM,EAAN,cAA2B,CAAW,CACpC,MAAM,MAAO,CAQX,OAPkB,MAAM,KAAK,SAAS,uBAAuB,CAU/D,MAAM,OAAO,CAAE,YAAkC,CA0B/C,OAzBkB,MAAM,KAAK,SAAS,uBAAuB,EAAS,SAAS"}
1
+ {"version":3,"file":"device.mjs","names":[],"sources":["../../../src/api/modules/device.ts"],"sourcesContent":["import BaseClient from '../base'\n\nexport interface DeviceSettings {\n deviceId?: string\n alias?: string | null\n location?: string | null\n timezone?: string\n interval?: {\n powerMs?: number\n batteryMs?: number\n }\n sleep?: {\n enabled: boolean\n start: string\n end: string\n }\n}\n\nclass DeviceModule extends BaseClient {\n async list() {\n const response = (await this.fetchApi(`/authV2/open/devices`)) as {\n id: string\n alias?: string | null\n location?: string | null\n series: string\n model: string\n edition: 1 | 2\n }[]\n\n return response\n }\n\n async status({ deviceId }: { deviceId: string }) {\n const response = (await this.fetchApi(`/authV2/open/device/${deviceId}/status`)) as {\n deviceId: string\n alias?: string | null\n location?: string | null\n status: {\n version: string\n current: string\n description: string\n battery: string\n wifi: string\n }\n renderInfo: {\n last: string\n current: {\n rotated: boolean\n border: number\n image?: string[] | null\n }\n next: {\n battery: string\n power: string\n }\n }\n }\n\n return response\n }\n\n async getSettings({ deviceId }: { deviceId: string }) {\n const response = (await this.fetchApi(\n `/authV2/open/device/${deviceId}/settings`,\n )) as DeviceSettings\n\n return response\n }\n\n async updateSettings({ deviceId }: { deviceId: string }, settings: DeviceSettings) {\n const response = (await this.fetchApi(`/authV2/open/device/${deviceId}/settings`, {\n method: 'POST',\n body: JSON.stringify(settings),\n })) as { message: string }\n\n return response\n }\n}\n\nexport default DeviceModule\n"],"mappings":"2BAkBA,IAAM,EAAN,cAA2B,CAAW,CACpC,MAAM,MAAO,CAUX,OAAO,MATiB,KAAK,SAAS,sBAAsB,CAU9D,CAEA,MAAM,OAAO,CAAE,YAAkC,CA0B/C,OAAO,MAzBiB,KAAK,SAAS,uBAAuB,EAAS,QAAQ,CA0BhF,CAEA,MAAM,YAAY,CAAE,YAAkC,CAKpD,OAAO,MAJiB,KAAK,SAC3B,uBAAuB,EAAS,UAClC,CAGF,CAEA,MAAM,eAAe,CAAE,YAAkC,EAA0B,CAMjF,OAAO,MALiB,KAAK,SAAS,uBAAuB,EAAS,WAAY,CAChF,OAAQ,OACR,KAAM,KAAK,UAAU,CAAQ,CAC/B,CAAC,CAGH,CACF"}
@@ -0,0 +1,14 @@
1
+ import BaseClient from "../base.mjs";
2
+ //#region src/api/modules/timezone.d.ts
3
+ interface Timezone {
4
+ key: string;
5
+ name: string;
6
+ utcOffsetMinutes: number;
7
+ utcOffsetLabel: string;
8
+ }
9
+ declare class TimezoneModule extends BaseClient {
10
+ list(): Promise<Timezone[]>;
11
+ }
12
+ //#endregion
13
+ export { Timezone, TimezoneModule as default };
14
+ //# sourceMappingURL=timezone.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timezone.d.mts","names":[],"sources":["../../../src/api/modules/timezone.ts"],"mappings":";;UAEiB;EACf;EACA;EACA;EACA;;cAGI,uBAAuB;EACrB,QAAI,QAAA"}
@@ -0,0 +1,2 @@
1
+ import e from"../base.mjs";var t=class extends e{async list(){return await this.fetchApi(`/authV2/open/timezones`)}};export{t as default};
2
+ //# sourceMappingURL=timezone.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timezone.mjs","names":[],"sources":["../../../src/api/modules/timezone.ts"],"sourcesContent":["import BaseClient from '../base'\n\nexport interface Timezone {\n key: string\n name: string\n utcOffsetMinutes: number\n utcOffsetLabel: string\n}\n\nclass TimezoneModule extends BaseClient {\n async list() {\n const response = (await this.fetchApi(`/authV2/open/timezones`)) as Timezone[]\n\n return response\n }\n}\n\nexport default TimezoneModule\n"],"mappings":"2BASA,IAAM,EAAN,cAA6B,CAAW,CACtC,MAAM,MAAO,CAGX,OAAO,MAFiB,KAAK,SAAS,wBAAwB,CAGhE,CACF"}
@@ -0,0 +1,2 @@
1
+ import{version as e}from"../package.mjs";import{registerAuthCommand as t}from"./commands/auth.mjs";import{registerContentCommands as n}from"./commands/content.mjs";import{registerDeviceCommands as r}from"./commands/device.mjs";import{registerTimezoneCommands as i}from"./commands/timezone.mjs";import{cac as a}from"cac";function o(){let o=a(`quote0`);return o.option(`--json`,`Emit machine-readable JSON output.`),t(o),r(o),n(o),i(o),o.help(),o.version(e),o}export{o as buildCli};
2
+ //# sourceMappingURL=app.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.mjs","names":[],"sources":["../../src/cli/app.ts"],"sourcesContent":["import { cac } from 'cac'\nimport { version } from '../../package.json'\nimport { registerAuthCommand } from './commands/auth'\nimport { registerContentCommands } from './commands/content'\nimport { registerDeviceCommands } from './commands/device'\nimport { registerTimezoneCommands } from './commands/timezone'\n\nexport function buildCli() {\n const cli = cac('quote0')\n\n cli.option('--json', 'Emit machine-readable JSON output.')\n\n registerAuthCommand(cli)\n registerDeviceCommands(cli)\n registerContentCommands(cli)\n registerTimezoneCommands(cli)\n\n cli.help()\n cli.version(version)\n\n return cli\n}\n"],"mappings":"gUAOA,SAAgB,GAAW,CACzB,IAAM,EAAM,EAAI,QAAQ,EAYxB,OAVA,EAAI,OAAO,SAAU,oCAAoC,EAEzD,EAAoB,CAAG,EACvB,EAAuB,CAAG,EAC1B,EAAwB,CAAG,EAC3B,EAAyB,CAAG,EAE5B,EAAI,KAAK,EACT,EAAI,QAAQ,CAAO,EAEZ,CACT"}
@@ -0,0 +1,2 @@
1
+ import{CliError as e}from"../errors.mjs";import{createCliContext as t}from"../context.mjs";import n from"../views/AuthPrompt.mjs";import{render as r}from"ink";import i from"react";import{jsx as a}from"react/jsx-runtime";function o(e){e.command(`auth`,`Enter and save API key`).action(async e=>{await s(t(e))})}async function s(t){if(t.json)throw new e("The `auth` command is interactive only and does not support `--json`.",{code:`UNSUPPORTED_OUTPUT_MODE`});await new Promise(e=>{let n=!1,i=r(a(c,{initialValue:t.config.get(`apiKey`,``),onSubmit:e=>{e.length===0?t.config.delete(`apiKey`):t.config.set(`apiKey`,e),n=!0},isSubmitted:()=>n,onComplete:()=>{i.unmount(),e()}}))})}function c({initialValue:e,onSubmit:t,isSubmitted:r,onComplete:o}){let[s,c]=i.useState(!1);return i.useEffect(()=>{if(!s||!r())return;let e=setTimeout(o,300);return()=>clearTimeout(e)},[s,r,o]),a(n,{initialValue:e,submitted:s,onSubmit:e=>{t(e),c(!0)}})}export{o as registerAuthCommand};
2
+ //# sourceMappingURL=auth.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.mjs","names":[],"sources":["../../../src/cli/commands/auth.tsx"],"sourcesContent":["import { render } from 'ink'\nimport React from 'react'\nimport type { CAC } from 'cac'\nimport { createCliContext, type CliContext } from '../context'\nimport { CliError } from '../errors'\nimport type { GlobalCommandOptions } from '../types'\nimport AuthPrompt from '../views/AuthPrompt'\n\nexport function registerAuthCommand(cli: CAC) {\n cli.command('auth', 'Enter and save API key').action(async (options: GlobalCommandOptions) => {\n await runAuthCommand(createCliContext(options))\n })\n}\n\nasync function runAuthCommand(context: CliContext) {\n if (context.json) {\n throw new CliError('The `auth` command is interactive only and does not support `--json`.', {\n code: 'UNSUPPORTED_OUTPUT_MODE',\n })\n }\n\n await new Promise<void>(resolve => {\n let submitted = false\n const app = render(\n <AuthSession\n initialValue={context.config.get('apiKey', '')}\n onSubmit={value => {\n if (value.length === 0) {\n context.config.delete('apiKey')\n } else {\n context.config.set('apiKey', value)\n }\n\n submitted = true\n }}\n isSubmitted={() => submitted}\n onComplete={() => {\n app.unmount()\n resolve()\n }}\n />,\n )\n })\n}\n\nfunction AuthSession({\n initialValue,\n onSubmit,\n isSubmitted,\n onComplete,\n}: {\n initialValue: string\n onSubmit: (value: string) => void\n isSubmitted: () => boolean\n onComplete: () => void\n}) {\n const [submitted, setSubmitted] = React.useState(false)\n\n React.useEffect(() => {\n if (!submitted || !isSubmitted()) {\n return\n }\n\n const timer = setTimeout(onComplete, 300)\n return () => clearTimeout(timer)\n }, [submitted, isSubmitted, onComplete])\n\n return (\n <AuthPrompt\n initialValue={initialValue}\n submitted={submitted}\n onSubmit={value => {\n onSubmit(value)\n setSubmitted(true)\n }}\n />\n )\n}\n"],"mappings":"4NAQA,SAAgB,EAAoB,EAAU,CAC5C,EAAI,QAAQ,OAAQ,wBAAwB,CAAC,CAAC,OAAO,KAAO,IAAkC,CAC5F,MAAM,EAAe,EAAiB,CAAO,CAAC,CAChD,CAAC,CACH,CAEA,eAAe,EAAe,EAAqB,CACjD,GAAI,EAAQ,KACV,MAAM,IAAI,EAAS,wEAAyE,CAC1F,KAAM,yBACR,CAAC,EAGH,MAAM,IAAI,QAAc,GAAW,CACjC,IAAI,EAAY,GACV,EAAM,EACV,EAAC,EAAD,CACE,aAAc,EAAQ,OAAO,IAAI,SAAU,EAAE,EAC7C,SAAU,GAAS,CACb,EAAM,SAAW,EACnB,EAAQ,OAAO,OAAO,QAAQ,EAE9B,EAAQ,OAAO,IAAI,SAAU,CAAK,EAGpC,EAAY,EACd,EACA,gBAAmB,EACnB,eAAkB,CAChB,EAAI,QAAQ,EACZ,EAAQ,CACV,CACD,CAAA,CACH,CACF,CAAC,CACH,CAEA,SAAS,EAAY,CACnB,eACA,WACA,cACA,cAMC,CACD,GAAM,CAAC,EAAW,GAAgB,EAAM,SAAS,EAAK,EAWtD,OATA,EAAM,cAAgB,CACpB,GAAI,CAAC,GAAa,CAAC,EAAY,EAC7B,OAGF,IAAM,EAAQ,WAAW,EAAY,GAAG,EACxC,UAAa,aAAa,CAAK,CACjC,EAAG,CAAC,EAAW,EAAa,CAAU,CAAC,EAGrC,EAAC,EAAD,CACgB,eACH,YACX,SAAU,GAAS,CACjB,EAAS,CAAK,EACd,EAAa,EAAI,CACnB,CACD,CAAA,CAEL"}
@@ -0,0 +1,2 @@
1
+ import{BORDER as e,DITHER_KERNELS as t,DITHER_TYPES as n,TASK_TYPES as r,TEXT_API_FONT_FAMILIES as i}from"../../api/modules/content.mjs";import{CliError as a}from"../errors.mjs";import{createCliContext as o}from"../context.mjs";import{outputResult as s}from"../output.mjs";import c from"node:fs/promises";function l(e){e.command(`content [...args]`,`Manage content`).usage(`content <command> [options]`).example(`content next <deviceId>`).example(`content list <deviceId> --task-type fixed`).example(`content text <deviceId> --message "Hello"`).example(`content image <deviceId> --file ./frame.png`).example(`content image <deviceId> --url https://example.com/frame.png`).example(`content canvas <deviceId> --file ./window.json`).option(`-f, --file <file>`,"Path to image file, or windowData JSON file for `content canvas`").option(`--url <url>`,`http(s) image URL to push directly (alternative to --file)`).option(`--data <data>`,"Path to data JSON file for `content canvas`").option(`--layout-full-tw <layoutFullTw>`,"Tailwind classes overriding the FULL layout for `content canvas`").option(`--task-type <taskType>`,`Task type to list (${r.join(`, `)})`).option(`--refresh-now`,`Whether to refresh the device immediately`).option(`--link <link>`,`Optional link to open when content is tapped`).option(`--border <border>`,`Screen border color: 0 for white, 1 for black`).option(`--dither-type <ditherType>`,`Dithering algorithm to use (${n.join(`, `)})`).option(`--dither-kernel <ditherKernel>`,`Dithering kernel to use (${t.join(`, `)})`).option(`--task-key <taskKey>`,`Task key to identify the target Text/Image API content when multiple exist on the device`).option(`--task-alias <taskAlias>`,`Alias to distinguish the task in the device task list`).option(`--message <message>`,`Text message body`).option(`--title <title>`,`Text title`).option(`--signature <signature>`,`Text signature`).option(`--icon <icon>`,`PNG Base64 icon data or http(s) image URL`).option(`--title-font-family <titleFontFamily>`,`Title font family (${i.join(`, `)})`).option(`--title-font-size <titleFontSize>`,`Title font size (8-48 px)`).option(`--title-font-weight <titleFontWeight>`,`Title font weight (100-900)`).option(`--message-font-family <messageFontFamily>`,`Message font family (${i.join(`, `)})`).option(`--message-font-size <messageFontSize>`,`Message font size (8-48 px)`).option(`--message-font-weight <messageFontWeight>`,`Message font weight (100-900)`).option(`--message-line-height <messageLineHeight>`,`Message line height (0.8-3)`).option(`--signature-font-family <signatureFontFamily>`,`Signature font family (${i.join(`, `)})`).option(`--signature-font-size <signatureFontSize>`,`Signature font size (8-48 px)`).option(`--signature-font-weight <signatureFontWeight>`,`Signature font weight (100-900)`).action(async(e,i)=>{let c=o(i),[l,...f]=e;if(l==null)throw new a("Missing content command. Use `content next <deviceId>`, `content list <deviceId>`, `content text <deviceId>`, `content image <deviceId>`, or `content canvas <deviceId>`.",{code:`MISSING_SUBCOMMAND`});if(l===`next`){let[e,...t]=f;if(typeof e!=`string`||e.length===0)throw new a("Missing device serial number. Usage: `content next <deviceId>`.",{code:`MISSING_DEVICE_ID`});if(t.length>0)throw new a(`Unused args: ${t.map(e=>`\`${e}\``).join(`, `)}`,{code:`UNUSED_ARGS`});y(i);let n={type:`content-next`,response:await c.createClient().content.next({deviceId:e})};s(c,n);return}if(l===`list`){let[e,...t]=f;if(typeof e!=`string`||e.length===0)throw new a("Missing device serial number. Usage: `content list <deviceId> --task-type <fixed|loop>`.",{code:`MISSING_DEVICE_ID`});if(t.length>0)throw new a(`Unused args: ${t.map(e=>`\`${e}\``).join(`, `)}`,{code:`UNUSED_ARGS`});let n=v(`task-type`,i.taskType,r);if(n==null)throw new a(`Missing required option \`--task-type <taskType>\`. Expected one of: ${r.join(`, `)}.`,{code:`MISSING_TASK_TYPE`});b(i);let o={type:`content-list`,tasks:await c.createClient().content.list({deviceId:e,taskType:n})};s(c,o);return}if(l===`text`){let[e,...t]=f;if(typeof e!=`string`||e.length===0)throw new a("Missing device serial number. Usage: `content text <deviceId> --message <message>`.",{code:`MISSING_DEVICE_ID`});if(t.length>0)throw new a(`Unused args: ${t.map(e=>`\`${e}\``).join(`, `)}`,{code:`UNUSED_ARGS`});u(i);let n=d(i),r=g(i.taskAlias),o={type:`content-text`,response:await c.createClient().content.pushText({deviceId:e},{message:i.message,title:i.title,signature:i.signature,icon:i.icon,link:i.link,refreshNow:i.refreshNow,taskKey:i.taskKey,taskAlias:r,styles:n})};s(c,o);return}if(l===`image`){let[e,...r]=f;if(typeof e!=`string`||e.length===0)throw new a("Missing device serial number. Usage: `content image <deviceId> --file <file>`.",{code:`MISSING_DEVICE_ID`});if(r.length>0)throw new a(`Unused args: ${r.map(e=>`\`${e}\``).join(`, `)}`,{code:`UNUSED_ARGS`});let o=_(i.border),l=v(`dither-type`,i.ditherType,n),u=v(`dither-kernel`,i.ditherKernel,t),d=g(i.taskAlias),{image:p,source:m}=await w(i),h={type:`content-image`,file:m,response:await c.createClient().content.pushImage({deviceId:e},{image:p,refreshNow:i.refreshNow,link:i.link,border:o,ditherType:l,ditherKernel:u,taskKey:i.taskKey,taskAlias:d})};s(c,h);return}if(l===`canvas`){let[e,...t]=f;if(typeof e!=`string`||e.length===0)throw new a("Missing device serial number. Usage: `content canvas <deviceId> --file <windowData.json>`.",{code:`MISSING_DEVICE_ID`});if(t.length>0)throw new a(`Unused args: ${t.map(e=>`\`${e}\``).join(`, `)}`,{code:`UNUSED_ARGS`});let n=i.file;if(typeof n!=`string`||n.length===0)throw new a("Missing required option `--file <windowData.json>`.",{code:`MISSING_FILE`});let r=_(i.border),o=g(i.taskAlias),l=await T(`file`,n),u=typeof i.data==`string`&&i.data.length>0?await T(`data`,i.data):void 0,d=typeof i.layoutFullTw==`string`&&i.layoutFullTw.length>0?{tw:i.layoutFullTw}:void 0,p={type:`content-canvas`,file:n,response:await c.createClient().canvas.pushCanvas({deviceId:e},{windowData:l,data:u,layoutFull:d,refreshNow:i.refreshNow,link:i.link,border:r,taskKey:i.taskKey,taskAlias:o})};s(c,p);return}throw new a(`Unknown content command \`${l}\`.`,{code:`UNKNOWN_SUBCOMMAND`})})}function u(e){if(![e.title,e.message,e.signature].some(e=>typeof e==`string`&&e.length>0))throw new a("At least one of `--title`, `--message`, or `--signature` must be provided for `content text`.",{code:`MISSING_TEXT_CONTENT`})}function d(e){let t=f({fontFamily:p(`title-font-family`,e.titleFontFamily),fontSize:m(`title-font-size`,e.titleFontSize,{min:8,max:48}),fontWeight:h(`title-font-weight`,e.titleFontWeight)}),n=f({fontFamily:p(`message-font-family`,e.messageFontFamily),fontSize:m(`message-font-size`,e.messageFontSize,{min:8,max:48}),fontWeight:h(`message-font-weight`,e.messageFontWeight),lineHeight:m(`message-line-height`,e.messageLineHeight,{min:.8,max:3})}),r=f({fontFamily:p(`signature-font-family`,e.signatureFontFamily),fontSize:m(`signature-font-size`,e.signatureFontSize,{min:8,max:48}),fontWeight:h(`signature-font-weight`,e.signatureFontWeight)}),i=Object.keys(t).length>0,a=Object.keys(n).length>0,o=Object.keys(r).length>0;if(!(!i&&!a&&!o))return{...i&&{title:t},...a&&{message:n},...o&&{signature:r}}}function f(e){let t={};for(let[n,r]of Object.entries(e))r!==void 0&&(t[n]=r);return t}function p(e,t){if(t!=null){if(typeof t!=`string`||!i.includes(t))throw new a(`Invalid --${e}. Expected one of: ${i.join(`, `)}.`,{code:`INVALID_${e.replaceAll(`-`,`_`).toUpperCase()}`});return t}}function m(e,t,n){if(t==null)return;let r=Number(t);if(Number.isNaN(r)||r<n.min||r>n.max)throw new a(`Invalid --${e}: ${t}. Expected a number between ${n.min} and ${n.max}.`,{code:`INVALID_${e.replaceAll(`-`,`_`).toUpperCase()}`});return r}function h(e,t){if(t==null)return;let n=Number(t);if(Number.isNaN(n)||n<100||n>900||n%100!=0)throw new a(`Invalid --${e}: ${t}. Expected a font weight between 100 and 900 and divisible by 100.`,{code:`INVALID_${e.replaceAll(`-`,`_`).toUpperCase()}`});return n}function g(e){if(e!=null){if(typeof e!=`string`||e.length>100)throw new a(`Invalid --task-alias. Expected a string with a maximum length of 100 characters.`,{code:`INVALID_TASK_ALIAS`});return e}}function _(t){if(t==null)return;let n=Number(t);if(Number.isNaN(n)||!e.includes(n))throw new a(`Invalid value for --border. Expected one of: ${e.join(`, `)}.`,{code:`INVALID_BORDER`});return n}function v(e,t,n){if(t!=null){if(typeof t!=`string`||!n.includes(t))throw new a(`Invalid value for --${e}. Expected one of: ${n.join(`, `)}.`,{code:`INVALID_${e.replaceAll(`-`,`_`).toUpperCase()}`});return t}}function y(e){C(`content next`,e,[`taskType`,`refreshNow`,`link`,`border`,`ditherType`,`ditherKernel`,`taskKey`,`taskAlias`,`message`,`title`,`signature`,`icon`,`titleFontFamily`,`titleFontSize`,`titleFontWeight`,`messageFontFamily`,`messageFontSize`,`messageFontWeight`,`messageLineHeight`,`signatureFontFamily`,`signatureFontSize`,`signatureFontWeight`,...x])}function b(e){C(`content list`,e,[`refreshNow`,`link`,`border`,`ditherType`,`ditherKernel`,`taskKey`,`taskAlias`,`message`,`title`,`signature`,`icon`,`titleFontFamily`,`titleFontSize`,`titleFontWeight`,`messageFontFamily`,`messageFontSize`,`messageFontWeight`,`messageLineHeight`,`signatureFontFamily`,`signatureFontSize`,`signatureFontWeight`,...x])}const x=[`file`,`url`,`data`,`layoutFullTw`],S={taskType:`task-type`,refreshNow:`refresh-now`,ditherType:`dither-type`,ditherKernel:`dither-kernel`,taskKey:`task-key`,taskAlias:`task-alias`,layoutFullTw:`layout-full-tw`,titleFontFamily:`title-font-family`,titleFontSize:`title-font-size`,titleFontWeight:`title-font-weight`,messageFontFamily:`message-font-family`,messageFontSize:`message-font-size`,messageFontWeight:`message-font-weight`,messageLineHeight:`message-line-height`,signatureFontFamily:`signature-font-family`,signatureFontSize:`signature-font-size`,signatureFontWeight:`signature-font-weight`};function C(e,t,n){let r=n.flatMap(e=>t[e]==null?[]:[`--${S[e]??e}`]);if(r.length!==0)throw new a(`Unsupported option for \`${e}\`: ${r.join(`, `)}.`,{code:`UNSUPPORTED_OPTION`})}async function w(e){let t=typeof e.file==`string`&&e.file.length>0?e.file:null,n=typeof e.url==`string`&&e.url.length>0?e.url:null;if(t!=null&&n!=null)throw new a("Options `--file` and `--url` cannot be used together.",{code:`CONFLICTING_OPTIONS`});if(n!=null){if(!/^https?:\/\//.test(n)||n.length>2048)throw new a(`Invalid --url. Expected an http(s) URL with a maximum length of 2048 characters.`,{code:`INVALID_URL`});return{image:n,source:n}}if(t==null)throw new a("Missing required option `--file <file>` or `--url <url>`.",{code:`MISSING_FILE`});return{image:(await c.readFile(t)).toString(`base64`),source:t}}async function T(e,t){let n=await c.readFile(t,`utf8`);try{return JSON.parse(n)}catch{throw new a(`Invalid --${e}: ${t} is not valid JSON.`,{code:`INVALID_${e.replaceAll(`-`,`_`).toUpperCase()}`})}}export{l as registerContentCommands};
2
+ //# sourceMappingURL=content.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.mjs","names":[],"sources":["../../../src/cli/commands/content.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport type { CAC } from 'cac'\nimport { BORDER, DITHER_KERNELS, DITHER_TYPES, TASK_TYPES, TEXT_API_FONT_FAMILIES } from '../../api'\nimport type { TextStyles } from '../../api/modules/content'\nimport { createCliContext } from '../context'\nimport { CliError } from '../errors'\nimport { outputResult } from '../output'\nimport type {\n ContentCanvasResult,\n ContentImageResult,\n ContentListResult,\n ContentNextResult,\n ContentTextResult,\n GlobalCommandOptions,\n} from '../types'\n\ninterface ContentCommandOptions extends GlobalCommandOptions {\n file?: string\n url?: string\n data?: string\n layoutFullTw?: string\n taskType?: string\n refreshNow?: boolean\n link?: string\n border?: string\n ditherType?: string\n ditherKernel?: string\n taskKey?: string\n taskAlias?: string\n message?: string\n title?: string\n signature?: string\n icon?: string\n titleFontFamily?: string\n titleFontSize?: string\n titleFontWeight?: string\n messageFontFamily?: string\n messageFontSize?: string\n messageFontWeight?: string\n messageLineHeight?: string\n signatureFontFamily?: string\n signatureFontSize?: string\n signatureFontWeight?: string\n}\n\nexport function registerContentCommands(cli: CAC) {\n cli\n .command('content [...args]', 'Manage content')\n .usage('content <command> [options]')\n .example('content next <deviceId>')\n .example('content list <deviceId> --task-type fixed')\n .example('content text <deviceId> --message \"Hello\"')\n .example('content image <deviceId> --file ./frame.png')\n .example('content image <deviceId> --url https://example.com/frame.png')\n .example('content canvas <deviceId> --file ./window.json')\n .option('-f, --file <file>', 'Path to image file, or windowData JSON file for `content canvas`')\n .option('--url <url>', 'http(s) image URL to push directly (alternative to --file)')\n .option('--data <data>', 'Path to data JSON file for `content canvas`')\n .option(\n '--layout-full-tw <layoutFullTw>',\n 'Tailwind classes overriding the FULL layout for `content canvas`',\n )\n .option('--task-type <taskType>', `Task type to list (${TASK_TYPES.join(', ')})`)\n .option('--refresh-now', 'Whether to refresh the device immediately')\n .option('--link <link>', 'Optional link to open when content is tapped')\n .option('--border <border>', 'Screen border color: 0 for white, 1 for black')\n .option('--dither-type <ditherType>', `Dithering algorithm to use (${DITHER_TYPES.join(', ')})`)\n .option(\n '--dither-kernel <ditherKernel>',\n `Dithering kernel to use (${DITHER_KERNELS.join(', ')})`,\n )\n .option(\n '--task-key <taskKey>',\n 'Task key to identify the target Text/Image API content when multiple exist on the device',\n )\n .option('--task-alias <taskAlias>', 'Alias to distinguish the task in the device task list')\n .option('--message <message>', 'Text message body')\n .option('--title <title>', 'Text title')\n .option('--signature <signature>', 'Text signature')\n .option('--icon <icon>', 'PNG Base64 icon data or http(s) image URL')\n .option(\n '--title-font-family <titleFontFamily>',\n `Title font family (${TEXT_API_FONT_FAMILIES.join(', ')})`,\n )\n .option('--title-font-size <titleFontSize>', 'Title font size (8-48 px)')\n .option('--title-font-weight <titleFontWeight>', 'Title font weight (100-900)')\n .option(\n '--message-font-family <messageFontFamily>',\n `Message font family (${TEXT_API_FONT_FAMILIES.join(', ')})`,\n )\n .option('--message-font-size <messageFontSize>', 'Message font size (8-48 px)')\n .option('--message-font-weight <messageFontWeight>', 'Message font weight (100-900)')\n .option('--message-line-height <messageLineHeight>', 'Message line height (0.8-3)')\n .option(\n '--signature-font-family <signatureFontFamily>',\n `Signature font family (${TEXT_API_FONT_FAMILIES.join(', ')})`,\n )\n .option('--signature-font-size <signatureFontSize>', 'Signature font size (8-48 px)')\n .option('--signature-font-weight <signatureFontWeight>', 'Signature font weight (100-900)')\n .action(async (args: string[], options: ContentCommandOptions) => {\n const context = createCliContext(options)\n const [subcommand, ...rest] = args\n\n if (subcommand == null) {\n throw new CliError(\n 'Missing content command. Use `content next <deviceId>`, `content list <deviceId>`, `content text <deviceId>`, `content image <deviceId>`, or `content canvas <deviceId>`.',\n {\n code: 'MISSING_SUBCOMMAND',\n },\n )\n }\n\n if (subcommand === 'next') {\n const [deviceId, ...unused] = rest\n\n if (typeof deviceId !== 'string' || deviceId.length === 0) {\n throw new CliError('Missing device serial number. Usage: `content next <deviceId>`.', {\n code: 'MISSING_DEVICE_ID',\n })\n }\n\n if (unused.length > 0) {\n throw new CliError(`Unused args: ${unused.map(value => `\\`${value}\\``).join(', ')}`, {\n code: 'UNUSED_ARGS',\n })\n }\n\n assertNoNextOptions(options)\n\n const result: ContentNextResult = {\n type: 'content-next',\n response: await context.createClient().content.next({ deviceId }),\n }\n\n outputResult(context, result)\n return\n }\n\n if (subcommand === 'list') {\n const [deviceId, ...unused] = rest\n\n if (typeof deviceId !== 'string' || deviceId.length === 0) {\n throw new CliError(\n 'Missing device serial number. Usage: `content list <deviceId> --task-type <fixed|loop>`.',\n {\n code: 'MISSING_DEVICE_ID',\n },\n )\n }\n\n if (unused.length > 0) {\n throw new CliError(`Unused args: ${unused.map(value => `\\`${value}\\``).join(', ')}`, {\n code: 'UNUSED_ARGS',\n })\n }\n\n const taskType = parseChoice('task-type', options.taskType, TASK_TYPES)\n\n if (taskType == null) {\n throw new CliError(\n `Missing required option \\`--task-type <taskType>\\`. Expected one of: ${TASK_TYPES.join(', ')}.`,\n {\n code: 'MISSING_TASK_TYPE',\n },\n )\n }\n\n assertNoListOptions(options)\n\n const result: ContentListResult = {\n type: 'content-list',\n tasks: await context.createClient().content.list({ deviceId, taskType }),\n }\n\n outputResult(context, result)\n return\n }\n\n if (subcommand === 'text') {\n const [deviceId, ...unused] = rest\n\n if (typeof deviceId !== 'string' || deviceId.length === 0) {\n throw new CliError(\n 'Missing device serial number. Usage: `content text <deviceId> --message <message>`.',\n {\n code: 'MISSING_DEVICE_ID',\n },\n )\n }\n\n if (unused.length > 0) {\n throw new CliError(`Unused args: ${unused.map(value => `\\`${value}\\``).join(', ')}`, {\n code: 'UNUSED_ARGS',\n })\n }\n\n assertAtLeastOneTextField(options)\n\n const styles = buildTextStyles(options)\n const taskAlias = parseTaskAlias(options.taskAlias)\n\n const result: ContentTextResult = {\n type: 'content-text',\n response: await context.createClient().content.pushText(\n { deviceId },\n {\n message: options.message,\n title: options.title,\n signature: options.signature,\n icon: options.icon,\n link: options.link,\n refreshNow: options.refreshNow,\n taskKey: options.taskKey,\n taskAlias,\n styles,\n },\n ),\n }\n\n outputResult(context, result)\n return\n }\n\n if (subcommand === 'image') {\n const [deviceId, ...unused] = rest\n\n if (typeof deviceId !== 'string' || deviceId.length === 0) {\n throw new CliError(\n 'Missing device serial number. Usage: `content image <deviceId> --file <file>`.',\n {\n code: 'MISSING_DEVICE_ID',\n },\n )\n }\n\n if (unused.length > 0) {\n throw new CliError(`Unused args: ${unused.map(value => `\\`${value}\\``).join(', ')}`, {\n code: 'UNUSED_ARGS',\n })\n }\n\n const border = parseBorder(options.border)\n const ditherType = parseChoice('dither-type', options.ditherType, DITHER_TYPES)\n const ditherKernel = parseChoice('dither-kernel', options.ditherKernel, DITHER_KERNELS)\n const taskAlias = parseTaskAlias(options.taskAlias)\n const { image, source } = await resolveImageSource(options)\n\n const result: ContentImageResult = {\n type: 'content-image',\n file: source,\n response: await context.createClient().content.pushImage(\n { deviceId },\n {\n image,\n refreshNow: options.refreshNow,\n link: options.link,\n border,\n ditherType,\n ditherKernel,\n taskKey: options.taskKey,\n taskAlias,\n },\n ),\n }\n\n outputResult(context, result)\n return\n }\n\n if (subcommand === 'canvas') {\n const [deviceId, ...unused] = rest\n\n if (typeof deviceId !== 'string' || deviceId.length === 0) {\n throw new CliError(\n 'Missing device serial number. Usage: `content canvas <deviceId> --file <windowData.json>`.',\n {\n code: 'MISSING_DEVICE_ID',\n },\n )\n }\n\n if (unused.length > 0) {\n throw new CliError(`Unused args: ${unused.map(value => `\\`${value}\\``).join(', ')}`, {\n code: 'UNUSED_ARGS',\n })\n }\n\n const filePath = options.file\n\n if (typeof filePath !== 'string' || filePath.length === 0) {\n throw new CliError('Missing required option `--file <windowData.json>`.', {\n code: 'MISSING_FILE',\n })\n }\n\n const border = parseBorder(options.border)\n const taskAlias = parseTaskAlias(options.taskAlias)\n const windowData = await readJsonFile('file', filePath)\n const data =\n typeof options.data === 'string' && options.data.length > 0\n ? await readJsonFile('data', options.data)\n : undefined\n const layoutFull =\n typeof options.layoutFullTw === 'string' && options.layoutFullTw.length > 0\n ? { tw: options.layoutFullTw }\n : undefined\n\n const result: ContentCanvasResult = {\n type: 'content-canvas',\n file: filePath,\n response: await context.createClient().canvas.pushCanvas(\n { deviceId },\n {\n windowData,\n data,\n layoutFull,\n refreshNow: options.refreshNow,\n link: options.link,\n border,\n taskKey: options.taskKey,\n taskAlias,\n },\n ),\n }\n\n outputResult(context, result)\n return\n }\n\n throw new CliError(`Unknown content command \\`${subcommand}\\`.`, {\n code: 'UNKNOWN_SUBCOMMAND',\n })\n })\n}\n\nfunction assertAtLeastOneTextField(options: ContentCommandOptions) {\n const hasField = [options.title, options.message, options.signature].some(\n value => typeof value === 'string' && value.length > 0,\n )\n\n if (!hasField) {\n throw new CliError(\n 'At least one of `--title`, `--message`, or `--signature` must be provided for `content text`.',\n {\n code: 'MISSING_TEXT_CONTENT',\n },\n )\n }\n}\n\nfunction buildTextStyles(options: ContentCommandOptions): TextStyles | undefined {\n const title = definedEntries({\n fontFamily: parseOptionalFontFamily('title-font-family', options.titleFontFamily),\n fontSize: parseOptionalNumberInRange('title-font-size', options.titleFontSize, {\n min: 8,\n max: 48,\n }),\n fontWeight: parseOptionalFontWeight('title-font-weight', options.titleFontWeight),\n })\n\n const message = definedEntries({\n fontFamily: parseOptionalFontFamily('message-font-family', options.messageFontFamily),\n fontSize: parseOptionalNumberInRange('message-font-size', options.messageFontSize, {\n min: 8,\n max: 48,\n }),\n fontWeight: parseOptionalFontWeight('message-font-weight', options.messageFontWeight),\n lineHeight: parseOptionalNumberInRange('message-line-height', options.messageLineHeight, {\n min: 0.8,\n max: 3,\n }),\n })\n\n const signature = definedEntries({\n fontFamily: parseOptionalFontFamily('signature-font-family', options.signatureFontFamily),\n fontSize: parseOptionalNumberInRange('signature-font-size', options.signatureFontSize, {\n min: 8,\n max: 48,\n }),\n fontWeight: parseOptionalFontWeight('signature-font-weight', options.signatureFontWeight),\n })\n\n const hasTitle = Object.keys(title).length > 0\n const hasMessage = Object.keys(message).length > 0\n const hasSignature = Object.keys(signature).length > 0\n\n if (!hasTitle && !hasMessage && !hasSignature) {\n return undefined\n }\n\n return {\n ...(hasTitle && { title }),\n ...(hasMessage && { message }),\n ...(hasSignature && { signature }),\n } as TextStyles\n}\n\nfunction definedEntries<T extends Record<string, unknown>>(obj: T): Partial<T> {\n const result: Partial<T> = {}\n\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key as keyof T] = value as T[keyof T]\n }\n }\n\n return result\n}\n\nfunction parseOptionalFontFamily(name: string, value: unknown) {\n if (value == null) {\n return undefined\n }\n\n if (\n typeof value !== 'string' ||\n !TEXT_API_FONT_FAMILIES.includes(value as (typeof TEXT_API_FONT_FAMILIES)[number])\n ) {\n throw new CliError(\n `Invalid --${name}. Expected one of: ${TEXT_API_FONT_FAMILIES.join(', ')}.`,\n {\n code: `INVALID_${name.replaceAll('-', '_').toUpperCase()}`,\n },\n )\n }\n\n return value as (typeof TEXT_API_FONT_FAMILIES)[number]\n}\n\nfunction parseOptionalNumberInRange(\n name: string,\n value: unknown,\n range: { min: number; max: number },\n) {\n if (value == null) {\n return undefined\n }\n\n const parsed = Number(value)\n\n if (Number.isNaN(parsed) || parsed < range.min || parsed > range.max) {\n throw new CliError(\n `Invalid --${name}: ${value}. Expected a number between ${range.min} and ${range.max}.`,\n {\n code: `INVALID_${name.replaceAll('-', '_').toUpperCase()}`,\n },\n )\n }\n\n return parsed\n}\n\nfunction parseOptionalFontWeight(name: string, value: unknown) {\n if (value == null) {\n return undefined\n }\n\n const parsed = Number(value)\n\n if (Number.isNaN(parsed) || parsed < 100 || parsed > 900 || parsed % 100 !== 0) {\n throw new CliError(\n `Invalid --${name}: ${value}. Expected a font weight between 100 and 900 and divisible by 100.`,\n {\n code: `INVALID_${name.replaceAll('-', '_').toUpperCase()}`,\n },\n )\n }\n\n return parsed\n}\n\nfunction parseTaskAlias(value: unknown) {\n if (value == null) {\n return undefined\n }\n\n if (typeof value !== 'string' || value.length > 100) {\n throw new CliError(\n 'Invalid --task-alias. Expected a string with a maximum length of 100 characters.',\n {\n code: 'INVALID_TASK_ALIAS',\n },\n )\n }\n\n return value\n}\n\nfunction parseBorder(value: unknown) {\n if (value == null) {\n return undefined\n }\n\n const parsed = Number(value)\n\n if (Number.isNaN(parsed) || !BORDER.includes(parsed as (typeof BORDER)[number])) {\n throw new CliError(`Invalid value for --border. Expected one of: ${BORDER.join(', ')}.`, {\n code: 'INVALID_BORDER',\n })\n }\n\n return parsed as (typeof BORDER)[number]\n}\n\nfunction parseChoice<T extends readonly string[]>(name: string, value: unknown, choices: T) {\n if (value == null) {\n return undefined\n }\n\n if (typeof value !== 'string' || !choices.includes(value as T[number])) {\n throw new CliError(`Invalid value for --${name}. Expected one of: ${choices.join(', ')}.`, {\n code: `INVALID_${name.replaceAll('-', '_').toUpperCase()}`,\n })\n }\n\n return value as T[number]\n}\n\nfunction assertNoNextOptions(options: ContentCommandOptions) {\n assertNoOptionsFor('content next', options, [\n 'taskType',\n 'refreshNow',\n 'link',\n 'border',\n 'ditherType',\n 'ditherKernel',\n 'taskKey',\n 'taskAlias',\n 'message',\n 'title',\n 'signature',\n 'icon',\n 'titleFontFamily',\n 'titleFontSize',\n 'titleFontWeight',\n 'messageFontFamily',\n 'messageFontSize',\n 'messageFontWeight',\n 'messageLineHeight',\n 'signatureFontFamily',\n 'signatureFontSize',\n 'signatureFontWeight',\n ...SHARED_FILE_OPTIONS,\n ])\n}\n\nfunction assertNoListOptions(options: ContentCommandOptions) {\n assertNoOptionsFor('content list', options, [\n 'refreshNow',\n 'link',\n 'border',\n 'ditherType',\n 'ditherKernel',\n 'taskKey',\n 'taskAlias',\n 'message',\n 'title',\n 'signature',\n 'icon',\n 'titleFontFamily',\n 'titleFontSize',\n 'titleFontWeight',\n 'messageFontFamily',\n 'messageFontSize',\n 'messageFontWeight',\n 'messageLineHeight',\n 'signatureFontFamily',\n 'signatureFontSize',\n 'signatureFontWeight',\n ...SHARED_FILE_OPTIONS,\n ])\n}\n\nconst SHARED_FILE_OPTIONS = ['file', 'url', 'data', 'layoutFullTw'] as const\n\nconst OPTION_FLAG_NAMES: Record<string, string> = {\n taskType: 'task-type',\n refreshNow: 'refresh-now',\n ditherType: 'dither-type',\n ditherKernel: 'dither-kernel',\n taskKey: 'task-key',\n taskAlias: 'task-alias',\n layoutFullTw: 'layout-full-tw',\n titleFontFamily: 'title-font-family',\n titleFontSize: 'title-font-size',\n titleFontWeight: 'title-font-weight',\n messageFontFamily: 'message-font-family',\n messageFontSize: 'message-font-size',\n messageFontWeight: 'message-font-weight',\n messageLineHeight: 'message-line-height',\n signatureFontFamily: 'signature-font-family',\n signatureFontSize: 'signature-font-size',\n signatureFontWeight: 'signature-font-weight',\n}\n\nfunction assertNoOptionsFor(\n command: string,\n options: ContentCommandOptions,\n keys: readonly string[],\n) {\n const unsupportedOptions = keys.flatMap(key =>\n options[key as keyof ContentCommandOptions] == null\n ? []\n : [`--${OPTION_FLAG_NAMES[key] ?? key}`],\n )\n\n if (unsupportedOptions.length === 0) {\n return\n }\n\n throw new CliError(`Unsupported option for \\`${command}\\`: ${unsupportedOptions.join(', ')}.`, {\n code: 'UNSUPPORTED_OPTION',\n })\n}\n\nasync function resolveImageSource(options: ContentCommandOptions) {\n const filePath = typeof options.file === 'string' && options.file.length > 0 ? options.file : null\n const url = typeof options.url === 'string' && options.url.length > 0 ? options.url : null\n\n if (filePath != null && url != null) {\n throw new CliError('Options `--file` and `--url` cannot be used together.', {\n code: 'CONFLICTING_OPTIONS',\n })\n }\n\n if (url != null) {\n if (!/^https?:\\/\\//.test(url) || url.length > 2048) {\n throw new CliError(\n 'Invalid --url. Expected an http(s) URL with a maximum length of 2048 characters.',\n {\n code: 'INVALID_URL',\n },\n )\n }\n\n return { image: url, source: url }\n }\n\n if (filePath == null) {\n throw new CliError('Missing required option `--file <file>` or `--url <url>`.', {\n code: 'MISSING_FILE',\n })\n }\n\n const file = await fs.readFile(filePath)\n\n return { image: file.toString('base64'), source: filePath }\n}\n\nasync function readJsonFile(name: string, filePath: string) {\n const raw = await fs.readFile(filePath, 'utf8')\n\n try {\n return JSON.parse(raw) as Record<string, unknown>\n } catch {\n throw new CliError(`Invalid --${name}: ${filePath} is not valid JSON.`, {\n code: `INVALID_${name.replaceAll('-', '_').toUpperCase()}`,\n })\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{CliError as e}from"../errors.mjs";import{createCliContext as t}from"../context.mjs";import{outputResult as n}from"../output.mjs";function r(r){r.command(`device [...args]`,`Manage devices`).usage(`device <command> [options]`).example(`device list`).example(`device status <deviceId>`).example(`device settings <deviceId>`).example(`device settings <deviceId> --alias "Desk" --timezone Asia/Shanghai`).option(`--alias <alias>`,`Device alias (pass an empty string to clear)`).option(`--location <location>`,`Device location (pass an empty string to clear)`).option(`--timezone <timezone>`,"Timezone key from `timezone list`").option(`--power-ms <powerMs>`,`Refresh interval on power, in milliseconds (60000-43200000)`).option(`--battery-ms <batteryMs>`,`Wake-up refresh interval on battery, in milliseconds (60000-43200000)`).option(`--sleep-start <sleepStart>`,`Sleep start time in HH:mm (device local time)`).option(`--sleep-end <sleepEnd>`,`Sleep end time in HH:mm (device local time)`).option(`--sleep-disabled`,`Disable sleep mode`).action(async(r,a)=>{let o=t(a),[c,...l]=r;if(c==null)throw new e("Missing device command. Use `device list`, `device status <deviceId>`, or `device settings <deviceId>`.",{code:`MISSING_SUBCOMMAND`});if(c===`list`){if(l.length>0)throw new e(`Unused args: ${l.map(e=>`\`${e}\``).join(`, `)}`,{code:`UNUSED_ARGS`});s(a,`device list`);let t={type:`device-list`,devices:await o.createClient().device.list()};n(o,t);return}if(c===`status`){let[t,...r]=l;if(typeof t!=`string`||t.length===0)throw new e("Missing device serial number. Usage: `device status <deviceId>`.",{code:`MISSING_DEVICE_ID`});if(r.length>0)throw new e(`Unused args: ${r.map(e=>`\`${e}\``).join(`, `)}`,{code:`UNUSED_ARGS`});s(a,`device status`);let i={type:`device-status`,device:await o.createClient().device.status({deviceId:t})};n(o,i);return}if(c===`settings`){let[t,...r]=l;if(typeof t!=`string`||t.length===0)throw new e("Missing device serial number. Usage: `device settings <deviceId>`.",{code:`MISSING_DEVICE_ID`});if(r.length>0)throw new e(`Unused args: ${r.map(e=>`\`${e}\``).join(`, `)}`,{code:`UNUSED_ARGS`});let s;if(a.sleepDisabled===!0&&a.sleepStart==null&&a.sleepEnd==null){let e=await o.createClient().device.getSettings({deviceId:t});s=e.sleep==null?void 0:{start:e.sleep.start,end:e.sleep.end}}let c=i(a,s);if(c==null){let e={type:`device-settings`,deviceId:t,settings:await o.createClient().device.getSettings({deviceId:t})};n(o,e);return}let u={type:`device-settings-update`,response:await o.createClient().device.updateSettings({deviceId:t},c)};n(o,u);return}throw new e(`Unknown device command \`${c}\`.`,{code:`UNKNOWN_SUBCOMMAND`})})}function i(t,n){let r={};if(t.alias!=null){if(t.alias.length>100)throw new e(`Invalid --alias. Expected a string with a maximum length of 100 characters.`,{code:`INVALID_ALIAS`});r.alias=t.alias}if(t.location!=null){if(t.location.length>100)throw new e(`Invalid --location. Expected a string with a maximum length of 100 characters.`,{code:`INVALID_LOCATION`});r.location=t.location}t.timezone!=null&&(r.timezone=t.timezone);let i=a(`power-ms`,t.powerMs),s=a(`battery-ms`,t.batteryMs);if((i!=null||s!=null)&&(r.interval={...i!=null&&{powerMs:i},...s!=null&&{batteryMs:s}}),t.sleepDisabled===!0){if(t.sleepStart!=null||t.sleepEnd!=null)throw new e("Option `--sleep-disabled` cannot be used together with `--sleep-start` or `--sleep-end`.",{code:`CONFLICTING_OPTIONS`});r.sleep={enabled:!1,start:n?.start??`00:00`,end:n?.end??`23:59`}}else if(t.sleepStart!=null||t.sleepEnd!=null){if(t.sleepStart==null||t.sleepEnd==null)throw new e("Options `--sleep-start` and `--sleep-end` must be provided together.",{code:`MISSING_SLEEP_TIME`});if(o(`sleep-start`,t.sleepStart),o(`sleep-end`,t.sleepEnd),t.sleepStart===t.sleepEnd)throw new e("Invalid sleep time: `--sleep-start` and `--sleep-end` cannot be equal.",{code:`INVALID_SLEEP_TIME`});r.sleep={enabled:!0,start:t.sleepStart,end:t.sleepEnd}}if(Object.keys(r).length!==0)return r}function a(t,n){if(n==null)return;let r=Number(n);if(!Number.isInteger(r)||r<6e4||r>432e5||r%6e4!=0)throw new e(`Invalid --${t}: ${n}. Expected a multiple of 60000 between 60000 and 43200000.`,{code:`INVALID_${t.replaceAll(`-`,`_`).toUpperCase()}`});return r}function o(t,n){if(!/^([01]\d|2[0-3]):[0-5]\d$/.test(n))throw new e(`Invalid --${t}: ${n}. Expected a time in HH:mm (24-hour) format.`,{code:`INVALID_${t.replaceAll(`-`,`_`).toUpperCase()}`})}function s(t,n){let r=[[`alias`,t.alias],[`location`,t.location],[`timezone`,t.timezone],[`power-ms`,t.powerMs],[`battery-ms`,t.batteryMs],[`sleep-start`,t.sleepStart],[`sleep-end`,t.sleepEnd],[`sleep-disabled`,t.sleepDisabled]].flatMap(([e,t])=>t==null?[]:[e]);if(r.length!==0)throw new e(`Unsupported option for \`${n}\`: ${r.map(e=>`--${e}`).join(`, `)}.`,{code:`UNSUPPORTED_OPTION`})}export{r as registerDeviceCommands};
2
+ //# sourceMappingURL=device.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.mjs","names":[],"sources":["../../../src/cli/commands/device.ts"],"sourcesContent":["import type { CAC } from 'cac'\nimport type { DeviceSettings } from '../../api/modules/device'\nimport { createCliContext } from '../context'\nimport { CliError } from '../errors'\nimport { outputResult } from '../output'\nimport type {\n DeviceListResult,\n DeviceSettingsResult,\n DeviceSettingsUpdateResult,\n DeviceStatusResult,\n GlobalCommandOptions,\n} from '../types'\n\ninterface DeviceCommandOptions extends GlobalCommandOptions {\n alias?: string\n location?: string\n timezone?: string\n powerMs?: string\n batteryMs?: string\n sleepStart?: string\n sleepEnd?: string\n sleepDisabled?: boolean\n}\n\nexport function registerDeviceCommands(cli: CAC) {\n cli\n .command('device [...args]', 'Manage devices')\n .usage('device <command> [options]')\n .example('device list')\n .example('device status <deviceId>')\n .example('device settings <deviceId>')\n .example('device settings <deviceId> --alias \"Desk\" --timezone Asia/Shanghai')\n .option('--alias <alias>', 'Device alias (pass an empty string to clear)')\n .option('--location <location>', 'Device location (pass an empty string to clear)')\n .option('--timezone <timezone>', 'Timezone key from `timezone list`')\n .option('--power-ms <powerMs>', 'Refresh interval on power, in milliseconds (60000-43200000)')\n .option(\n '--battery-ms <batteryMs>',\n 'Wake-up refresh interval on battery, in milliseconds (60000-43200000)',\n )\n .option('--sleep-start <sleepStart>', 'Sleep start time in HH:mm (device local time)')\n .option('--sleep-end <sleepEnd>', 'Sleep end time in HH:mm (device local time)')\n .option('--sleep-disabled', 'Disable sleep mode')\n .action(async (args: string[], options: DeviceCommandOptions) => {\n const context = createCliContext(options)\n const [subcommand, ...rest] = args\n\n if (subcommand == null) {\n throw new CliError(\n 'Missing device command. Use `device list`, `device status <deviceId>`, or `device settings <deviceId>`.',\n {\n code: 'MISSING_SUBCOMMAND',\n },\n )\n }\n\n if (subcommand === 'list') {\n if (rest.length > 0) {\n throw new CliError(`Unused args: ${rest.map(value => `\\`${value}\\``).join(', ')}`, {\n code: 'UNUSED_ARGS',\n })\n }\n\n assertNoSettingsOptions(options, 'device list')\n\n const result: DeviceListResult = {\n type: 'device-list',\n devices: await context.createClient().device.list(),\n }\n\n outputResult(context, result)\n return\n }\n\n if (subcommand === 'status') {\n const [deviceId, ...unused] = rest\n\n if (typeof deviceId !== 'string' || deviceId.length === 0) {\n throw new CliError('Missing device serial number. Usage: `device status <deviceId>`.', {\n code: 'MISSING_DEVICE_ID',\n })\n }\n\n if (unused.length > 0) {\n throw new CliError(`Unused args: ${unused.map(value => `\\`${value}\\``).join(', ')}`, {\n code: 'UNUSED_ARGS',\n })\n }\n\n assertNoSettingsOptions(options, 'device status')\n\n const result: DeviceStatusResult = {\n type: 'device-status',\n device: await context.createClient().device.status({ deviceId }),\n }\n\n outputResult(context, result)\n return\n }\n\n if (subcommand === 'settings') {\n const [deviceId, ...unused] = rest\n\n if (typeof deviceId !== 'string' || deviceId.length === 0) {\n throw new CliError('Missing device serial number. Usage: `device settings <deviceId>`.', {\n code: 'MISSING_DEVICE_ID',\n })\n }\n\n if (unused.length > 0) {\n throw new CliError(`Unused args: ${unused.map(value => `\\`${value}\\``).join(', ')}`, {\n code: 'UNUSED_ARGS',\n })\n }\n\n // When disabling sleep without explicit times, reuse the device's current\n // sleep window: the API requires all three sleep fields and start !== end.\n let currentSleep: { start: string; end: string } | undefined\n if (\n options.sleepDisabled === true &&\n options.sleepStart == null &&\n options.sleepEnd == null\n ) {\n const current = await context.createClient().device.getSettings({ deviceId })\n currentSleep =\n current.sleep != null\n ? { start: current.sleep.start, end: current.sleep.end }\n : undefined\n }\n\n const settings = buildDeviceSettings(options, currentSleep)\n\n if (settings == null) {\n const result: DeviceSettingsResult = {\n type: 'device-settings',\n deviceId,\n settings: await context.createClient().device.getSettings({ deviceId }),\n }\n\n outputResult(context, result)\n return\n }\n\n const result: DeviceSettingsUpdateResult = {\n type: 'device-settings-update',\n response: await context.createClient().device.updateSettings({ deviceId }, settings),\n }\n\n outputResult(context, result)\n return\n }\n\n throw new CliError(`Unknown device command \\`${subcommand}\\`.`, {\n code: 'UNKNOWN_SUBCOMMAND',\n })\n })\n}\n\nfunction buildDeviceSettings(\n options: DeviceCommandOptions,\n currentSleep?: { start: string; end: string },\n): DeviceSettings | undefined {\n const settings: DeviceSettings = {}\n\n if (options.alias != null) {\n if (options.alias.length > 100) {\n throw new CliError(\n 'Invalid --alias. Expected a string with a maximum length of 100 characters.',\n {\n code: 'INVALID_ALIAS',\n },\n )\n }\n\n settings.alias = options.alias\n }\n\n if (options.location != null) {\n if (options.location.length > 100) {\n throw new CliError(\n 'Invalid --location. Expected a string with a maximum length of 100 characters.',\n {\n code: 'INVALID_LOCATION',\n },\n )\n }\n\n settings.location = options.location\n }\n\n if (options.timezone != null) {\n settings.timezone = options.timezone\n }\n\n const powerMs = parseInterval('power-ms', options.powerMs)\n const batteryMs = parseInterval('battery-ms', options.batteryMs)\n\n if (powerMs != null || batteryMs != null) {\n settings.interval = {\n ...(powerMs != null && { powerMs }),\n ...(batteryMs != null && { batteryMs }),\n }\n }\n\n if (options.sleepDisabled === true) {\n if (options.sleepStart != null || options.sleepEnd != null) {\n throw new CliError(\n 'Option `--sleep-disabled` cannot be used together with `--sleep-start` or `--sleep-end`.',\n {\n code: 'CONFLICTING_OPTIONS',\n },\n )\n }\n\n settings.sleep = {\n enabled: false,\n start: currentSleep?.start ?? '00:00',\n end: currentSleep?.end ?? '23:59',\n }\n } else if (options.sleepStart != null || options.sleepEnd != null) {\n if (options.sleepStart == null || options.sleepEnd == null) {\n throw new CliError('Options `--sleep-start` and `--sleep-end` must be provided together.', {\n code: 'MISSING_SLEEP_TIME',\n })\n }\n\n assertSleepTime('sleep-start', options.sleepStart)\n assertSleepTime('sleep-end', options.sleepEnd)\n\n if (options.sleepStart === options.sleepEnd) {\n throw new CliError('Invalid sleep time: `--sleep-start` and `--sleep-end` cannot be equal.', {\n code: 'INVALID_SLEEP_TIME',\n })\n }\n\n settings.sleep = { enabled: true, start: options.sleepStart, end: options.sleepEnd }\n }\n\n if (Object.keys(settings).length === 0) {\n return undefined\n }\n\n return settings\n}\n\nfunction parseInterval(name: string, value: unknown) {\n if (value == null) {\n return undefined\n }\n\n const parsed = Number(value)\n\n if (!Number.isInteger(parsed) || parsed < 60000 || parsed > 43200000 || parsed % 60000 !== 0) {\n throw new CliError(\n `Invalid --${name}: ${value}. Expected a multiple of 60000 between 60000 and 43200000.`,\n {\n code: `INVALID_${name.replaceAll('-', '_').toUpperCase()}`,\n },\n )\n }\n\n return parsed\n}\n\nfunction assertSleepTime(name: string, value: string) {\n if (!/^([01]\\d|2[0-3]):[0-5]\\d$/.test(value)) {\n throw new CliError(`Invalid --${name}: ${value}. Expected a time in HH:mm (24-hour) format.`, {\n code: `INVALID_${name.replaceAll('-', '_').toUpperCase()}`,\n })\n }\n}\n\nfunction assertNoSettingsOptions(options: DeviceCommandOptions, command: string) {\n const unsupportedOptions = [\n ['alias', options.alias],\n ['location', options.location],\n ['timezone', options.timezone],\n ['power-ms', options.powerMs],\n ['battery-ms', options.batteryMs],\n ['sleep-start', options.sleepStart],\n ['sleep-end', options.sleepEnd],\n ['sleep-disabled', options.sleepDisabled],\n ].flatMap(([name, value]) => (value == null ? [] : [name]))\n\n if (unsupportedOptions.length === 0) {\n return\n }\n\n throw new CliError(\n `Unsupported option for \\`${command}\\`: ${unsupportedOptions\n .map(name => `--${name}`)\n .join(', ')}.`,\n {\n code: 'UNSUPPORTED_OPTION',\n },\n )\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{CliError as e}from"../errors.mjs";import{createCliContext as t}from"../context.mjs";import{outputResult as n}from"../output.mjs";function r(r){r.command(`timezone [...args]`,`Manage timezones`).usage(`timezone <command> [options]`).example(`timezone list`).action(async(r,i)=>{let a=t(i),[o,...s]=r;if(o==null)throw new e("Missing timezone command. Use `timezone list`.",{code:`MISSING_SUBCOMMAND`});if(o===`list`){if(s.length>0)throw new e(`Unused args: ${s.map(e=>`\`${e}\``).join(`, `)}`,{code:`UNUSED_ARGS`});let t={type:`timezone-list`,timezones:await a.createClient().timezone.list()};n(a,t);return}throw new e(`Unknown timezone command \`${o}\`.`,{code:`UNKNOWN_SUBCOMMAND`})})}export{r as registerTimezoneCommands};
2
+ //# sourceMappingURL=timezone.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timezone.mjs","names":[],"sources":["../../../src/cli/commands/timezone.ts"],"sourcesContent":["import type { CAC } from 'cac'\nimport { createCliContext } from '../context'\nimport { CliError } from '../errors'\nimport { outputResult } from '../output'\nimport type { GlobalCommandOptions, TimezoneListResult } from '../types'\n\nexport function registerTimezoneCommands(cli: CAC) {\n cli\n .command('timezone [...args]', 'Manage timezones')\n .usage('timezone <command> [options]')\n .example('timezone list')\n .action(async (args: string[], options: GlobalCommandOptions) => {\n const context = createCliContext(options)\n const [subcommand, ...rest] = args\n\n if (subcommand == null) {\n throw new CliError('Missing timezone command. Use `timezone list`.', {\n code: 'MISSING_SUBCOMMAND',\n })\n }\n\n if (subcommand === 'list') {\n if (rest.length > 0) {\n throw new CliError(`Unused args: ${rest.map(value => `\\`${value}\\``).join(', ')}`, {\n code: 'UNUSED_ARGS',\n })\n }\n\n const result: TimezoneListResult = {\n type: 'timezone-list',\n timezones: await context.createClient().timezone.list(),\n }\n\n outputResult(context, result)\n return\n }\n\n throw new CliError(`Unknown timezone command \\`${subcommand}\\`.`, {\n code: 'UNKNOWN_SUBCOMMAND',\n })\n })\n}\n"],"mappings":"wIAMA,SAAgB,EAAyB,EAAU,CACjD,EACG,QAAQ,qBAAsB,kBAAkB,CAAC,CACjD,MAAM,8BAA8B,CAAC,CACrC,QAAQ,eAAe,CAAC,CACxB,OAAO,MAAO,EAAgB,IAAkC,CAC/D,IAAM,EAAU,EAAiB,CAAO,EAClC,CAAC,EAAY,GAAG,GAAQ,EAE9B,GAAI,GAAc,KAChB,MAAM,IAAI,EAAS,iDAAkD,CACnE,KAAM,oBACR,CAAC,EAGH,GAAI,IAAe,OAAQ,CACzB,GAAI,EAAK,OAAS,EAChB,MAAM,IAAI,EAAS,gBAAgB,EAAK,IAAI,GAAS,KAAK,EAAM,GAAG,CAAC,CAAC,KAAK,IAAI,IAAK,CACjF,KAAM,aACR,CAAC,EAGH,IAAM,EAA6B,CACjC,KAAM,gBACN,UAAW,MAAM,EAAQ,aAAa,CAAC,CAAC,SAAS,KAAK,CACxD,EAEA,EAAa,EAAS,CAAM,EAC5B,MACF,CAEA,MAAM,IAAI,EAAS,8BAA8B,EAAW,KAAM,CAChE,KAAM,oBACR,CAAC,CACH,CAAC,CACL"}
@@ -0,0 +1,2 @@
1
+ import e from"../api/index.mjs";import t from"../config.mjs";import{CliError as n}from"./errors.mjs";function r(r={}){return{json:r.json===!0,config:t,createClient(){let r=t.get(`apiKey`,``);if(r.length===0)throw new n("Missing API key. Run `quote0 auth` first.",{code:`MISSING_API_KEY`});return new e({apiKey:r})}}}export{r as createCliContext};
2
+ //# sourceMappingURL=context.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.mjs","names":[],"sources":["../../src/cli/context.ts"],"sourcesContent":["import Quote0 from '../api'\nimport config from '../config'\nimport { CliError } from './errors'\nimport type { GlobalCommandOptions } from './types'\n\nexport interface CliContext {\n readonly json: boolean\n readonly config: typeof config\n createClient(): Quote0\n}\n\nexport function createCliContext(options: GlobalCommandOptions = {}): CliContext {\n return {\n json: options.json === true,\n config,\n createClient() {\n const apiKey = config.get('apiKey', '')\n\n if (apiKey.length === 0) {\n throw new CliError('Missing API key. Run `quote0 auth` first.', {\n code: 'MISSING_API_KEY',\n })\n }\n\n return new Quote0({ apiKey })\n },\n }\n}\n"],"mappings":"qGAWA,SAAgB,EAAiB,EAAgC,CAAC,EAAe,CAC/E,MAAO,CACL,KAAM,EAAQ,OAAS,GACvB,SACA,cAAe,CACb,IAAM,EAAS,EAAO,IAAI,SAAU,EAAE,EAEtC,GAAI,EAAO,SAAW,EACpB,MAAM,IAAI,EAAS,4CAA6C,CAC9D,KAAM,iBACR,CAAC,EAGH,OAAO,IAAI,EAAO,CAAE,QAAO,CAAC,CAC9B,CACF,CACF"}
@@ -0,0 +1,2 @@
1
+ var e=class extends Error{code;exitCode;constructor(e,t){super(e),this.name=`CliError`,this.code=t?.code??`CLI_ERROR`,this.exitCode=t?.exitCode??1}};function t(t){return t instanceof e?t:t instanceof Error?new e(t.message):new e(`An unknown error occurred.`)}export{e as CliError,t as toCliError};
2
+ //# sourceMappingURL=errors.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../../src/cli/errors.ts"],"sourcesContent":["export class CliError extends Error {\n readonly code: string\n readonly exitCode: number\n\n constructor(message: string, options?: { code?: string; exitCode?: number }) {\n super(message)\n this.name = 'CliError'\n this.code = options?.code ?? 'CLI_ERROR'\n this.exitCode = options?.exitCode ?? 1\n }\n}\n\nexport function toCliError(error: unknown) {\n if (error instanceof CliError) {\n return error\n }\n\n if (error instanceof Error) {\n return new CliError(error.message)\n }\n\n return new CliError('An unknown error occurred.')\n}\n"],"mappings":"AAAA,IAAa,EAAb,cAA8B,KAAM,CAClC,KACA,SAEA,YAAY,EAAiB,EAAgD,CAC3E,MAAM,CAAO,EACb,KAAK,KAAO,WACZ,KAAK,KAAO,GAAS,MAAQ,YAC7B,KAAK,SAAW,GAAS,UAAY,CACvC,CACF,EAEA,SAAgB,EAAW,EAAgB,CASzC,OARI,aAAiB,EACZ,EAGL,aAAiB,MACZ,IAAI,EAAS,EAAM,OAAO,EAG5B,IAAI,EAAS,4BAA4B,CAClD"}
@@ -0,0 +1,2 @@
1
+ import{CliError as e}from"./errors.mjs";import{handleCliError as t}from"./output.mjs";import{buildCli as n}from"./app.mjs";async function r(r=process.argv){let i=n();try{if(i.parse(r,{run:!1}),i.matchedCommand==null){let[t]=i.args;throw t==null?new e(`Please specify a command.`,{code:`MISSING_COMMAND`}):new e(`Unknown command \`${t}\`.`,{code:`UNKNOWN_COMMAND`})}await i.runMatchedCommand()}catch(e){t(e,r.includes(`--json`))}}export{r as runCli};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/cli/index.ts"],"sourcesContent":["import { buildCli } from './app'\nimport { CliError } from './errors'\nimport { handleCliError } from './output'\n\nexport async function runCli(argv = process.argv) {\n const cli = buildCli()\n\n try {\n cli.parse(argv, { run: false })\n\n if (cli.matchedCommand == null) {\n const [command] = cli.args\n\n if (command == null) {\n throw new CliError('Please specify a command.', {\n code: 'MISSING_COMMAND',\n })\n }\n\n throw new CliError(`Unknown command \\`${command}\\`.`, {\n code: 'UNKNOWN_COMMAND',\n })\n }\n\n await cli.runMatchedCommand()\n } catch (error) {\n handleCliError(error, argv.includes('--json'))\n }\n}\n"],"mappings":"2HAIA,eAAsB,EAAO,EAAO,QAAQ,KAAM,CAChD,IAAM,EAAM,EAAS,EAErB,GAAI,CAGF,GAFA,EAAI,MAAM,EAAM,CAAE,IAAK,EAAM,CAAC,EAE1B,EAAI,gBAAkB,KAAM,CAC9B,GAAM,CAAC,GAAW,EAAI,KAQtB,MANI,GAAW,KACP,IAAI,EAAS,4BAA6B,CAC9C,KAAM,iBACR,CAAC,EAGG,IAAI,EAAS,qBAAqB,EAAQ,KAAM,CACpD,KAAM,iBACR,CAAC,CACH,CAEA,MAAM,EAAI,kBAAkB,CAC9B,OAAS,EAAO,CACd,EAAe,EAAO,EAAK,SAAS,QAAQ,CAAC,CAC/C,CACF"}
@@ -0,0 +1,4 @@
1
+ import{toCliError as e}from"./errors.mjs";import{ErrorView as t,ResultView as n}from"./views/ResultView.mjs";import{render as r}from"ink";import"react";import{jsx as i}from"react/jsx-runtime";function a(e,t){if(e.json){process.stdout.write(JSON.stringify(t,null,2)+`
2
+ `);return}r(i(n,{result:t}))}function o(n,a=process.argv.includes(`--json`)){let o=e(n);a?process.stderr.write(JSON.stringify({error:{code:o.code,message:o.message}},null,2)+`
3
+ `):r(i(t,{message:o.message,code:o.code})),process.exitCode=o.exitCode}export{o as handleCliError,a as outputResult};
4
+ //# sourceMappingURL=output.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.mjs","names":[],"sources":["../../src/cli/output.tsx"],"sourcesContent":["import { render } from 'ink'\nimport React from 'react'\nimport { toCliError } from './errors'\nimport type { CliContext } from './context'\nimport type { CliResult } from './types'\nimport { ErrorView, ResultView } from './views/ResultView'\n\nexport function outputResult(context: CliContext, result: CliResult) {\n if (context.json) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n')\n return\n }\n\n render(<ResultView result={result} />)\n}\n\nexport function handleCliError(error: unknown, json = process.argv.includes('--json')) {\n const cliError = toCliError(error)\n\n if (json) {\n process.stderr.write(\n JSON.stringify(\n {\n error: {\n code: cliError.code,\n message: cliError.message,\n },\n },\n null,\n 2,\n ) + '\\n',\n )\n } else {\n render(<ErrorView message={cliError.message} code={cliError.code} />)\n }\n\n process.exitCode = cliError.exitCode\n}\n"],"mappings":"gMAOA,SAAgB,EAAa,EAAqB,EAAmB,CACnE,GAAI,EAAQ,KAAM,CAChB,QAAQ,OAAO,MAAM,KAAK,UAAU,EAAQ,KAAM,CAAC,EAAI;CAAI,EAC3D,MACF,CAEA,EAAO,EAAC,EAAD,CAAoB,QAAS,CAAA,CAAC,CACvC,CAEA,SAAgB,EAAe,EAAgB,EAAO,QAAQ,KAAK,SAAS,QAAQ,EAAG,CACrF,IAAM,EAAW,EAAW,CAAK,EAE7B,EACF,QAAQ,OAAO,MACb,KAAK,UACH,CACE,MAAO,CACL,KAAM,EAAS,KACf,QAAS,EAAS,OACpB,CACF,EACA,KACA,CACF,EAAI;CACN,EAEA,EAAO,EAAC,EAAD,CAAW,QAAS,EAAS,QAAS,KAAM,EAAS,IAAO,CAAA,CAAC,EAGtE,QAAQ,SAAW,EAAS,QAC9B"}
@@ -0,0 +1,2 @@
1
+ import e from"../../components/Container.mjs";import t from"../../components/ListItem.mjs";import{SectionList as n}from"../../components/Section.mjs";import{Text as r}from"ink";import"react";import{UncontrolledTextInput as i}from"ink-text-input";import{jsx as a,jsxs as o}from"react/jsx-runtime";function s({initialValue:s,onSubmit:c,submitted:l}){return a(e,{children:o(n,{children:[a(t,{children:a(r,{children:`Authentication`})}),l?a(r,{dimColor:!0,children:`API key saved`}):a(i,{initialValue:s,onSubmit:c,placeholder:`API key...`,mask:`*`})]})})}export{s as default};
2
+ //# sourceMappingURL=AuthPrompt.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthPrompt.mjs","names":[],"sources":["../../../src/cli/views/AuthPrompt.tsx"],"sourcesContent":["import { Text } from 'ink'\nimport { UncontrolledTextInput } from 'ink-text-input'\nimport React from 'react'\nimport Container from '../../components/Container'\nimport ListItem from '../../components/ListItem'\nimport { SectionList } from '../../components/Section'\n\nexport interface AuthPromptProps {\n initialValue: string\n onSubmit: (value: string) => void\n submitted: boolean\n}\n\nexport default function AuthPrompt({ initialValue, onSubmit, submitted }: AuthPromptProps) {\n return (\n <Container>\n <SectionList>\n <ListItem>\n <Text>Authentication</Text>\n </ListItem>\n {!submitted ? (\n <UncontrolledTextInput\n initialValue={initialValue}\n onSubmit={onSubmit}\n placeholder=\"API key...\"\n mask=\"*\"\n />\n ) : (\n <Text dimColor>API key saved</Text>\n )}\n </SectionList>\n </Container>\n )\n}\n"],"mappings":"wSAaA,SAAwB,EAAW,CAAE,eAAc,WAAU,aAA8B,CACzF,OACE,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAM,gBAAoB,CAAA,CAClB,CAAA,EACR,EAQA,EAAC,EAAD,CAAM,SAAA,GAAS,SAAA,eAAmB,CAAA,EAPlC,EAAC,EAAD,CACgB,eACJ,WACV,YAAY,aACZ,KAAK,GACN,CAAA,CAIQ,CAAA,CAAA,CACJ,CAAA,CAEf"}
@@ -0,0 +1,2 @@
1
+ import e from"../../components/Container.mjs";import t from"../../components/ListItem.mjs";import{SectionList as n}from"../../components/Section.mjs";import{Box as r,Text as i}from"ink";import{jsx as a,jsxs as o}from"react/jsx-runtime";import{Table as s}from"@kud/ink-ui";function c(e){return e.map(e=>({key:e.key,name:e.name,utcOffsetMinutes:e.utcOffsetMinutes,utcOffsetLabel:e.utcOffsetLabel}))}function l({result:l}){if(l.type===`device-list`)return a(e,{children:o(n,{children:[a(t,{trailing:o(i,{dimColor:!0,children:[l.devices.length,`/`,l.devices.length]}),children:a(i,{children:`Devices`})}),l.devices.length===0?a(t,{children:a(i,{dimColor:!0,children:`No devices found`})}):l.devices.map(e=>o(r,{flexDirection:`column`,children:[a(t,{trailing:a(i,{children:e.id}),children:a(i,{dimColor:!0,children:`ID`})}),a(t,{trailing:a(i,{children:e.series}),children:a(i,{dimColor:!0,children:`Series`})}),a(t,{trailing:a(i,{children:e.model}),children:a(i,{dimColor:!0,children:`Model`})}),a(t,{trailing:a(i,{children:e.edition}),children:a(i,{dimColor:!0,children:`Edition`})})]},e.id))]})});if(l.type===`device-status`){let{device:s}=l;return a(e,{children:o(n,{children:[a(t,{trailing:o(i,{children:[a(i,{dimColor:!0,children:`Serial Number: `}),s.deviceId]}),children:o(r,{gap:1,children:[a(i,{children:s.alias??`Unnamed device`}),s.location&&a(i,{dimColor:!0,children:s.location}),a(i,{dimColor:!0,children:s.status.battery})]})}),a(r,{flexDirection:`column`,children:[[`Status`,s.status.current],[`Battery`,s.status.battery],[`Wi-Fi`,s.status.wifi],[`Last Render`,s.renderInfo.last],[`Next Render (Battery)`,s.renderInfo.next.battery],[`Next Render (Power)`,s.renderInfo.next.power],[`Current Images`,String(s.renderInfo.current.image?.length??0)],[`Version`,`v${s.status.version}`]].map(([e,n])=>a(t,{trailing:a(i,{children:n}),children:a(i,{dimColor:!0,children:e})},e))})]})})}if(l.type===`device-settings`){let{settings:s}=l;return a(e,{children:o(n,{children:[a(t,{trailing:a(i,{dimColor:!0,children:l.deviceId}),children:a(i,{children:`Device Settings`})}),a(r,{flexDirection:`column`,children:[[`Alias`,s.alias??`-`],[`Location`,s.location??`-`],[`Timezone`,s.timezone??`-`],[`Interval (Power)`,s.interval?.powerMs==null?`-`:`${s.interval.powerMs} ms`],[`Interval (Battery)`,s.interval?.batteryMs==null?`-`:`${s.interval.batteryMs} ms`],[`Sleep`,s.sleep==null?`-`:s.sleep.enabled?`${s.sleep.start} - ${s.sleep.end}`:`Disabled`]].map(([e,n])=>a(t,{trailing:a(i,{children:n}),children:a(i,{dimColor:!0,children:e})},e))})]})})}return l.type===`device-settings-update`?a(e,{children:o(n,{children:[a(i,{children:`Update Device Settings`}),a(t,{children:a(i,{children:l.response.message})})]})}):l.type===`content-next`?a(e,{children:o(n,{children:[a(i,{children:`Next Content`}),a(t,{children:a(i,{children:l.response.message})})]})}):l.type===`content-text`?a(e,{children:o(n,{children:[a(i,{children:`Push Text`}),a(t,{children:a(i,{children:l.response.message})})]})}):l.type===`timezone-list`?a(e,{children:o(n,{children:[a(t,{trailing:o(i,{dimColor:!0,children:[l.timezones.length,`/`,l.timezones.length]}),children:a(i,{children:`Timezones`})}),l.timezones.length===0?a(t,{children:a(i,{dimColor:!0,children:`No timezones found`})}):a(s,{columns:[{key:`key`,header:`Key`},{key:`name`,header:`Name`},{key:`utcOffsetLabel`,header:`Offset`},{key:`utcOffsetMinutes`,header:`Minutes`}],data:c(l.timezones)})]})}):l.type===`content-list`?a(e,{children:o(n,{children:[a(t,{trailing:o(i,{dimColor:!0,children:[l.tasks.length,`/`,l.tasks.length]}),children:a(i,{children:`Tasks`})}),l.tasks.length===0?a(t,{children:a(i,{dimColor:!0,children:`No tasks found`})}):l.tasks.map((e,n)=>o(r,{flexDirection:`column`,children:[a(t,{trailing:a(i,{children:e.type}),children:a(i,{dimColor:!0,children:e.key??`(no key)`})}),e.title!=null&&a(t,{trailing:a(i,{children:e.title}),children:a(i,{dimColor:!0,children:`Title`})}),e.message!=null&&a(t,{trailing:a(i,{children:e.message}),children:a(i,{dimColor:!0,children:`Message`})})]},e.key??n))]})}):l.type===`content-canvas`?a(e,{children:o(n,{children:[a(i,{children:`Push Canvas`}),a(t,{trailing:a(i,{dimColor:!0,children:l.file}),children:a(i,{children:l.response.message})})]})}):a(e,{children:o(n,{children:[a(i,{children:`Push Image`}),a(t,{trailing:a(i,{dimColor:!0,children:l.file}),children:a(i,{children:l.response.message})})]})})}function u({message:r,code:s}){return a(e,{children:o(n,{children:[a(t,{trailing:a(i,{dimColor:!0,children:s}),children:a(i,{children:`Error`})}),a(t,{children:a(i,{children:r})})]})})}export{u as ErrorView,l as ResultView};
2
+ //# sourceMappingURL=ResultView.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResultView.mjs","names":[],"sources":["../../../src/cli/views/ResultView.tsx"],"sourcesContent":["import { Box, Text } from 'ink'\nimport { Table } from '@kud/ink-ui'\nimport Container from '../../components/Container'\nimport ListItem from '../../components/ListItem'\nimport { SectionList } from '../../components/Section'\nimport type { Timezone } from '../../api/modules/timezone'\nimport type { CliResult } from '../types'\n\ntype TimezoneTableRow = {\n [key: string]: string | number\n key: string\n name: string\n utcOffsetMinutes: number\n utcOffsetLabel: string\n}\n\nfunction toTimezoneRows(timezones: Timezone[]): TimezoneTableRow[] {\n return timezones.map(timezone => ({\n key: timezone.key,\n name: timezone.name,\n utcOffsetMinutes: timezone.utcOffsetMinutes,\n utcOffsetLabel: timezone.utcOffsetLabel,\n }))\n}\n\nexport function ResultView({ result }: { result: CliResult }) {\n if (result.type === 'device-list') {\n return (\n <Container>\n <SectionList>\n <ListItem\n trailing={\n <Text dimColor>\n {result.devices.length}/{result.devices.length}\n </Text>\n }\n >\n <Text>Devices</Text>\n </ListItem>\n {result.devices.length === 0 ? (\n <ListItem>\n <Text dimColor>No devices found</Text>\n </ListItem>\n ) : (\n result.devices.map(device => (\n <Box key={device.id} flexDirection=\"column\">\n <ListItem trailing={<Text>{device.id}</Text>}>\n <Text dimColor>ID</Text>\n </ListItem>\n <ListItem trailing={<Text>{device.series}</Text>}>\n <Text dimColor>Series</Text>\n </ListItem>\n <ListItem trailing={<Text>{device.model}</Text>}>\n <Text dimColor>Model</Text>\n </ListItem>\n <ListItem trailing={<Text>{device.edition}</Text>}>\n <Text dimColor>Edition</Text>\n </ListItem>\n </Box>\n ))\n )}\n </SectionList>\n </Container>\n )\n }\n\n if (result.type === 'device-status') {\n const { device } = result\n\n return (\n <Container>\n <SectionList>\n <ListItem\n trailing={\n <Text>\n <Text dimColor>Serial Number: </Text>\n {device.deviceId}\n </Text>\n }\n >\n <Box gap={1}>\n <Text>{device.alias ?? 'Unnamed device'}</Text>\n {device.location && <Text dimColor>{device.location}</Text>}\n <Text dimColor>{device.status.battery}</Text>\n </Box>\n </ListItem>\n <Box flexDirection=\"column\">\n {[\n ['Status', device.status.current],\n ['Battery', device.status.battery],\n ['Wi-Fi', device.status.wifi],\n ['Last Render', device.renderInfo.last],\n ['Next Render (Battery)', device.renderInfo.next.battery],\n ['Next Render (Power)', device.renderInfo.next.power],\n ['Current Images', String(device.renderInfo.current.image?.length ?? 0)],\n ['Version', `v${device.status.version}`],\n ].map(([label, value]) => (\n <ListItem key={label} trailing={<Text>{value}</Text>}>\n <Text dimColor>{label}</Text>\n </ListItem>\n ))}\n </Box>\n </SectionList>\n </Container>\n )\n }\n\n if (result.type === 'device-settings') {\n const { settings } = result\n\n return (\n <Container>\n <SectionList>\n <ListItem trailing={<Text dimColor>{result.deviceId}</Text>}>\n <Text>Device Settings</Text>\n </ListItem>\n <Box flexDirection=\"column\">\n {[\n ['Alias', settings.alias ?? '-'],\n ['Location', settings.location ?? '-'],\n ['Timezone', settings.timezone ?? '-'],\n [\n 'Interval (Power)',\n settings.interval?.powerMs != null ? `${settings.interval.powerMs} ms` : '-',\n ],\n [\n 'Interval (Battery)',\n settings.interval?.batteryMs != null ? `${settings.interval.batteryMs} ms` : '-',\n ],\n [\n 'Sleep',\n settings.sleep != null\n ? settings.sleep.enabled\n ? `${settings.sleep.start} - ${settings.sleep.end}`\n : 'Disabled'\n : '-',\n ],\n ].map(([label, value]) => (\n <ListItem key={label} trailing={<Text>{value}</Text>}>\n <Text dimColor>{label}</Text>\n </ListItem>\n ))}\n </Box>\n </SectionList>\n </Container>\n )\n }\n\n if (result.type === 'device-settings-update') {\n return (\n <Container>\n <SectionList>\n <Text>Update Device Settings</Text>\n <ListItem>\n <Text>{result.response.message}</Text>\n </ListItem>\n </SectionList>\n </Container>\n )\n }\n\n if (result.type === 'content-next') {\n return (\n <Container>\n <SectionList>\n <Text>Next Content</Text>\n <ListItem>\n <Text>{result.response.message}</Text>\n </ListItem>\n </SectionList>\n </Container>\n )\n }\n\n if (result.type === 'content-text') {\n return (\n <Container>\n <SectionList>\n <Text>Push Text</Text>\n <ListItem>\n <Text>{result.response.message}</Text>\n </ListItem>\n </SectionList>\n </Container>\n )\n }\n\n if (result.type === 'timezone-list') {\n return (\n <Container>\n <SectionList>\n <ListItem\n trailing={\n <Text dimColor>\n {result.timezones.length}/{result.timezones.length}\n </Text>\n }\n >\n <Text>Timezones</Text>\n </ListItem>\n {result.timezones.length === 0 ? (\n <ListItem>\n <Text dimColor>No timezones found</Text>\n </ListItem>\n ) : (\n <Table\n columns={[\n { key: 'key', header: 'Key' },\n { key: 'name', header: 'Name' },\n { key: 'utcOffsetLabel', header: 'Offset' },\n { key: 'utcOffsetMinutes', header: 'Minutes' },\n ]}\n data={toTimezoneRows(result.timezones)}\n />\n )}\n </SectionList>\n </Container>\n )\n }\n\n if (result.type === 'content-list') {\n return (\n <Container>\n <SectionList>\n <ListItem\n trailing={\n <Text dimColor>\n {result.tasks.length}/{result.tasks.length}\n </Text>\n }\n >\n <Text>Tasks</Text>\n </ListItem>\n {result.tasks.length === 0 ? (\n <ListItem>\n <Text dimColor>No tasks found</Text>\n </ListItem>\n ) : (\n result.tasks.map((task, index) => (\n <Box key={task.key ?? index} flexDirection=\"column\">\n <ListItem trailing={<Text>{task.type}</Text>}>\n <Text dimColor>{task.key ?? '(no key)'}</Text>\n </ListItem>\n {task.title != null && (\n <ListItem trailing={<Text>{task.title}</Text>}>\n <Text dimColor>Title</Text>\n </ListItem>\n )}\n {task.message != null && (\n <ListItem trailing={<Text>{task.message}</Text>}>\n <Text dimColor>Message</Text>\n </ListItem>\n )}\n </Box>\n ))\n )}\n </SectionList>\n </Container>\n )\n }\n\n if (result.type === 'content-canvas') {\n return (\n <Container>\n <SectionList>\n <Text>Push Canvas</Text>\n <ListItem trailing={<Text dimColor>{result.file}</Text>}>\n <Text>{result.response.message}</Text>\n </ListItem>\n </SectionList>\n </Container>\n )\n }\n\n return (\n <Container>\n <SectionList>\n <Text>Push Image</Text>\n <ListItem trailing={<Text dimColor>{result.file}</Text>}>\n <Text>{result.response.message}</Text>\n </ListItem>\n </SectionList>\n </Container>\n )\n}\n\nexport function ErrorView({ message, code }: { message: string; code: string }) {\n return (\n <Container>\n <SectionList>\n <ListItem trailing={<Text dimColor>{code}</Text>}>\n <Text>Error</Text>\n </ListItem>\n <ListItem>\n <Text>{message}</Text>\n </ListItem>\n </SectionList>\n </Container>\n )\n}\n"],"mappings":"gRAgBA,SAAS,EAAe,EAA2C,CACjE,OAAO,EAAU,IAAI,IAAa,CAChC,IAAK,EAAS,IACd,KAAM,EAAS,KACf,iBAAkB,EAAS,iBAC3B,eAAgB,EAAS,cAC3B,EAAE,CACJ,CAEA,SAAgB,EAAW,CAAE,UAAiC,CAC5D,GAAI,EAAO,OAAS,cAClB,OACE,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CACE,SACE,EAAC,EAAD,CAAM,SAAA,GAAN,SAAA,CACG,EAAO,QAAQ,OAAO,IAAE,EAAO,QAAQ,MACpC,IAGR,SAAA,EAAC,EAAD,CAAA,SAAM,SAAa,CAAA,CACX,CAAA,EACT,EAAO,QAAQ,SAAW,EACzB,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAM,SAAA,GAAS,SAAA,kBAAsB,CAAA,CAC7B,CAAA,EAEV,EAAO,QAAQ,IAAI,GACjB,EAAC,EAAD,CAAqB,cAAc,SAAnC,SAAA,CACE,EAAC,EAAD,CAAU,SAAU,EAAC,EAAD,CAAA,SAAO,EAAO,EAAS,CAAA,EACzC,SAAA,EAAC,EAAD,CAAM,SAAA,GAAS,SAAA,IAAQ,CAAA,CACf,CAAA,EACV,EAAC,EAAD,CAAU,SAAU,EAAC,EAAD,CAAA,SAAO,EAAO,MAAa,CAAA,EAC7C,SAAA,EAAC,EAAD,CAAM,SAAA,GAAS,SAAA,QAAY,CAAA,CACnB,CAAA,EACV,EAAC,EAAD,CAAU,SAAU,EAAC,EAAD,CAAA,SAAO,EAAO,KAAY,CAAA,EAC5C,SAAA,EAAC,EAAD,CAAM,SAAA,GAAS,SAAA,OAAW,CAAA,CAClB,CAAA,EACV,EAAC,EAAD,CAAU,SAAU,EAAC,EAAD,CAAA,SAAO,EAAO,OAAc,CAAA,EAC9C,SAAA,EAAC,EAAD,CAAM,SAAA,GAAS,SAAA,SAAa,CAAA,CACpB,CAAA,CACP,CAbK,EAAA,EAAO,EAaZ,CACN,CAEQ,CAAA,CAAA,CACJ,CAAA,EAIf,GAAI,EAAO,OAAS,gBAAiB,CACnC,GAAM,CAAE,UAAW,EAEnB,OACE,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CACE,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAM,SAAA,GAAS,SAAA,iBAAqB,CAAA,EACnC,EAAO,QACJ,CAAA,CAAA,EAGR,SAAA,EAAC,EAAD,CAAK,IAAK,EAAV,SAAA,CACE,EAAC,EAAD,CAAA,SAAO,EAAO,OAAS,gBAAuB,CAAA,EAC7C,EAAO,UAAY,EAAC,EAAD,CAAM,SAAA,GAAU,SAAA,EAAO,QAAe,CAAA,EAC1D,EAAC,EAAD,CAAM,SAAA,GAAU,SAAA,EAAO,OAAO,OAAc,CAAA,CACzC,GACG,CAAA,EACV,EAAC,EAAD,CAAK,cAAc,SAChB,SAAA,CACC,CAAC,SAAU,EAAO,OAAO,OAAO,EAChC,CAAC,UAAW,EAAO,OAAO,OAAO,EACjC,CAAC,QAAS,EAAO,OAAO,IAAI,EAC5B,CAAC,cAAe,EAAO,WAAW,IAAI,EACtC,CAAC,wBAAyB,EAAO,WAAW,KAAK,OAAO,EACxD,CAAC,sBAAuB,EAAO,WAAW,KAAK,KAAK,EACpD,CAAC,iBAAkB,OAAO,EAAO,WAAW,QAAQ,OAAO,QAAU,CAAC,CAAC,EACvE,CAAC,UAAW,IAAI,EAAO,OAAO,SAAS,CACzC,CAAC,CAAC,KAAK,CAAC,EAAO,KACb,EAAC,EAAD,CAAsB,SAAU,EAAC,EAAD,CAAA,SAAO,CAAY,CAAA,EACjD,SAAA,EAAC,EAAD,CAAM,SAAA,GAAU,SAAA,CAAY,CAAA,CACpB,EAFK,CAEL,CACX,CACE,CAAA,CACM,CAAA,CAAA,CACJ,CAAA,CAEf,CAEA,GAAI,EAAO,OAAS,kBAAmB,CACrC,GAAM,CAAE,YAAa,EAErB,OACE,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAU,SAAU,EAAC,EAAD,CAAM,SAAA,GAAU,SAAA,EAAO,QAAe,CAAA,EACxD,SAAA,EAAC,EAAD,CAAA,SAAM,iBAAqB,CAAA,CACnB,CAAA,EACV,EAAC,EAAD,CAAK,cAAc,SAChB,SAAA,CACC,CAAC,QAAS,EAAS,OAAS,GAAG,EAC/B,CAAC,WAAY,EAAS,UAAY,GAAG,EACrC,CAAC,WAAY,EAAS,UAAY,GAAG,EACrC,CACE,mBACA,EAAS,UAAU,SAAW,KAA2C,IAApC,GAAG,EAAS,SAAS,QAAQ,IACpE,EACA,CACE,qBACA,EAAS,UAAU,WAAa,KAA6C,IAAtC,GAAG,EAAS,SAAS,UAAU,IACxE,EACA,CACE,QACA,EAAS,OAAS,KAId,IAHA,EAAS,MAAM,QACb,GAAG,EAAS,MAAM,MAAM,KAAK,EAAS,MAAM,MAC5C,UAER,CACF,CAAC,CAAC,KAAK,CAAC,EAAO,KACb,EAAC,EAAD,CAAsB,SAAU,EAAC,EAAD,CAAA,SAAO,CAAY,CAAA,EACjD,SAAA,EAAC,EAAD,CAAM,SAAA,GAAU,SAAA,CAAY,CAAA,CACpB,EAFK,CAEL,CACX,CACE,CAAA,CACM,CAAA,CAAA,CACJ,CAAA,CAEf,CAgIA,OA9HI,EAAO,OAAS,yBAEhB,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAA,SAAM,wBAA4B,CAAA,EAClC,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAO,EAAO,SAAS,OAAc,CAAA,CAC7B,CAAA,CACC,CAAA,CAAA,CACJ,CAAA,EAIX,EAAO,OAAS,eAEhB,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAA,SAAM,cAAkB,CAAA,EACxB,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAO,EAAO,SAAS,OAAc,CAAA,CAC7B,CAAA,CACC,CAAA,CAAA,CACJ,CAAA,EAIX,EAAO,OAAS,eAEhB,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAA,SAAM,WAAe,CAAA,EACrB,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAO,EAAO,SAAS,OAAc,CAAA,CAC7B,CAAA,CACC,CAAA,CAAA,CACJ,CAAA,EAIX,EAAO,OAAS,gBAEhB,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CACE,SACE,EAAC,EAAD,CAAM,SAAA,GAAN,SAAA,CACG,EAAO,UAAU,OAAO,IAAE,EAAO,UAAU,MACxC,IAGR,SAAA,EAAC,EAAD,CAAA,SAAM,WAAe,CAAA,CACb,CAAA,EACT,EAAO,UAAU,SAAW,EAC3B,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAM,SAAA,GAAS,SAAA,oBAAwB,CAAA,CAC/B,CAAA,EAEV,EAAC,EAAD,CACE,QAAS,CACP,CAAE,IAAK,MAAO,OAAQ,KAAM,EAC5B,CAAE,IAAK,OAAQ,OAAQ,MAAO,EAC9B,CAAE,IAAK,iBAAkB,OAAQ,QAAS,EAC1C,CAAE,IAAK,mBAAoB,OAAQ,SAAU,CAC/C,EACA,KAAM,EAAe,EAAO,SAAS,CACtC,CAAA,CAEQ,CAAA,CAAA,CACJ,CAAA,EAIX,EAAO,OAAS,eAEhB,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CACE,SACE,EAAC,EAAD,CAAM,SAAA,GAAN,SAAA,CACG,EAAO,MAAM,OAAO,IAAE,EAAO,MAAM,MAChC,IAGR,SAAA,EAAC,EAAD,CAAA,SAAM,OAAW,CAAA,CACT,CAAA,EACT,EAAO,MAAM,SAAW,EACvB,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAM,SAAA,GAAS,SAAA,gBAAoB,CAAA,CAC3B,CAAA,EAEV,EAAO,MAAM,KAAK,EAAM,IACtB,EAAC,EAAD,CAA6B,cAAc,SAA3C,SAAA,CACE,EAAC,EAAD,CAAU,SAAU,EAAC,EAAD,CAAA,SAAO,EAAK,IAAW,CAAA,EACzC,SAAA,EAAC,EAAD,CAAM,SAAA,GAAU,SAAA,EAAK,KAAO,UAAiB,CAAA,CACrC,CAAA,EACT,EAAK,OAAS,MACb,EAAC,EAAD,CAAU,SAAU,EAAC,EAAD,CAAA,SAAO,EAAK,KAAY,CAAA,EAC1C,SAAA,EAAC,EAAD,CAAM,SAAA,GAAS,SAAA,OAAW,CAAA,CAClB,CAAA,EAEX,EAAK,SAAW,MACf,EAAC,EAAD,CAAU,SAAU,EAAC,EAAD,CAAA,SAAO,EAAK,OAAc,CAAA,EAC5C,SAAA,EAAC,EAAD,CAAM,SAAA,GAAS,SAAA,SAAa,CAAA,CACpB,CAAA,CAET,CAdK,EAAA,EAAK,KAAO,CAcjB,CACN,CAEQ,CAAA,CAAA,CACJ,CAAA,EAIX,EAAO,OAAS,iBAEhB,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAA,SAAM,aAAiB,CAAA,EACvB,EAAC,EAAD,CAAU,SAAU,EAAC,EAAD,CAAM,SAAA,GAAU,SAAA,EAAO,IAAW,CAAA,EACpD,SAAA,EAAC,EAAD,CAAA,SAAO,EAAO,SAAS,OAAc,CAAA,CAC7B,CAAA,CACC,CAAA,CAAA,CACJ,CAAA,EAKb,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAA,SAAM,YAAgB,CAAA,EACtB,EAAC,EAAD,CAAU,SAAU,EAAC,EAAD,CAAM,SAAA,GAAU,SAAA,EAAO,IAAW,CAAA,EACpD,SAAA,EAAC,EAAD,CAAA,SAAO,EAAO,SAAS,OAAc,CAAA,CAC7B,CAAA,CACC,CAAA,CAAA,CACJ,CAAA,CAEf,CAEA,SAAgB,EAAU,CAAE,UAAS,QAA2C,CAC9E,OACE,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAU,SAAU,EAAC,EAAD,CAAM,SAAA,GAAU,SAAA,CAAW,CAAA,EAC7C,SAAA,EAAC,EAAD,CAAA,SAAM,OAAW,CAAA,CACT,CAAA,EACV,EAAC,EAAD,CAAA,SACE,EAAC,EAAD,CAAA,SAAO,CAAc,CAAA,CACb,CAAA,CACC,CAAA,CAAA,CACJ,CAAA,CAEf"}
@@ -1 +1 @@
1
- {"version":3,"file":"Container.mjs","names":[],"sources":["../../src/components/Container.tsx"],"sourcesContent":["import { Box } from 'ink'\nimport type React from 'react'\n\nexport default function Container({ ...props }: React.ComponentProps<typeof Box>) {\n return <Box borderStyle=\"round\" flexDirection=\"column\" {...props} />\n}\n"],"mappings":"kEAGA,SAAwB,EAAU,CAAE,GAAG,GAA2C,CAChF,OAAO,EAAC,EAAD,CAAK,YAAY,QAAQ,cAAc,SAAS,GAAI,EAAS,CAAA"}
1
+ {"version":3,"file":"Container.mjs","names":[],"sources":["../../src/components/Container.tsx"],"sourcesContent":["import { Box } from 'ink'\nimport type React from 'react'\n\nexport default function Container({ ...props }: React.ComponentProps<typeof Box>) {\n return <Box borderStyle=\"round\" flexDirection=\"column\" {...props} />\n}\n"],"mappings":"kEAGA,SAAwB,EAAU,CAAE,GAAG,GAA2C,CAChF,OAAO,EAAC,EAAD,CAAK,YAAY,QAAQ,cAAc,SAAS,GAAI,CAAQ,CAAA,CACrE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ListItem.mjs","names":[],"sources":["../../src/components/ListItem.tsx"],"sourcesContent":["import { Box, Text } from 'ink'\n\nexport default function ListItem({\n leading,\n children,\n trailing,\n ...props\n}: React.ComponentProps<typeof Box> & {\n leading?: React.ReactNode\n children?: React.ReactNode\n trailing?: React.ReactNode\n}) {\n return (\n <Box justifyContent=\"space-between\" {...props}>\n <Box>\n {leading && (\n <>\n {leading}\n <Text> </Text>\n </>\n )}\n {children}\n </Box>\n <Box>{trailing}</Box>\n </Box>\n )\n}\n"],"mappings":"oGAEA,SAAwB,EAAS,CAC/B,UACA,WACA,WACA,GAAG,GAKF,CACD,OACE,EAAC,EAAD,CAAK,eAAe,gBAAgB,GAAI,WAAxC,CACE,EAAC,EAAD,CAAA,SAAA,CACG,GACC,EAAA,EAAA,CAAA,SAAA,CACG,EACD,EAAC,EAAD,CAAA,SAAM,IAAQ,CAAA,CACb,CAAA,CAAA,CAEJ,EACG,CAAA,CAAA,CACN,EAAC,EAAD,CAAA,SAAM,EAAe,CAAA,CACjB"}
1
+ {"version":3,"file":"ListItem.mjs","names":[],"sources":["../../src/components/ListItem.tsx"],"sourcesContent":["import { Box, Text } from 'ink'\n\nexport default function ListItem({\n leading,\n children,\n trailing,\n ...props\n}: React.ComponentProps<typeof Box> & {\n leading?: React.ReactNode\n children?: React.ReactNode\n trailing?: React.ReactNode\n}) {\n return (\n <Box justifyContent=\"space-between\" {...props}>\n <Box>\n {leading && (\n <>\n {leading}\n <Text> </Text>\n </>\n )}\n {children}\n </Box>\n <Box>{trailing}</Box>\n </Box>\n )\n}\n"],"mappings":"oGAEA,SAAwB,EAAS,CAC/B,UACA,WACA,WACA,GAAG,GAKF,CACD,OACE,EAAC,EAAD,CAAK,eAAe,gBAAgB,GAAI,EAAxC,SAAA,CACE,EAAC,EAAD,CAAA,SAAA,CACG,GACC,EAAA,EAAA,CAAA,SAAA,CACG,EACD,EAAC,EAAD,CAAA,SAAM,GAAO,CAAA,CACb,CAAA,CAAA,EAEH,CACE,CAAA,CAAA,EACL,EAAC,EAAD,CAAA,SAAM,CAAc,CAAA,CACjB,GAET"}
@@ -1,2 +1,2 @@
1
- import e from"../utils/ink-props-helpers.mjs";import{Box as t}from"ink";import{jsx as n}from"react/jsx-runtime";import r from"react";function i({isLast:r,...i}){return n(t,{...r!==!0&&{borderStyle:`single`,borderDimColor:!0,...e.border(`bottom`)},paddingX:1,flexDirection:`column`,...i})}function a({children:e}){let t=r.Children.toArray(e);return r.Children.map(t,(e,r)=>n(i,{isLast:r===t.length-1,children:e}))}export{a as SectionList};
1
+ import e from"../utils/ink-props-helpers.mjs";import{Box as t}from"ink";import n from"react";import{jsx as r}from"react/jsx-runtime";function i({isLast:n,...i}){return r(t,{...n!==!0&&{borderStyle:`single`,borderDimColor:!0,...e.border(`bottom`)},paddingX:1,flexDirection:`column`,...i})}function a({children:e}){let t=n.Children.toArray(e);return n.Children.map(t,(e,n)=>r(i,{isLast:n===t.length-1,children:e}))}export{i as Section,i as default,a as SectionList};
2
2
  //# sourceMappingURL=Section.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Section.mjs","names":[],"sources":["../../src/components/Section.tsx"],"sourcesContent":["import { Box } from 'ink'\nimport { inkPropsHelpers } from '../utils'\nimport React from 'react'\n\nfunction Section({ isLast, ...props }: React.ComponentProps<typeof Box> & { isLast?: boolean }) {\n return (\n <Box\n {...(isLast !== true && {\n borderStyle: 'single',\n borderDimColor: true,\n ...inkPropsHelpers.border('bottom'),\n })}\n paddingX={1}\n flexDirection=\"column\"\n {...props}\n />\n )\n}\n\nfunction SectionList({ children }: { children: React.ReactNode }) {\n const arrayChildren = React.Children.toArray(children)\n return React.Children.map(arrayChildren, (child, i) => (\n <Section isLast={i === arrayChildren.length - 1}>{child}</Section>\n ))\n}\n\nexport { Section, SectionList }\nexport default Section\n"],"mappings":"qIAIA,SAAS,EAAQ,CAAE,SAAQ,GAAG,GAAkE,CAC9F,OACE,EAAC,EAAD,CACE,GAAK,IAAW,IAAQ,CACtB,YAAa,SACb,eAAgB,GAChB,GAAG,EAAgB,OAAO,SAAS,CACpC,CACD,SAAU,EACV,cAAc,SACd,GAAI,EACJ,CAAA,CAIN,SAAS,EAAY,CAAE,YAA2C,CAChE,IAAM,EAAgB,EAAM,SAAS,QAAQ,EAAS,CACtD,OAAO,EAAM,SAAS,IAAI,GAAgB,EAAO,IAC/C,EAAC,EAAD,CAAS,OAAQ,IAAM,EAAc,OAAS,WAAI,EAAgB,CAAA,CAClE"}
1
+ {"version":3,"file":"Section.mjs","names":[],"sources":["../../src/components/Section.tsx"],"sourcesContent":["import { Box } from 'ink'\nimport { inkPropsHelpers } from '../utils'\nimport React from 'react'\n\nfunction Section({ isLast, ...props }: React.ComponentProps<typeof Box> & { isLast?: boolean }) {\n return (\n <Box\n {...(isLast !== true && {\n borderStyle: 'single',\n borderDimColor: true,\n ...inkPropsHelpers.border('bottom'),\n })}\n paddingX={1}\n flexDirection=\"column\"\n {...props}\n />\n )\n}\n\nfunction SectionList({ children }: { children: React.ReactNode }) {\n const arrayChildren = React.Children.toArray(children)\n return React.Children.map(arrayChildren, (child, i) => (\n <Section isLast={i === arrayChildren.length - 1}>{child}</Section>\n ))\n}\n\nexport { Section, SectionList }\nexport default Section\n"],"mappings":"qIAIA,SAAS,EAAQ,CAAE,SAAQ,GAAG,GAAkE,CAC9F,OACE,EAAC,EAAD,CACE,GAAK,IAAW,IAAQ,CACtB,YAAa,SACb,eAAgB,GAChB,GAAG,EAAgB,OAAO,QAAQ,CACpC,EACA,SAAU,EACV,cAAc,SACd,GAAI,CACL,CAAA,CAEL,CAEA,SAAS,EAAY,CAAE,YAA2C,CAChE,IAAM,EAAgB,EAAM,SAAS,QAAQ,CAAQ,EACrD,OAAO,EAAM,SAAS,IAAI,GAAgB,EAAO,IAC/C,EAAC,EAAD,CAAS,OAAQ,IAAM,EAAc,OAAS,EAAI,SAAA,CAAe,CAAA,CAClE,CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import Conf from 'conf'\nimport { parse, stringify } from 'yaml'\nimport { name } from '../package.json'\n\nconst config = new Conf({\n projectName: name,\n fileExtension: 'yaml',\n serialize: stringify,\n deserialize: parse,\n})\n\nexport default config\n"],"mappings":"qGAIA,MAAM,EAAS,IAAI,EAAK,CACtB,YAAa,EACb,cAAe,OACf,UAAW,EACX,YAAa,EACd,CAAC"}
1
+ {"version":3,"file":"config.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import Conf from 'conf'\nimport { parse, stringify } from 'yaml'\nimport { name } from '../package.json'\n\nconst config = new Conf({\n projectName: name,\n fileExtension: 'yaml',\n serialize: stringify,\n deserialize: parse,\n})\n\nexport default config\n"],"mappings":"qGAIA,MAAM,EAAS,IAAI,EAAK,CACtB,YAAa,EACb,cAAe,OACf,UAAW,EACX,YAAa,CACf,CAAC"}
package/dist/index.d.mts CHANGED
@@ -1 +1 @@
1
- export { };
1
+ export {}
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import{BORDER as e,DITHER_KERNELS as t,DITHER_TYPES as n}from"./api/modules/content.mjs";import r from"./api/index.mjs";import i from"./components/Container.mjs";import{SectionList as a}from"./components/Section.mjs";import o from"./components/ListItem.mjs";import s from"./config.mjs";import c from"yargs";import{hideBin as l}from"yargs/helpers";import{Box as u,Text as d,render as f}from"ink";import{jsx as p,jsxs as m}from"react/jsx-runtime";import h from"react";import{UncontrolledTextInput as g}from"ink-text-input";import _ from"node:fs/promises";const v=new r({apiKey:s.get(`apiKey`,``)});c(l(process.argv)).scriptName(`quote0`).command(`auth`,`Enter and save API key`,e=>e,async e=>{f(p(()=>{let[e,t]=h.useState(!1);return p(i,{children:m(a,{children:[p(o,{children:p(d,{children:`Authentication`})}),e?p(d,{dimColor:!0,children:`API key saved`}):p(g,{initialValue:s.get(`apiKey`,``),onSubmit:e=>{e.length===0?(s.delete(`apiKey`),t(!0)):(s.set(`apiKey`,e),t(!0))},placeholder:`API key…`,mask:`*`})]})})},{}))}).command(`device`,`Manage devices`,e=>e.demandCommand(1).command(`list`,`List all devices`,e=>e,async e=>{try{let e=await v.device.list();f(p(()=>p(i,{children:m(a,{children:[p(o,{trailing:m(d,{dimColor:!0,children:[e.length,`/`,e.length]}),children:p(d,{children:`Devices`})}),[...e.length===0?[p(o,{children:p(d,{dimColor:!0,children:`No devices found`})})]:e.map(e=>m(u,{flexDirection:`column`,children:[p(o,{trailing:p(d,{children:e.id}),children:p(d,{dimColor:!0,children:`ID`})}),p(o,{trailing:p(d,{children:e.series}),children:p(d,{dimColor:!0,children:`Series`})}),p(o,{trailing:p(d,{children:e.model}),children:p(d,{dimColor:!0,children:`Model`})}),p(o,{trailing:p(d,{children:e.edition}),children:p(d,{dimColor:!0,children:`Edition`})})]}))]]})}),{}))}catch(e){console.error(e)}}).command(`status <device-id>`,`Check device status`,e=>e.positional(`device-id`,{describe:`Device ID to check status for`,type:`string`}),async e=>{try{let t=await v.device.status({deviceId:e.deviceId});f(p(i,{children:m(a,{children:[p(o,{trailing:m(d,{children:[p(d,{dimColor:!0,children:`Device ID: `}),t.deviceId]}),children:m(u,{gap:1,children:[p(d,{children:t.alias}),p(d,{dimColor:!0,children:t.location}),p(d,{dimColor:!0,children:t.status.battery})]})}),p(u,{flexDirection:`column`,children:[...[[`Status`,t.status.current],[`Battery`,t.status.battery],[`Wi-Fi`,t.status.wifi],[`Last Render`,t.renderInfo.last],[`Next Render (Battery)`,t.renderInfo.next.battery],[`Next Render (Power)`,t.renderInfo.next.power],[`Current Images`,t.renderInfo.current.image.length],[`Version`,m(d,{children:[p(d,{dimColor:!0,children:`v`}),t.status.version]})]].map(([e,t])=>p(o,{trailing:p(d,{children:t}),children:p(d,{dimColor:!0,children:e})}))]})]})}))}catch(e){console.error(e)}})).command(`content`,`Manage content`,r=>r.demandCommand(1).command(`next <device-id>`,`Switch to next content`,e=>e.positional(`device-id`,{describe:`Device ID to switch content for`,type:`string`}),async e=>{try{let t=await v.content.next({deviceId:e.deviceId});f(p(i,{children:m(a,{children:[p(d,{children:`Next Content`}),p(d,{children:t.message})]})}))}catch(e){console.error(e)}}).command(`image <device-id>`,`Push an image to device`,r=>r.positional(`device-id`,{describe:`Device ID to push image to`,type:`string`}).option(`f`,{alias:`file`,describe:`Path to image file`,type:`string`,demandOption:!0}).option(`refresh-now`,{describe:`Whether to refresh the device immediately`,type:`boolean`}).option(`link`,{describe:`Optional link to open when image is tapped`,type:`string`}).option(`border`,{describe:`Whether to add a border around the image`,type:`number`,choices:e}).option(`dither-type`,{describe:`Dithering algorithm to use`,type:`string`,choices:n}).option(`dither-kernel`,{describe:`Dithering kernel to use (if dither-type is DIFFUSION)`,type:`string`,choices:t}).option(`task-key`,{describe:`Optional task key to track rendering status`,type:`string`}),async e=>{let t=(await _.readFile(e.f)).toString(`base64`),n=await v.content.pushImage({deviceId:e.deviceId},{image:t,refreshNow:e.refreshNow,link:e.link,border:e.border,ditherType:e.ditherType,ditherKernel:e.ditherKernel,taskKey:e.taskKey});f(p(()=>p(i,{children:m(a,{children:[p(d,{children:`Push Image`}),p(o,{children:p(d,{children:n.message})})]})}),{}))})).demandCommand(1,`Please specify a command`).strict().parse();export{};
2
+ import{runCli as e}from"./cli/index.mjs";e();export{};
3
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.tsx"],"sourcesContent":["#!/usr/bin/env node\n\nimport yargs from 'yargs'\nimport { hideBin } from 'yargs/helpers'\nimport { Box, render, Text } from 'ink'\nimport Quote0, { BORDER, DITHER_TYPES, DITHER_KERNELS } from './api'\nimport Container from './components/Container'\nimport { SectionList } from './components/Section'\nimport ListItem from './components/ListItem'\nimport { UncontrolledTextInput } from 'ink-text-input'\nimport config from './config'\nimport React from 'react'\nimport fs from 'node:fs/promises'\n\nconst quote0 = new Quote0({\n apiKey: config.get('apiKey', ''),\n})\n\nyargs(hideBin(process.argv))\n .scriptName('quote0')\n .command(\n 'auth',\n 'Enter and save API key',\n yargs => yargs,\n async argv => {\n const Main = () => {\n const [submitted, setSubmitted] = React.useState(false)\n\n return (\n <Container>\n <SectionList>\n <ListItem>\n <Text>Authentication</Text>\n </ListItem>\n {!submitted ? (\n <UncontrolledTextInput\n initialValue={config.get('apiKey', '')}\n onSubmit={v => {\n if (v.length === 0) {\n config.delete('apiKey')\n setSubmitted(true)\n } else {\n config.set('apiKey', v)\n setSubmitted(true)\n }\n }}\n placeholder=\"API key…\"\n mask=\"*\"\n />\n ) : (\n <Text dimColor>API key saved</Text>\n )}\n </SectionList>\n </Container>\n )\n }\n\n render(<Main />)\n },\n )\n .command('device', 'Manage devices', yargs =>\n yargs\n .demandCommand(1)\n .command(\n 'list',\n 'List all devices',\n yargs => yargs,\n async argv => {\n try {\n const devices = await quote0.device.list()\n\n const Main = () => (\n <Container>\n <SectionList>\n <ListItem\n trailing={\n <Text dimColor>\n {devices.length}/{devices.length}\n </Text>\n }\n >\n <Text>Devices</Text>\n </ListItem>\n {...devices.length === 0\n ? [\n <ListItem>\n <Text dimColor>No devices found</Text>\n </ListItem>,\n ]\n : devices.map(device => (\n <Box flexDirection=\"column\">\n <ListItem trailing={<Text>{device.id}</Text>}>\n <Text dimColor>ID</Text>\n </ListItem>\n <ListItem trailing={<Text>{device.series}</Text>}>\n <Text dimColor>Series</Text>\n </ListItem>\n <ListItem trailing={<Text>{device.model}</Text>}>\n <Text dimColor>Model</Text>\n </ListItem>\n <ListItem trailing={<Text>{device.edition}</Text>}>\n <Text dimColor>Edition</Text>\n </ListItem>\n </Box>\n ))}\n </SectionList>\n </Container>\n )\n\n render(<Main />)\n } catch (error) {\n console.error(error)\n }\n },\n )\n .command(\n 'status <device-id>',\n 'Check device status',\n yargs =>\n yargs.positional('device-id', {\n describe: 'Device ID to check status for',\n type: 'string',\n }),\n async argv => {\n try {\n const response = await quote0.device.status({\n deviceId: argv.deviceId!,\n })\n\n render(\n <Container>\n <SectionList>\n <ListItem\n trailing={\n <Text>\n <Text dimColor>Device ID: </Text>\n {response.deviceId}\n </Text>\n }\n >\n <Box gap={1}>\n <Text>{response.alias}</Text>\n <Text dimColor>{response.location}</Text>\n <Text dimColor>{response.status.battery}</Text>\n </Box>\n </ListItem>\n <Box flexDirection=\"column\">\n {...[\n ['Status', response.status.current],\n ['Battery', response.status.battery],\n ['Wi-Fi', response.status.wifi],\n ['Last Render', response.renderInfo.last],\n ['Next Render (Battery)', response.renderInfo.next.battery],\n ['Next Render (Power)', response.renderInfo.next.power],\n ['Current Images', response.renderInfo.current.image.length],\n [\n 'Version',\n <Text>\n <Text dimColor>v</Text>\n {response.status.version}\n </Text>,\n ],\n ].map(([k, v]) => (\n <ListItem trailing={<Text>{v}</Text>}>\n <Text dimColor>{k}</Text>\n </ListItem>\n ))}\n </Box>\n </SectionList>\n </Container>,\n )\n } catch (error) {\n console.error(error)\n }\n },\n ),\n )\n .command('content', 'Manage content', yargs =>\n yargs\n .demandCommand(1)\n .command(\n 'next <device-id>',\n 'Switch to next content',\n yargs =>\n yargs.positional('device-id', {\n describe: 'Device ID to switch content for',\n type: 'string',\n }),\n async argv => {\n try {\n const response = await quote0.content.next({\n deviceId: argv.deviceId!,\n })\n\n render(\n <Container>\n <SectionList>\n <Text>Next Content</Text>\n <Text>{response.message}</Text>\n </SectionList>\n </Container>,\n )\n } catch (error) {\n console.error(error)\n }\n },\n )\n .command(\n 'image <device-id>',\n 'Push an image to device',\n yargs =>\n yargs\n .positional('device-id', {\n describe: 'Device ID to push image to',\n type: 'string',\n })\n .option('f', {\n alias: 'file',\n describe: 'Path to image file',\n type: 'string',\n demandOption: true,\n })\n .option('refresh-now', {\n describe: 'Whether to refresh the device immediately',\n type: 'boolean',\n })\n .option('link', {\n describe: 'Optional link to open when image is tapped',\n type: 'string',\n })\n .option('border', {\n describe: 'Whether to add a border around the image',\n type: 'number',\n choices: BORDER,\n })\n .option('dither-type', {\n describe: 'Dithering algorithm to use',\n type: 'string',\n choices: DITHER_TYPES,\n })\n .option('dither-kernel', {\n describe: 'Dithering kernel to use (if dither-type is DIFFUSION)',\n type: 'string',\n choices: DITHER_KERNELS,\n })\n .option('task-key', {\n describe: 'Optional task key to track rendering status',\n type: 'string',\n }),\n async argv => {\n const file = await fs.readFile(argv.f)\n const base64 = file.toString('base64')\n\n const response = await quote0.content.pushImage(\n { deviceId: argv.deviceId! },\n {\n image: base64,\n refreshNow: argv.refreshNow,\n link: argv.link,\n border: argv.border,\n ditherType: argv.ditherType,\n ditherKernel: argv.ditherKernel,\n taskKey: argv.taskKey,\n },\n )\n\n const Main = () => {\n return (\n <Container>\n <SectionList>\n <Text>Push Image</Text>\n <ListItem>\n <Text>{response.message}</Text>\n </ListItem>\n </SectionList>\n </Container>\n )\n }\n\n render(<Main />)\n },\n ),\n )\n .demandCommand(1, 'Please specify a command')\n .strict()\n .parse()\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.tsx"],"sourcesContent":["#!/usr/bin/env node\n\nimport { runCli } from './cli'\n\nvoid runCli()\n"],"mappings":";yCAIK,EAAO"}
package/dist/package.mjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=`quote0`;export{e as name};
1
+ var e=`quote0`,t=`1.0.0-alpha.8`;export{e as name,t as version};
2
2
  //# sourceMappingURL=package.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ink-props-helpers.mjs","names":[],"sources":["../../src/utils/ink-props-helpers.ts"],"sourcesContent":["const inkPropsHelpers = {\n border: (...directions: ('top' | 'right' | 'bottom' | 'left')[]) => {\n return {\n borderTop: directions.includes('top'),\n borderRight: directions.includes('right'),\n borderBottom: directions.includes('bottom'),\n borderLeft: directions.includes('left'),\n }\n },\n}\n\nexport default inkPropsHelpers\n"],"mappings":"AAAA,MAAM,EAAkB,CACtB,QAAS,GAAG,KACH,CACL,UAAW,EAAW,SAAS,MAAM,CACrC,YAAa,EAAW,SAAS,QAAQ,CACzC,aAAc,EAAW,SAAS,SAAS,CAC3C,WAAY,EAAW,SAAS,OAAO,CACxC,EAEJ"}
1
+ {"version":3,"file":"ink-props-helpers.mjs","names":[],"sources":["../../src/utils/ink-props-helpers.ts"],"sourcesContent":["const inkPropsHelpers = {\n border: (...directions: ('top' | 'right' | 'bottom' | 'left')[]) => {\n return {\n borderTop: directions.includes('top'),\n borderRight: directions.includes('right'),\n borderBottom: directions.includes('bottom'),\n borderLeft: directions.includes('left'),\n }\n },\n}\n\nexport default inkPropsHelpers\n"],"mappings":"AAAA,MAAM,EAAkB,CACtB,QAAS,GAAG,KACH,CACL,UAAW,EAAW,SAAS,KAAK,EACpC,YAAa,EAAW,SAAS,OAAO,EACxC,aAAc,EAAW,SAAS,QAAQ,EAC1C,WAAY,EAAW,SAAS,MAAM,CACxC,EAEJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quote0",
3
- "version": "1.0.0-alpha.7",
3
+ "version": "1.0.0-alpha.8",
4
4
  "description": "TypeScript SDK and CLI for Quote/0.",
5
5
  "keywords": [
6
6
  "cli",
@@ -12,7 +12,10 @@
12
12
  },
13
13
  "license": "MIT",
14
14
  "author": "Mr. Will (https://github.com/MrWillCom)",
15
- "repository": "MrWillCom/quote0",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "MrWillCom/quote0"
18
+ },
16
19
  "bin": {
17
20
  "quote0": "dist/index.mjs"
18
21
  },
@@ -24,23 +27,22 @@
24
27
  ".": "./dist/api/index.mjs"
25
28
  },
26
29
  "dependencies": {
30
+ "@kud/ink-ui": "^0.14.1",
31
+ "cac": "^7.0.0",
27
32
  "conf": "^15.1.0",
28
- "ink": "^6.8.0",
29
- "ink-spinner": "^5.0.0",
33
+ "ink": "^7.1.1",
30
34
  "ink-text-input": "^6.0.0",
31
- "react": "^19.2.4",
32
- "yaml": "^2.8.3",
33
- "yargs": "^18.0.0"
35
+ "react": "^19.2.8",
36
+ "yaml": "^2.9.0"
34
37
  },
35
38
  "devDependencies": {
36
- "@changesets/cli": "^2.30.0",
37
- "@types/node": "^25.5.0",
38
- "@types/react": "^19.2.14",
39
- "@types/yargs": "^17.0.35",
40
- "oxfmt": "^0.42.0",
41
- "tsdown": "^0.21.4",
42
- "tsx": "^4.21.0",
43
- "typescript": "^6.0.2"
39
+ "@changesets/cli": "^2.31.1",
40
+ "@types/node": "^26.2.0",
41
+ "@types/react": "^19.2.18",
42
+ "oxfmt": "^0.62.0",
43
+ "tsdown": "^0.22.14",
44
+ "tsx": "^4.23.12",
45
+ "typescript": "^6.0.3"
44
46
  },
45
47
  "scripts": {
46
48
  "build": "tsc --noEmit && tsdown",