@arcanewizards/timecode-toolbox 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -0
  3. package/dist/components/frontend/index.js +1035 -442
  4. package/dist/components/frontend/index.mjs +884 -291
  5. package/dist/entrypoint.css +163 -53
  6. package/dist/entrypoint.js +1769 -788
  7. package/dist/entrypoint.js.map +4 -4
  8. package/dist/frontend.js +1769 -788
  9. package/dist/frontend.js.map +4 -4
  10. package/dist/index.d.mts +3 -1
  11. package/dist/index.d.ts +3 -1
  12. package/dist/index.js +346 -76
  13. package/dist/index.mjs +348 -69
  14. package/dist/start.d.mts +1 -2
  15. package/dist/start.d.ts +1 -2
  16. package/dist/start.js +349 -77
  17. package/dist/start.mjs +351 -70
  18. package/package.json +12 -6
  19. package/.turbo/turbo-build.log +0 -58
  20. package/.turbo/turbo-lint.log +0 -4
  21. package/CHANGELOG.md +0 -40
  22. package/eslint.config.mjs +0 -49
  23. package/src/app.tsx +0 -147
  24. package/src/components/backend/index.ts +0 -6
  25. package/src/components/backend/toolbox-root.ts +0 -119
  26. package/src/components/frontend/constants.ts +0 -81
  27. package/src/components/frontend/entrypoint.ts +0 -12
  28. package/src/components/frontend/frontend.css +0 -108
  29. package/src/components/frontend/index.tsx +0 -46
  30. package/src/components/frontend/toolbox/content.tsx +0 -45
  31. package/src/components/frontend/toolbox/context.tsx +0 -63
  32. package/src/components/frontend/toolbox/core/size-aware-div.tsx +0 -51
  33. package/src/components/frontend/toolbox/core/timecode-display.tsx +0 -592
  34. package/src/components/frontend/toolbox/generators.tsx +0 -318
  35. package/src/components/frontend/toolbox/inputs.tsx +0 -484
  36. package/src/components/frontend/toolbox/outputs.tsx +0 -581
  37. package/src/components/frontend/toolbox/preferences.ts +0 -25
  38. package/src/components/frontend/toolbox/root.tsx +0 -335
  39. package/src/components/frontend/toolbox/settings.tsx +0 -54
  40. package/src/components/frontend/toolbox/types.ts +0 -28
  41. package/src/components/frontend/toolbox/util.tsx +0 -61
  42. package/src/components/proto.ts +0 -420
  43. package/src/config.ts +0 -7
  44. package/src/generators/clock.tsx +0 -206
  45. package/src/generators/index.tsx +0 -15
  46. package/src/index.ts +0 -38
  47. package/src/inputs/artnet.tsx +0 -305
  48. package/src/inputs/index.tsx +0 -13
  49. package/src/inputs/tcnet.tsx +0 -272
  50. package/src/outputs/artnet.tsx +0 -170
  51. package/src/outputs/index.tsx +0 -11
  52. package/src/start.ts +0 -47
  53. package/src/tree.ts +0 -133
  54. package/src/types.ts +0 -12
  55. package/src/urls.ts +0 -49
  56. package/src/util.ts +0 -82
  57. package/tailwind.config.cjs +0 -7
  58. package/tsconfig.json +0 -10
  59. package/tsup.config.ts +0 -10
package/dist/start.mjs CHANGED
@@ -1,10 +1,17 @@
1
+ #!/usr/bin/env node
1
2
  var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
6
  var __getProtoOf = Object.getPrototypeOf;
6
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __commonJS = (cb, mod) => function __require() {
8
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
9
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
10
+ }) : x)(function(x) {
11
+ if (typeof require !== "undefined") return require.apply(this, arguments);
12
+ throw Error('Dynamic require of "' + x + '" is not supported');
13
+ });
14
+ var __commonJS = (cb, mod) => function __require2() {
8
15
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
16
  };
10
17
  var __export = (target, all) => {
@@ -1809,6 +1816,7 @@ var runSigilApp = ({
1809
1816
  logger: upstreamLogger,
1810
1817
  title,
1811
1818
  version: version2,
1819
+ edition,
1812
1820
  appProps,
1813
1821
  toolkitOptions,
1814
1822
  createApp: createApp2,
@@ -1867,10 +1875,10 @@ var runSigilApp = ({
1867
1875
  logger2.info(`${title} ready to start listening`);
1868
1876
  }
1869
1877
  });
1870
- let api = null;
1878
+ let api2 = null;
1871
1879
  const apiListeners = /* @__PURE__ */ new Set();
1872
1880
  const setAppApi = (value) => {
1873
- api = value;
1881
+ api2 = value;
1874
1882
  for (const listener of apiListeners) {
1875
1883
  listener(value);
1876
1884
  }
@@ -1903,6 +1911,7 @@ var runSigilApp = ({
1903
1911
  createApp2({
1904
1912
  title,
1905
1913
  version: version2,
1914
+ edition,
1906
1915
  toolkit,
1907
1916
  logger: logger2,
1908
1917
  logEventEmitter,
@@ -1922,8 +1931,8 @@ var runSigilApp = ({
1922
1931
  if (event === "apiChange") {
1923
1932
  const apiListener = listener;
1924
1933
  apiListeners.add(apiListener);
1925
- if (api) {
1926
- apiListener(api);
1934
+ if (api2) {
1935
+ apiListener(api2);
1927
1936
  }
1928
1937
  return;
1929
1938
  }
@@ -2137,10 +2146,10 @@ var AppListenerManager = ({
2137
2146
 
2138
2147
  // src/app.tsx
2139
2148
  import {
2140
- useCallback as useCallback6,
2141
- useEffect as useEffect9,
2142
- useMemo as useMemo5,
2143
- useState as useState6
2149
+ useCallback as useCallback7,
2150
+ useEffect as useEffect10,
2151
+ useMemo as useMemo6,
2152
+ useState as useState7
2144
2153
  } from "react";
2145
2154
 
2146
2155
  // src/components/backend/index.ts
@@ -6196,8 +6205,7 @@ var NEVER = INVALID;
6196
6205
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js
6197
6206
  var zod_default = external_exports;
6198
6207
 
6199
- // ../../packages/sigil/dist/chunk-H4U4Z4GM.js
6200
- import { useEffect as useEffect4 } from "react";
6208
+ // ../../packages/sigil/dist/chunk-WYUGJOEB.js
6201
6209
  var SIGIL_COLOR = external_exports.enum([
6202
6210
  "purple",
6203
6211
  "blue",
@@ -6292,12 +6300,18 @@ var OUTPUT_CONFIG = zod_default.object({
6292
6300
  var TOOLBOX_CONFIG = zod_default.object({
6293
6301
  inputs: zod_default.record(zod_default.string(), INPUT_CONFIG),
6294
6302
  generators: zod_default.record(zod_default.string(), GENERATOR_CONFIG),
6295
- outputs: zod_default.record(zod_default.string(), OUTPUT_CONFIG)
6303
+ outputs: zod_default.record(zod_default.string(), OUTPUT_CONFIG),
6304
+ /**
6305
+ * Hash of the license the user has agreed to.
6306
+ */
6307
+ agreedToLicense: zod_default.string().optional(),
6308
+ checkForUpdates: zod_default.boolean().optional().default(true)
6296
6309
  });
6297
6310
  var DEFAULT_CONFIG = {
6298
6311
  inputs: {},
6299
6312
  generators: {},
6300
- outputs: {}
6313
+ outputs: {},
6314
+ checkForUpdates: true
6301
6315
  };
6302
6316
  var isPlaying = (state) => state.state === "playing" || state.state === "lagging";
6303
6317
  var isStopped = (state) => state.state === "stopped";
@@ -6313,9 +6327,11 @@ var DEFAULT_PROPS2 = {
6313
6327
  state: {
6314
6328
  inputs: {},
6315
6329
  outputs: {},
6316
- generators: {}
6330
+ generators: {},
6331
+ updates: null
6317
6332
  },
6318
- handlers: { children: {} }
6333
+ handlers: { children: {} },
6334
+ license: ""
6319
6335
  };
6320
6336
  var ToolboxRoot = class extends Base {
6321
6337
  /** @hidden */
@@ -6343,7 +6359,8 @@ var ToolboxRoot = class extends Base {
6343
6359
  key: idMap.getId(this),
6344
6360
  config: this.props.config,
6345
6361
  state: this.props.state,
6346
- handlers: this.props.handlers
6362
+ handlers: this.props.handlers,
6363
+ license: this.props.license
6347
6364
  };
6348
6365
  }
6349
6366
  /** @hidden */
@@ -6372,9 +6389,56 @@ var ToolboxRoot = class extends Base {
6372
6389
  };
6373
6390
  };
6374
6391
 
6392
+ // src/components/backend/license-gate.ts
6393
+ import {
6394
+ Base as Base2,
6395
+ EventEmitter as EventEmitter4
6396
+ } from "@arcanejs/toolkit/components/base";
6397
+ var DEFAULT_PROPS3 = {
6398
+ license: "",
6399
+ hash: ""
6400
+ };
6401
+ var LicenseGate = class extends Base2 {
6402
+ /** @hidden */
6403
+ events = new EventEmitter4();
6404
+ constructor(props) {
6405
+ super(DEFAULT_PROPS3, props, {
6406
+ onPropsUpdated: (oldProps) => this.events.processPropChanges(
6407
+ {
6408
+ onAcceptLicense: "acceptLicense"
6409
+ },
6410
+ oldProps,
6411
+ this.props
6412
+ )
6413
+ });
6414
+ this.triggerInitialPropsUpdate();
6415
+ }
6416
+ addListener = this.events.addListener;
6417
+ removeListener = this.events.removeListener;
6418
+ /** @hidden */
6419
+ getProtoInfo(idMap) {
6420
+ return {
6421
+ namespace: "timecode-toolbox",
6422
+ component: "license-gate",
6423
+ key: idMap.getId(this),
6424
+ license: this.props.license,
6425
+ hash: this.props.hash
6426
+ };
6427
+ }
6428
+ /** @hidden */
6429
+ handleMessage = (message) => {
6430
+ if (isTimecodeToolboxComponentMessage(message, "license-gate")) {
6431
+ if (message.action === "accept-license") {
6432
+ this.events.emit("acceptLicense", message.hash);
6433
+ }
6434
+ }
6435
+ };
6436
+ };
6437
+
6375
6438
  // src/components/backend/index.ts
6376
6439
  var C = prepareComponents2("timecode-toolbox", {
6377
- ToolboxRoot
6440
+ ToolboxRoot,
6441
+ LicenseGate
6378
6442
  });
6379
6443
 
6380
6444
  // src/config.ts
@@ -6439,7 +6503,7 @@ var patchJson = (old, diff) => {
6439
6503
 
6440
6504
  // src/inputs/artnet.tsx
6441
6505
  import { useDataFileData } from "@arcanejs/react-toolkit/data";
6442
- import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef2, useState as useState3 } from "react";
6506
+ import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef2, useState as useState3 } from "react";
6443
6507
 
6444
6508
  // ../../packages/artnet/dist/chunk-J2HDMITA.js
6445
6509
  var ARTNET_PORT = 6454;
@@ -6458,7 +6522,7 @@ var TIMECODE_FPS = {
6458
6522
 
6459
6523
  // ../../packages/artnet/dist/index.js
6460
6524
  import { createSocket } from "dgram";
6461
- import EventEmitter4 from "events";
6525
+ import EventEmitter5 from "events";
6462
6526
  var ARTNET_HEADER = "Art-Net\0";
6463
6527
  var ARTNET_VERSION = 14;
6464
6528
  var OP_TIME_CODE = 38656;
@@ -6575,7 +6639,7 @@ var parseTimecodePacket = (packet, source) => {
6575
6639
  };
6576
6640
  };
6577
6641
  var createArtnet = (config) => {
6578
- const events = new EventEmitter4();
6642
+ const events = new EventEmitter5();
6579
6643
  let sendSocket = null;
6580
6644
  let receiveSocket = null;
6581
6645
  let destroyed = false;
@@ -6771,7 +6835,7 @@ var ArtnetInputConnection = ({
6771
6835
  const log = useLogger();
6772
6836
  const [artnetInstance, setArtnetInstance] = useState3(null);
6773
6837
  const delayRef = useRef2(delayMs ?? 0);
6774
- useEffect5(() => {
6838
+ useEffect4(() => {
6775
6839
  delayRef.current = delayMs ?? 0;
6776
6840
  }, [delayMs]);
6777
6841
  const setConnection = useCallback2(
@@ -6784,7 +6848,7 @@ var ArtnetInputConnection = ({
6784
6848
  })),
6785
6849
  [setState, uuid]
6786
6850
  );
6787
- useEffect5(() => {
6851
+ useEffect4(() => {
6788
6852
  const connectionConfig = {
6789
6853
  timecode: {
6790
6854
  name: null,
@@ -6837,7 +6901,7 @@ var ArtnetInputConnection = ({
6837
6901
  }
6838
6902
  };
6839
6903
  }, [setConnection, uuid, iface, port, log]);
6840
- useEffect5(() => {
6904
+ useEffect4(() => {
6841
6905
  let lastTimecode = null;
6842
6906
  let lastUsedTimecode = lastTimecode;
6843
6907
  let timecode = null;
@@ -6926,7 +6990,7 @@ var ArtnetInputConnection = ({
6926
6990
  artnetInstance?.removeListener("timecode", onTimecode);
6927
6991
  };
6928
6992
  }, [artnetInstance, log, iface, name, setConnection]);
6929
- useEffect5(() => {
6993
+ useEffect4(() => {
6930
6994
  return () => {
6931
6995
  setState((current) => {
6932
6996
  const { [uuid]: _, ...rest } = current.inputs;
@@ -6964,7 +7028,7 @@ import { useDataFileData as useDataFileData2 } from "@arcanejs/react-toolkit/dat
6964
7028
  import {
6965
7029
  useCallback as useCallback3,
6966
7030
  useContext as useContext2,
6967
- useEffect as useEffect6,
7031
+ useEffect as useEffect5,
6968
7032
  useMemo as useMemo2,
6969
7033
  useRef as useRef3
6970
7034
  } from "react";
@@ -6976,7 +7040,7 @@ var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
6976
7040
  var __getOwnPropNames2 = Object.getOwnPropertyNames;
6977
7041
  var __getProtoOf2 = Object.getPrototypeOf;
6978
7042
  var __hasOwnProp2 = Object.prototype.hasOwnProperty;
6979
- var __commonJS2 = (cb, mod) => function __require() {
7043
+ var __commonJS2 = (cb, mod) => function __require2() {
6980
7044
  return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
6981
7045
  };
6982
7046
  var __copyProps2 = (to, from, except, desc) => {
@@ -7515,7 +7579,7 @@ var calculateUniqueNodeId = (info) => {
7515
7579
 
7516
7580
  // ../../packages/tcnet/dist/index.js
7517
7581
  import { createSocket as createSocket2 } from "dgram";
7518
- import EventEmitter5 from "events";
7582
+ import EventEmitter6 from "events";
7519
7583
  import { promisify } from "util";
7520
7584
  var require_lodash = __commonJS2({
7521
7585
  "../../node_modules/.pnpm/lodash@4.17.23/node_modules/lodash/lodash.js"(exports, module) {
@@ -13034,7 +13098,7 @@ var bindSocket2 = (socket, port, address) => {
13034
13098
  };
13035
13099
  var createTCNetNode = (props) => {
13036
13100
  const { logger: logger2 } = props;
13037
- const events = new EventEmitter5();
13101
+ const events = new EventEmitter6();
13038
13102
  let iface = null;
13039
13103
  const sockets = {
13040
13104
  broadcastSend: null,
@@ -13545,7 +13609,7 @@ var createTCNetNode = (props) => {
13545
13609
  };
13546
13610
 
13547
13611
  // ../../packages/tcnet/dist/monitor.js
13548
- import EventEmitter6 from "events";
13612
+ import EventEmitter7 from "events";
13549
13613
  var MAX_DELTA_MS = 10;
13550
13614
  var layerDataIdToIndex = (dataLayerId) => {
13551
13615
  return dataLayerId - 1;
@@ -13564,7 +13628,7 @@ var TCNET_LAYER_INDEXES = Array.from(
13564
13628
  (_, i) => asLayerIndex(i)
13565
13629
  );
13566
13630
  var createTCNetTimecodeMonitor = (tcNetNode, logger2) => {
13567
- const events = new EventEmitter6();
13631
+ const events = new EventEmitter7();
13568
13632
  const on = events.on.bind(events);
13569
13633
  const addListener = events.addListener.bind(events);
13570
13634
  const removeListener = events.removeListener.bind(events);
@@ -13851,7 +13915,7 @@ var TcnetInputConnection = ({
13851
13915
  const nodeRef = useRef3(null);
13852
13916
  const isMountedRef = useRef3(true);
13853
13917
  const delayRef = useRef3(delayMs ?? 0);
13854
- useEffect6(() => {
13918
+ useEffect5(() => {
13855
13919
  delayRef.current = delayMs ?? 0;
13856
13920
  }, [delayMs]);
13857
13921
  const setConnection = useCallback3(
@@ -13891,7 +13955,7 @@ var TcnetInputConnection = ({
13891
13955
  });
13892
13956
  };
13893
13957
  }, [setConnection]);
13894
- useEffect6(() => {
13958
+ useEffect5(() => {
13895
13959
  const node = createTCNetNode({
13896
13960
  logger: logger2,
13897
13961
  networkInterface: iface,
@@ -13985,7 +14049,7 @@ var TcnetInputConnection = ({
13985
14049
  await nodeRef.current.destroy();
13986
14050
  }
13987
14051
  });
13988
- useEffect6(() => {
14052
+ useEffect5(() => {
13989
14053
  return () => {
13990
14054
  isMountedRef.current = false;
13991
14055
  setState((current) => {
@@ -14032,7 +14096,7 @@ var InputConnections = (props) => {
14032
14096
  import { useDataFileData as useDataFileData3 } from "@arcanejs/react-toolkit/data";
14033
14097
  import {
14034
14098
  useCallback as useCallback4,
14035
- useEffect as useEffect7,
14099
+ useEffect as useEffect6,
14036
14100
  useMemo as useMemo3,
14037
14101
  useState as useState4
14038
14102
  } from "react";
@@ -14091,7 +14155,7 @@ var ArtnetOutputConnection = ({
14091
14155
  })),
14092
14156
  [setState, uuid]
14093
14157
  );
14094
- useEffect7(() => {
14158
+ useEffect6(() => {
14095
14159
  let artnet = null;
14096
14160
  setConnection({ status: "connecting" });
14097
14161
  const created = createArtnet({
@@ -14128,7 +14192,7 @@ var ArtnetOutputConnection = ({
14128
14192
  }
14129
14193
  };
14130
14194
  }, [setConnection, uuid, target, log]);
14131
- useEffect7(() => {
14195
+ useEffect6(() => {
14132
14196
  return () => {
14133
14197
  setState((current) => {
14134
14198
  const { [uuid]: _, ...rest } = current.outputs;
@@ -14147,7 +14211,7 @@ var ArtnetOutputConnection = ({
14147
14211
  () => tcInstance?.state ? adjustTimecodeForDelay(tcInstance.state, config.delayMs ?? 0) : null,
14148
14212
  [tcInstance?.state, config.delayMs]
14149
14213
  );
14150
- useEffect7(() => {
14214
+ useEffect6(() => {
14151
14215
  if (!artnetInstance) {
14152
14216
  return;
14153
14217
  }
@@ -14195,7 +14259,7 @@ var OutputConnections = (props) => {
14195
14259
  // src/generators/clock.tsx
14196
14260
  import {
14197
14261
  useCallback as useCallback5,
14198
- useEffect as useEffect8,
14262
+ useEffect as useEffect7,
14199
14263
  useMemo as useMemo4,
14200
14264
  useState as useState5
14201
14265
  } from "react";
@@ -14388,7 +14452,7 @@ var ClockGenerator = ({
14388
14452
  }
14389
14453
  });
14390
14454
  }, []);
14391
- useEffect8(() => {
14455
+ useEffect7(() => {
14392
14456
  setLocalState((current) => {
14393
14457
  if (current.state === "none" || current.state === "stopped") {
14394
14458
  return current;
@@ -14403,12 +14467,12 @@ var ClockGenerator = ({
14403
14467
  };
14404
14468
  });
14405
14469
  }, [speed]);
14406
- useEffect8(() => {
14470
+ useEffect7(() => {
14407
14471
  setHandlers(
14408
14472
  (current) => updateTreeState(current, id, { play, pause, seekRelative, beginning })
14409
14473
  );
14410
14474
  }, [setHandlers, id, play, pause, seekRelative, beginning]);
14411
- useEffect8(
14475
+ useEffect7(
14412
14476
  () => setState((current) => ({
14413
14477
  ...current,
14414
14478
  generators: {
@@ -14429,7 +14493,7 @@ var ClockGenerator = ({
14429
14493
  })),
14430
14494
  [setState, uuid, state, config.name]
14431
14495
  );
14432
- useEffect8(
14496
+ useEffect7(
14433
14497
  () => () => {
14434
14498
  setState((current) => {
14435
14499
  const { [uuid]: _, ...rest } = current.generators;
@@ -14470,11 +14534,179 @@ var Generators = (props) => {
14470
14534
  return /* @__PURE__ */ jsx8(Fragment3, { children: /* @__PURE__ */ jsx8(ClockGenerators, { ...props }) });
14471
14535
  };
14472
14536
 
14537
+ // src/license.ts
14538
+ import { createHash } from "crypto";
14539
+ import { readFile } from "fs/promises";
14540
+ import { useEffect as useEffect8, useState as useState6 } from "react";
14541
+ var getLicense = async () => {
14542
+ const licenseText = await readFile(__require.resolve("../LICENSE"), "utf-8");
14543
+ const hash = createHash("sha256").update(licenseText).digest("hex");
14544
+ return { text: licenseText, hash };
14545
+ };
14546
+ var useLicense = () => {
14547
+ const [license, setLicense] = useState6(null);
14548
+ useEffect8(() => {
14549
+ getLicense().then(setLicense);
14550
+ }, []);
14551
+ return license;
14552
+ };
14553
+
14554
+ // src/updates.tsx
14555
+ import { useCallback as useCallback6, useEffect as useEffect9, useMemo as useMemo5 } from "react";
14556
+
14557
+ // ../../packages/apis/dist/index.js
14558
+ var APP_PLATFORM = zod_default.enum(["windows", "macos", "linux"]);
14559
+ var APP_ARCHITECTURE = zod_default.enum(["x64", "arm64"]);
14560
+ var APP_EDITION = zod_default.enum(["desktop", "cli"]);
14561
+ var CHECK_FOR_UPDATES_REQUEST = zod_default.object({
14562
+ app: zod_default.string(),
14563
+ edition: APP_EDITION,
14564
+ platform: APP_PLATFORM,
14565
+ architecture: APP_ARCHITECTURE,
14566
+ currentVersion: zod_default.string()
14567
+ });
14568
+ var CHECK_FOR_UPDATES_VERSION = zod_default.object({
14569
+ version: zod_default.string(),
14570
+ releaseNotes: zod_default.string()
14571
+ });
14572
+ var CHECK_FOR_UPDATES_RESPONSE = zod_default.object({
14573
+ downloadUrl: zod_default.string().optional(),
14574
+ latestVersion: zod_default.string(),
14575
+ newVersions: zod_default.array(CHECK_FOR_UPDATES_VERSION).optional()
14576
+ });
14577
+ var ApiError = class extends Error {
14578
+ constructor(message, response) {
14579
+ super(message);
14580
+ this.response = response;
14581
+ this.name = "ApiError";
14582
+ }
14583
+ };
14584
+ var api = (baseUrl) => {
14585
+ const checkForUpdates = async (request) => {
14586
+ const response = await fetch(new URL("/api/v1/updates", baseUrl), {
14587
+ method: "POST",
14588
+ headers: { "Content-Type": "application/json" },
14589
+ body: JSON.stringify(request)
14590
+ });
14591
+ if (!response.ok) {
14592
+ throw new ApiError(
14593
+ `Failed to check for updates: ${response.statusText} - ${await response.text()}`,
14594
+ response
14595
+ );
14596
+ }
14597
+ const responseData = await response.json();
14598
+ return CHECK_FOR_UPDATES_RESPONSE.parse(responseData);
14599
+ };
14600
+ return {
14601
+ checkForUpdates
14602
+ };
14603
+ };
14604
+
14605
+ // src/updates.tsx
14606
+ var getAppPlatform = () => {
14607
+ switch (process.platform) {
14608
+ case "win32":
14609
+ return "windows";
14610
+ case "darwin":
14611
+ return "macos";
14612
+ case "linux":
14613
+ return "linux";
14614
+ default:
14615
+ throw new Error(`Unsupported platform: ${process.platform}`);
14616
+ }
14617
+ };
14618
+ var getAppArchitecture = () => {
14619
+ switch (process.arch) {
14620
+ case "x64":
14621
+ return "x64";
14622
+ case "arm64":
14623
+ return "arm64";
14624
+ default:
14625
+ throw new Error(`Unsupported architecture: ${process.arch}`);
14626
+ }
14627
+ };
14628
+ var UpdateChecker = ({
14629
+ apiBaseUrl,
14630
+ version: version2,
14631
+ edition,
14632
+ setUpdateState
14633
+ }) => {
14634
+ const a = useMemo5(() => api(apiBaseUrl), [apiBaseUrl]);
14635
+ const logger2 = useLogger();
14636
+ const checkForUpdates = useCallback6(() => {
14637
+ const lastCheckedMillis = Date.now();
14638
+ setUpdateState({ type: "loading" });
14639
+ a.checkForUpdates({
14640
+ app: "timecode-toolbox",
14641
+ edition,
14642
+ platform: getAppPlatform(),
14643
+ architecture: getAppArchitecture(),
14644
+ currentVersion: version2
14645
+ }).then((response) => {
14646
+ if (!response.newVersions || response.newVersions.length === 0) {
14647
+ setUpdateState({ type: "up-to-date", lastCheckedMillis });
14648
+ logger2.info("No updates available");
14649
+ return;
14650
+ }
14651
+ setUpdateState({
14652
+ type: "updates-available",
14653
+ lastCheckedMillis,
14654
+ response
14655
+ });
14656
+ logger2.info(
14657
+ `Update available: ${response.latestVersion} - Download at ${response.downloadUrl}`
14658
+ );
14659
+ }).catch((error) => {
14660
+ const err = new Error("Failed to check for updates");
14661
+ err.cause = error instanceof Error ? error : new Error(String(error));
14662
+ setUpdateState({
14663
+ lastCheckedMillis,
14664
+ type: "error",
14665
+ error: String(err)
14666
+ });
14667
+ logger2.error(err);
14668
+ });
14669
+ }, [a, setUpdateState, edition, logger2, version2]);
14670
+ useEffect9(() => {
14671
+ checkForUpdates();
14672
+ const interval = setInterval(checkForUpdates, 1e3 * 60 * 60);
14673
+ return () => clearInterval(interval);
14674
+ }, [checkForUpdates]);
14675
+ useEffect9(() => {
14676
+ return () => {
14677
+ setUpdateState(null);
14678
+ };
14679
+ }, [setUpdateState]);
14680
+ return null;
14681
+ };
14682
+
14683
+ // src/env.ts
14684
+ var getEnv = (logger2) => {
14685
+ const PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : {
14686
+ from: 4100,
14687
+ to: 4200
14688
+ };
14689
+ let API_BASE_URL;
14690
+ try {
14691
+ API_BASE_URL = process.env.API_BASE_URL ? new URL(process.env.API_BASE_URL) : new URL("https://arcanewizards.com");
14692
+ } catch (error) {
14693
+ const err = new Error(`Invalid API_BASE_URL: ${process.env.API_BASE_URL}`);
14694
+ err.cause = error instanceof Error ? error : new Error(String(error));
14695
+ logger2.error(err);
14696
+ throw err;
14697
+ }
14698
+ return {
14699
+ PORT,
14700
+ API_BASE_URL
14701
+ };
14702
+ };
14703
+
14473
14704
  // src/app.tsx
14474
- import { jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
14705
+ import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
14475
14706
  var App = ({
14476
14707
  title,
14477
14708
  version: version2,
14709
+ edition,
14478
14710
  toolkit,
14479
14711
  dataDirectory,
14480
14712
  logger: logger2,
@@ -14482,8 +14714,9 @@ var App = ({
14482
14714
  setWindowUrl,
14483
14715
  shutdownContext
14484
14716
  }) => {
14717
+ const env = useMemo6(() => getEnv(logger2), [logger2]);
14485
14718
  const { data, error, updateData, resetData } = useDataFileContext(ToolboxConfigData);
14486
- useEffect9(() => {
14719
+ useEffect10(() => {
14487
14720
  if (error) {
14488
14721
  logger2.warn("Resetting config to application default");
14489
14722
  resetData();
@@ -14492,13 +14725,20 @@ var App = ({
14492
14725
  const onUpdateConfig = (diff) => {
14493
14726
  updateData((prev) => patchJson(prev, diff) ?? DEFAULT_CONFIG);
14494
14727
  };
14495
- const [state, setState] = useState6({
14728
+ const [state, setState] = useState7({
14496
14729
  inputs: {},
14497
14730
  outputs: {},
14498
- generators: {}
14731
+ generators: {},
14732
+ updates: null
14499
14733
  });
14500
- const [handlers, setHandlers] = useState6({ children: {} });
14501
- const availableHandlers = useMemo5(
14734
+ const setUpdateState = useCallback7((updates) => {
14735
+ setState((prev) => ({
14736
+ ...prev,
14737
+ updates
14738
+ }));
14739
+ }, []);
14740
+ const [handlers, setHandlers] = useState7({ children: {} });
14741
+ const availableHandlers = useMemo6(
14502
14742
  () => mapTree(
14503
14743
  handlers,
14504
14744
  (node) => Object.fromEntries(
@@ -14507,7 +14747,7 @@ var App = ({
14507
14747
  ),
14508
14748
  [handlers]
14509
14749
  );
14510
- const callHandler = useCallback6(
14750
+ const callHandler = useCallback7(
14511
14751
  async (call) => {
14512
14752
  const handlerFunc = getTreeValue(handlers, call.path)?.[call.handler];
14513
14753
  if (handlerFunc) {
@@ -14519,6 +14759,54 @@ var App = ({
14519
14759
  },
14520
14760
  [handlers]
14521
14761
  );
14762
+ const license = useLicense();
14763
+ const appListenerConfig = useMemo6(
14764
+ () => ({
14765
+ default: {
14766
+ port: env.PORT
14767
+ }
14768
+ }),
14769
+ [env.PORT]
14770
+ );
14771
+ if (!license) {
14772
+ return;
14773
+ }
14774
+ const children = data.agreedToLicense === license.hash ? /* @__PURE__ */ jsxs2(Fragment4, { children: [
14775
+ /* @__PURE__ */ jsx9(
14776
+ C.ToolboxRoot,
14777
+ {
14778
+ config: data,
14779
+ state,
14780
+ handlers: availableHandlers,
14781
+ onUpdateConfig,
14782
+ onCallHandler: callHandler,
14783
+ license: license.text
14784
+ }
14785
+ ),
14786
+ /* @__PURE__ */ jsx9(InputConnections, { state, setState }),
14787
+ /* @__PURE__ */ jsx9(
14788
+ Generators,
14789
+ {
14790
+ state,
14791
+ setState,
14792
+ setHandlers
14793
+ }
14794
+ ),
14795
+ /* @__PURE__ */ jsx9(OutputConnections, { state, setState })
14796
+ ] }) : /* @__PURE__ */ jsx9(
14797
+ C.LicenseGate,
14798
+ {
14799
+ license: license.text,
14800
+ hash: license.hash,
14801
+ onAcceptLicense: (agreedToLicense) => {
14802
+ logger2.info(`License accepted: ${agreedToLicense}`);
14803
+ updateData((current) => ({
14804
+ ...current,
14805
+ agreedToLicense
14806
+ }));
14807
+ }
14808
+ }
14809
+ );
14522
14810
  return /* @__PURE__ */ jsxs2(
14523
14811
  AppShell,
14524
14812
  {
@@ -14529,32 +14817,22 @@ var App = ({
14529
14817
  logEventEmitter,
14530
14818
  shutdownContext,
14531
14819
  children: [
14532
- /* @__PURE__ */ jsx9(
14533
- C.ToolboxRoot,
14820
+ children,
14821
+ data.checkForUpdates && /* @__PURE__ */ jsx9(
14822
+ UpdateChecker,
14534
14823
  {
14535
- config: data,
14536
- state,
14537
- handlers: availableHandlers,
14538
- onUpdateConfig,
14539
- onCallHandler: callHandler
14824
+ version: version2,
14825
+ edition,
14826
+ apiBaseUrl: env.API_BASE_URL,
14827
+ setUpdateState
14540
14828
  }
14541
14829
  ),
14542
- /* @__PURE__ */ jsx9(InputConnections, { state, setState }),
14543
- /* @__PURE__ */ jsx9(Generators, { state, setState, setHandlers }),
14544
- /* @__PURE__ */ jsx9(OutputConnections, { state, setState }),
14545
14830
  /* @__PURE__ */ jsx9(
14546
14831
  AppListenerManager,
14547
14832
  {
14548
14833
  toolkit,
14549
14834
  setWindowUrl,
14550
- listenerConfig: {
14551
- default: {
14552
- port: {
14553
- from: 4100,
14554
- to: 4200
14555
- }
14556
- }
14557
- }
14835
+ listenerConfig: appListenerConfig
14558
14836
  }
14559
14837
  )
14560
14838
  ]
@@ -14572,18 +14850,20 @@ var createApp = (props) => {
14572
14850
  };
14573
14851
 
14574
14852
  // package.json
14575
- var version = "0.1.0";
14853
+ var version = "0.1.2";
14576
14854
 
14577
14855
  // src/index.ts
14578
14856
  var runTimecodeToolboxServer = ({
14579
14857
  logger: logger2,
14580
14858
  appProps,
14581
14859
  toolkitOptions,
14582
- title
14860
+ title,
14861
+ edition
14583
14862
  }) => runSigilApp({
14584
14863
  logger: logger2,
14585
14864
  title,
14586
14865
  version,
14866
+ edition,
14587
14867
  appProps,
14588
14868
  toolkitOptions,
14589
14869
  createApp,
@@ -14607,7 +14887,8 @@ var server = runTimecodeToolboxServer({
14607
14887
  toolkitOptions: {
14608
14888
  entrypointJsFile: path2.join(path2.dirname(__dirname), "dist/entrypoint.js")
14609
14889
  },
14610
- title: "Timecode Toolbox Server"
14890
+ title: "Timecode Toolbox Server",
14891
+ edition: "cli"
14611
14892
  });
14612
14893
  var shutdown = () => server.shutdown().catch((err) => {
14613
14894
  logger.error({ err }, "Error during shutdown");