@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/index.mjs CHANGED
@@ -4,7 +4,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __commonJS = (cb, mod) => function __require() {
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
8
14
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
15
  };
10
16
  var __export = (target, all) => {
@@ -1805,6 +1811,7 @@ var runSigilApp = ({
1805
1811
  logger: upstreamLogger,
1806
1812
  title,
1807
1813
  version: version2,
1814
+ edition,
1808
1815
  appProps,
1809
1816
  toolkitOptions,
1810
1817
  createApp: createApp2,
@@ -1863,10 +1870,10 @@ var runSigilApp = ({
1863
1870
  logger.info(`${title} ready to start listening`);
1864
1871
  }
1865
1872
  });
1866
- let api = null;
1873
+ let api2 = null;
1867
1874
  const apiListeners = /* @__PURE__ */ new Set();
1868
1875
  const setAppApi = (value) => {
1869
- api = value;
1876
+ api2 = value;
1870
1877
  for (const listener of apiListeners) {
1871
1878
  listener(value);
1872
1879
  }
@@ -1899,6 +1906,7 @@ var runSigilApp = ({
1899
1906
  createApp2({
1900
1907
  title,
1901
1908
  version: version2,
1909
+ edition,
1902
1910
  toolkit,
1903
1911
  logger,
1904
1912
  logEventEmitter,
@@ -1918,8 +1926,8 @@ var runSigilApp = ({
1918
1926
  if (event === "apiChange") {
1919
1927
  const apiListener = listener;
1920
1928
  apiListeners.add(apiListener);
1921
- if (api) {
1922
- apiListener(api);
1929
+ if (api2) {
1930
+ apiListener(api2);
1923
1931
  }
1924
1932
  return;
1925
1933
  }
@@ -2133,10 +2141,10 @@ var AppListenerManager = ({
2133
2141
 
2134
2142
  // src/app.tsx
2135
2143
  import {
2136
- useCallback as useCallback6,
2137
- useEffect as useEffect9,
2138
- useMemo as useMemo5,
2139
- useState as useState6
2144
+ useCallback as useCallback7,
2145
+ useEffect as useEffect10,
2146
+ useMemo as useMemo6,
2147
+ useState as useState7
2140
2148
  } from "react";
2141
2149
 
2142
2150
  // src/components/backend/index.ts
@@ -6192,8 +6200,7 @@ var NEVER = INVALID;
6192
6200
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js
6193
6201
  var zod_default = external_exports;
6194
6202
 
6195
- // ../../packages/sigil/dist/chunk-H4U4Z4GM.js
6196
- import { useEffect as useEffect4 } from "react";
6203
+ // ../../packages/sigil/dist/chunk-WYUGJOEB.js
6197
6204
  var SIGIL_COLOR = external_exports.enum([
6198
6205
  "purple",
6199
6206
  "blue",
@@ -6288,12 +6295,18 @@ var OUTPUT_CONFIG = zod_default.object({
6288
6295
  var TOOLBOX_CONFIG = zod_default.object({
6289
6296
  inputs: zod_default.record(zod_default.string(), INPUT_CONFIG),
6290
6297
  generators: zod_default.record(zod_default.string(), GENERATOR_CONFIG),
6291
- outputs: zod_default.record(zod_default.string(), OUTPUT_CONFIG)
6298
+ outputs: zod_default.record(zod_default.string(), OUTPUT_CONFIG),
6299
+ /**
6300
+ * Hash of the license the user has agreed to.
6301
+ */
6302
+ agreedToLicense: zod_default.string().optional(),
6303
+ checkForUpdates: zod_default.boolean().optional().default(true)
6292
6304
  });
6293
6305
  var DEFAULT_CONFIG = {
6294
6306
  inputs: {},
6295
6307
  generators: {},
6296
- outputs: {}
6308
+ outputs: {},
6309
+ checkForUpdates: true
6297
6310
  };
6298
6311
  var isPlaying = (state) => state.state === "playing" || state.state === "lagging";
6299
6312
  var isStopped = (state) => state.state === "stopped";
@@ -6309,9 +6322,11 @@ var DEFAULT_PROPS2 = {
6309
6322
  state: {
6310
6323
  inputs: {},
6311
6324
  outputs: {},
6312
- generators: {}
6325
+ generators: {},
6326
+ updates: null
6313
6327
  },
6314
- handlers: { children: {} }
6328
+ handlers: { children: {} },
6329
+ license: ""
6315
6330
  };
6316
6331
  var ToolboxRoot = class extends Base {
6317
6332
  /** @hidden */
@@ -6339,7 +6354,8 @@ var ToolboxRoot = class extends Base {
6339
6354
  key: idMap.getId(this),
6340
6355
  config: this.props.config,
6341
6356
  state: this.props.state,
6342
- handlers: this.props.handlers
6357
+ handlers: this.props.handlers,
6358
+ license: this.props.license
6343
6359
  };
6344
6360
  }
6345
6361
  /** @hidden */
@@ -6368,9 +6384,56 @@ var ToolboxRoot = class extends Base {
6368
6384
  };
6369
6385
  };
6370
6386
 
6387
+ // src/components/backend/license-gate.ts
6388
+ import {
6389
+ Base as Base2,
6390
+ EventEmitter as EventEmitter4
6391
+ } from "@arcanejs/toolkit/components/base";
6392
+ var DEFAULT_PROPS3 = {
6393
+ license: "",
6394
+ hash: ""
6395
+ };
6396
+ var LicenseGate = class extends Base2 {
6397
+ /** @hidden */
6398
+ events = new EventEmitter4();
6399
+ constructor(props) {
6400
+ super(DEFAULT_PROPS3, props, {
6401
+ onPropsUpdated: (oldProps) => this.events.processPropChanges(
6402
+ {
6403
+ onAcceptLicense: "acceptLicense"
6404
+ },
6405
+ oldProps,
6406
+ this.props
6407
+ )
6408
+ });
6409
+ this.triggerInitialPropsUpdate();
6410
+ }
6411
+ addListener = this.events.addListener;
6412
+ removeListener = this.events.removeListener;
6413
+ /** @hidden */
6414
+ getProtoInfo(idMap) {
6415
+ return {
6416
+ namespace: "timecode-toolbox",
6417
+ component: "license-gate",
6418
+ key: idMap.getId(this),
6419
+ license: this.props.license,
6420
+ hash: this.props.hash
6421
+ };
6422
+ }
6423
+ /** @hidden */
6424
+ handleMessage = (message) => {
6425
+ if (isTimecodeToolboxComponentMessage(message, "license-gate")) {
6426
+ if (message.action === "accept-license") {
6427
+ this.events.emit("acceptLicense", message.hash);
6428
+ }
6429
+ }
6430
+ };
6431
+ };
6432
+
6371
6433
  // src/components/backend/index.ts
6372
6434
  var C = prepareComponents2("timecode-toolbox", {
6373
- ToolboxRoot
6435
+ ToolboxRoot,
6436
+ LicenseGate
6374
6437
  });
6375
6438
 
6376
6439
  // src/config.ts
@@ -6435,7 +6498,7 @@ var patchJson = (old, diff) => {
6435
6498
 
6436
6499
  // src/inputs/artnet.tsx
6437
6500
  import { useDataFileData } from "@arcanejs/react-toolkit/data";
6438
- import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef2, useState as useState3 } from "react";
6501
+ import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef2, useState as useState3 } from "react";
6439
6502
 
6440
6503
  // ../../packages/artnet/dist/chunk-J2HDMITA.js
6441
6504
  var ARTNET_PORT = 6454;
@@ -6454,7 +6517,7 @@ var TIMECODE_FPS = {
6454
6517
 
6455
6518
  // ../../packages/artnet/dist/index.js
6456
6519
  import { createSocket } from "dgram";
6457
- import EventEmitter4 from "events";
6520
+ import EventEmitter5 from "events";
6458
6521
  var ARTNET_HEADER = "Art-Net\0";
6459
6522
  var ARTNET_VERSION = 14;
6460
6523
  var OP_TIME_CODE = 38656;
@@ -6571,7 +6634,7 @@ var parseTimecodePacket = (packet, source) => {
6571
6634
  };
6572
6635
  };
6573
6636
  var createArtnet = (config) => {
6574
- const events = new EventEmitter4();
6637
+ const events = new EventEmitter5();
6575
6638
  let sendSocket = null;
6576
6639
  let receiveSocket = null;
6577
6640
  let destroyed = false;
@@ -6767,7 +6830,7 @@ var ArtnetInputConnection = ({
6767
6830
  const log = useLogger();
6768
6831
  const [artnetInstance, setArtnetInstance] = useState3(null);
6769
6832
  const delayRef = useRef2(delayMs ?? 0);
6770
- useEffect5(() => {
6833
+ useEffect4(() => {
6771
6834
  delayRef.current = delayMs ?? 0;
6772
6835
  }, [delayMs]);
6773
6836
  const setConnection = useCallback2(
@@ -6780,7 +6843,7 @@ var ArtnetInputConnection = ({
6780
6843
  })),
6781
6844
  [setState, uuid]
6782
6845
  );
6783
- useEffect5(() => {
6846
+ useEffect4(() => {
6784
6847
  const connectionConfig = {
6785
6848
  timecode: {
6786
6849
  name: null,
@@ -6833,7 +6896,7 @@ var ArtnetInputConnection = ({
6833
6896
  }
6834
6897
  };
6835
6898
  }, [setConnection, uuid, iface, port, log]);
6836
- useEffect5(() => {
6899
+ useEffect4(() => {
6837
6900
  let lastTimecode = null;
6838
6901
  let lastUsedTimecode = lastTimecode;
6839
6902
  let timecode = null;
@@ -6922,7 +6985,7 @@ var ArtnetInputConnection = ({
6922
6985
  artnetInstance?.removeListener("timecode", onTimecode);
6923
6986
  };
6924
6987
  }, [artnetInstance, log, iface, name, setConnection]);
6925
- useEffect5(() => {
6988
+ useEffect4(() => {
6926
6989
  return () => {
6927
6990
  setState((current) => {
6928
6991
  const { [uuid]: _, ...rest } = current.inputs;
@@ -6960,7 +7023,7 @@ import { useDataFileData as useDataFileData2 } from "@arcanejs/react-toolkit/dat
6960
7023
  import {
6961
7024
  useCallback as useCallback3,
6962
7025
  useContext as useContext2,
6963
- useEffect as useEffect6,
7026
+ useEffect as useEffect5,
6964
7027
  useMemo as useMemo2,
6965
7028
  useRef as useRef3
6966
7029
  } from "react";
@@ -6972,7 +7035,7 @@ var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
6972
7035
  var __getOwnPropNames2 = Object.getOwnPropertyNames;
6973
7036
  var __getProtoOf2 = Object.getPrototypeOf;
6974
7037
  var __hasOwnProp2 = Object.prototype.hasOwnProperty;
6975
- var __commonJS2 = (cb, mod) => function __require() {
7038
+ var __commonJS2 = (cb, mod) => function __require2() {
6976
7039
  return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
6977
7040
  };
6978
7041
  var __copyProps2 = (to, from, except, desc) => {
@@ -7511,7 +7574,7 @@ var calculateUniqueNodeId = (info) => {
7511
7574
 
7512
7575
  // ../../packages/tcnet/dist/index.js
7513
7576
  import { createSocket as createSocket2 } from "dgram";
7514
- import EventEmitter5 from "events";
7577
+ import EventEmitter6 from "events";
7515
7578
  import { promisify } from "util";
7516
7579
  var require_lodash = __commonJS2({
7517
7580
  "../../node_modules/.pnpm/lodash@4.17.23/node_modules/lodash/lodash.js"(exports, module) {
@@ -13030,7 +13093,7 @@ var bindSocket2 = (socket, port, address) => {
13030
13093
  };
13031
13094
  var createTCNetNode = (props) => {
13032
13095
  const { logger } = props;
13033
- const events = new EventEmitter5();
13096
+ const events = new EventEmitter6();
13034
13097
  let iface = null;
13035
13098
  const sockets = {
13036
13099
  broadcastSend: null,
@@ -13541,7 +13604,7 @@ var createTCNetNode = (props) => {
13541
13604
  };
13542
13605
 
13543
13606
  // ../../packages/tcnet/dist/monitor.js
13544
- import EventEmitter6 from "events";
13607
+ import EventEmitter7 from "events";
13545
13608
  var MAX_DELTA_MS = 10;
13546
13609
  var layerDataIdToIndex = (dataLayerId) => {
13547
13610
  return dataLayerId - 1;
@@ -13560,7 +13623,7 @@ var TCNET_LAYER_INDEXES = Array.from(
13560
13623
  (_, i) => asLayerIndex(i)
13561
13624
  );
13562
13625
  var createTCNetTimecodeMonitor = (tcNetNode, logger) => {
13563
- const events = new EventEmitter6();
13626
+ const events = new EventEmitter7();
13564
13627
  const on = events.on.bind(events);
13565
13628
  const addListener = events.addListener.bind(events);
13566
13629
  const removeListener = events.removeListener.bind(events);
@@ -13847,7 +13910,7 @@ var TcnetInputConnection = ({
13847
13910
  const nodeRef = useRef3(null);
13848
13911
  const isMountedRef = useRef3(true);
13849
13912
  const delayRef = useRef3(delayMs ?? 0);
13850
- useEffect6(() => {
13913
+ useEffect5(() => {
13851
13914
  delayRef.current = delayMs ?? 0;
13852
13915
  }, [delayMs]);
13853
13916
  const setConnection = useCallback3(
@@ -13887,7 +13950,7 @@ var TcnetInputConnection = ({
13887
13950
  });
13888
13951
  };
13889
13952
  }, [setConnection]);
13890
- useEffect6(() => {
13953
+ useEffect5(() => {
13891
13954
  const node = createTCNetNode({
13892
13955
  logger,
13893
13956
  networkInterface: iface,
@@ -13981,7 +14044,7 @@ var TcnetInputConnection = ({
13981
14044
  await nodeRef.current.destroy();
13982
14045
  }
13983
14046
  });
13984
- useEffect6(() => {
14047
+ useEffect5(() => {
13985
14048
  return () => {
13986
14049
  isMountedRef.current = false;
13987
14050
  setState((current) => {
@@ -14028,7 +14091,7 @@ var InputConnections = (props) => {
14028
14091
  import { useDataFileData as useDataFileData3 } from "@arcanejs/react-toolkit/data";
14029
14092
  import {
14030
14093
  useCallback as useCallback4,
14031
- useEffect as useEffect7,
14094
+ useEffect as useEffect6,
14032
14095
  useMemo as useMemo3,
14033
14096
  useState as useState4
14034
14097
  } from "react";
@@ -14087,7 +14150,7 @@ var ArtnetOutputConnection = ({
14087
14150
  })),
14088
14151
  [setState, uuid]
14089
14152
  );
14090
- useEffect7(() => {
14153
+ useEffect6(() => {
14091
14154
  let artnet = null;
14092
14155
  setConnection({ status: "connecting" });
14093
14156
  const created = createArtnet({
@@ -14124,7 +14187,7 @@ var ArtnetOutputConnection = ({
14124
14187
  }
14125
14188
  };
14126
14189
  }, [setConnection, uuid, target, log]);
14127
- useEffect7(() => {
14190
+ useEffect6(() => {
14128
14191
  return () => {
14129
14192
  setState((current) => {
14130
14193
  const { [uuid]: _, ...rest } = current.outputs;
@@ -14143,7 +14206,7 @@ var ArtnetOutputConnection = ({
14143
14206
  () => tcInstance?.state ? adjustTimecodeForDelay(tcInstance.state, config.delayMs ?? 0) : null,
14144
14207
  [tcInstance?.state, config.delayMs]
14145
14208
  );
14146
- useEffect7(() => {
14209
+ useEffect6(() => {
14147
14210
  if (!artnetInstance) {
14148
14211
  return;
14149
14212
  }
@@ -14191,7 +14254,7 @@ var OutputConnections = (props) => {
14191
14254
  // src/generators/clock.tsx
14192
14255
  import {
14193
14256
  useCallback as useCallback5,
14194
- useEffect as useEffect8,
14257
+ useEffect as useEffect7,
14195
14258
  useMemo as useMemo4,
14196
14259
  useState as useState5
14197
14260
  } from "react";
@@ -14384,7 +14447,7 @@ var ClockGenerator = ({
14384
14447
  }
14385
14448
  });
14386
14449
  }, []);
14387
- useEffect8(() => {
14450
+ useEffect7(() => {
14388
14451
  setLocalState((current) => {
14389
14452
  if (current.state === "none" || current.state === "stopped") {
14390
14453
  return current;
@@ -14399,12 +14462,12 @@ var ClockGenerator = ({
14399
14462
  };
14400
14463
  });
14401
14464
  }, [speed]);
14402
- useEffect8(() => {
14465
+ useEffect7(() => {
14403
14466
  setHandlers(
14404
14467
  (current) => updateTreeState(current, id, { play, pause, seekRelative, beginning })
14405
14468
  );
14406
14469
  }, [setHandlers, id, play, pause, seekRelative, beginning]);
14407
- useEffect8(
14470
+ useEffect7(
14408
14471
  () => setState((current) => ({
14409
14472
  ...current,
14410
14473
  generators: {
@@ -14425,7 +14488,7 @@ var ClockGenerator = ({
14425
14488
  })),
14426
14489
  [setState, uuid, state, config.name]
14427
14490
  );
14428
- useEffect8(
14491
+ useEffect7(
14429
14492
  () => () => {
14430
14493
  setState((current) => {
14431
14494
  const { [uuid]: _, ...rest } = current.generators;
@@ -14466,11 +14529,179 @@ var Generators = (props) => {
14466
14529
  return /* @__PURE__ */ jsx8(Fragment3, { children: /* @__PURE__ */ jsx8(ClockGenerators, { ...props }) });
14467
14530
  };
14468
14531
 
14532
+ // src/license.ts
14533
+ import { createHash } from "crypto";
14534
+ import { readFile } from "fs/promises";
14535
+ import { useEffect as useEffect8, useState as useState6 } from "react";
14536
+ var getLicense = async () => {
14537
+ const licenseText = await readFile(__require.resolve("../LICENSE"), "utf-8");
14538
+ const hash = createHash("sha256").update(licenseText).digest("hex");
14539
+ return { text: licenseText, hash };
14540
+ };
14541
+ var useLicense = () => {
14542
+ const [license, setLicense] = useState6(null);
14543
+ useEffect8(() => {
14544
+ getLicense().then(setLicense);
14545
+ }, []);
14546
+ return license;
14547
+ };
14548
+
14549
+ // src/updates.tsx
14550
+ import { useCallback as useCallback6, useEffect as useEffect9, useMemo as useMemo5 } from "react";
14551
+
14552
+ // ../../packages/apis/dist/index.js
14553
+ var APP_PLATFORM = zod_default.enum(["windows", "macos", "linux"]);
14554
+ var APP_ARCHITECTURE = zod_default.enum(["x64", "arm64"]);
14555
+ var APP_EDITION = zod_default.enum(["desktop", "cli"]);
14556
+ var CHECK_FOR_UPDATES_REQUEST = zod_default.object({
14557
+ app: zod_default.string(),
14558
+ edition: APP_EDITION,
14559
+ platform: APP_PLATFORM,
14560
+ architecture: APP_ARCHITECTURE,
14561
+ currentVersion: zod_default.string()
14562
+ });
14563
+ var CHECK_FOR_UPDATES_VERSION = zod_default.object({
14564
+ version: zod_default.string(),
14565
+ releaseNotes: zod_default.string()
14566
+ });
14567
+ var CHECK_FOR_UPDATES_RESPONSE = zod_default.object({
14568
+ downloadUrl: zod_default.string().optional(),
14569
+ latestVersion: zod_default.string(),
14570
+ newVersions: zod_default.array(CHECK_FOR_UPDATES_VERSION).optional()
14571
+ });
14572
+ var ApiError = class extends Error {
14573
+ constructor(message, response) {
14574
+ super(message);
14575
+ this.response = response;
14576
+ this.name = "ApiError";
14577
+ }
14578
+ };
14579
+ var api = (baseUrl) => {
14580
+ const checkForUpdates = async (request) => {
14581
+ const response = await fetch(new URL("/api/v1/updates", baseUrl), {
14582
+ method: "POST",
14583
+ headers: { "Content-Type": "application/json" },
14584
+ body: JSON.stringify(request)
14585
+ });
14586
+ if (!response.ok) {
14587
+ throw new ApiError(
14588
+ `Failed to check for updates: ${response.statusText} - ${await response.text()}`,
14589
+ response
14590
+ );
14591
+ }
14592
+ const responseData = await response.json();
14593
+ return CHECK_FOR_UPDATES_RESPONSE.parse(responseData);
14594
+ };
14595
+ return {
14596
+ checkForUpdates
14597
+ };
14598
+ };
14599
+
14600
+ // src/updates.tsx
14601
+ var getAppPlatform = () => {
14602
+ switch (process.platform) {
14603
+ case "win32":
14604
+ return "windows";
14605
+ case "darwin":
14606
+ return "macos";
14607
+ case "linux":
14608
+ return "linux";
14609
+ default:
14610
+ throw new Error(`Unsupported platform: ${process.platform}`);
14611
+ }
14612
+ };
14613
+ var getAppArchitecture = () => {
14614
+ switch (process.arch) {
14615
+ case "x64":
14616
+ return "x64";
14617
+ case "arm64":
14618
+ return "arm64";
14619
+ default:
14620
+ throw new Error(`Unsupported architecture: ${process.arch}`);
14621
+ }
14622
+ };
14623
+ var UpdateChecker = ({
14624
+ apiBaseUrl,
14625
+ version: version2,
14626
+ edition,
14627
+ setUpdateState
14628
+ }) => {
14629
+ const a = useMemo5(() => api(apiBaseUrl), [apiBaseUrl]);
14630
+ const logger = useLogger();
14631
+ const checkForUpdates = useCallback6(() => {
14632
+ const lastCheckedMillis = Date.now();
14633
+ setUpdateState({ type: "loading" });
14634
+ a.checkForUpdates({
14635
+ app: "timecode-toolbox",
14636
+ edition,
14637
+ platform: getAppPlatform(),
14638
+ architecture: getAppArchitecture(),
14639
+ currentVersion: version2
14640
+ }).then((response) => {
14641
+ if (!response.newVersions || response.newVersions.length === 0) {
14642
+ setUpdateState({ type: "up-to-date", lastCheckedMillis });
14643
+ logger.info("No updates available");
14644
+ return;
14645
+ }
14646
+ setUpdateState({
14647
+ type: "updates-available",
14648
+ lastCheckedMillis,
14649
+ response
14650
+ });
14651
+ logger.info(
14652
+ `Update available: ${response.latestVersion} - Download at ${response.downloadUrl}`
14653
+ );
14654
+ }).catch((error) => {
14655
+ const err = new Error("Failed to check for updates");
14656
+ err.cause = error instanceof Error ? error : new Error(String(error));
14657
+ setUpdateState({
14658
+ lastCheckedMillis,
14659
+ type: "error",
14660
+ error: String(err)
14661
+ });
14662
+ logger.error(err);
14663
+ });
14664
+ }, [a, setUpdateState, edition, logger, version2]);
14665
+ useEffect9(() => {
14666
+ checkForUpdates();
14667
+ const interval = setInterval(checkForUpdates, 1e3 * 60 * 60);
14668
+ return () => clearInterval(interval);
14669
+ }, [checkForUpdates]);
14670
+ useEffect9(() => {
14671
+ return () => {
14672
+ setUpdateState(null);
14673
+ };
14674
+ }, [setUpdateState]);
14675
+ return null;
14676
+ };
14677
+
14678
+ // src/env.ts
14679
+ var getEnv = (logger) => {
14680
+ const PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : {
14681
+ from: 4100,
14682
+ to: 4200
14683
+ };
14684
+ let API_BASE_URL;
14685
+ try {
14686
+ API_BASE_URL = process.env.API_BASE_URL ? new URL(process.env.API_BASE_URL) : new URL("https://arcanewizards.com");
14687
+ } catch (error) {
14688
+ const err = new Error(`Invalid API_BASE_URL: ${process.env.API_BASE_URL}`);
14689
+ err.cause = error instanceof Error ? error : new Error(String(error));
14690
+ logger.error(err);
14691
+ throw err;
14692
+ }
14693
+ return {
14694
+ PORT,
14695
+ API_BASE_URL
14696
+ };
14697
+ };
14698
+
14469
14699
  // src/app.tsx
14470
- import { jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
14700
+ import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
14471
14701
  var App = ({
14472
14702
  title,
14473
14703
  version: version2,
14704
+ edition,
14474
14705
  toolkit,
14475
14706
  dataDirectory,
14476
14707
  logger,
@@ -14478,8 +14709,9 @@ var App = ({
14478
14709
  setWindowUrl,
14479
14710
  shutdownContext
14480
14711
  }) => {
14712
+ const env = useMemo6(() => getEnv(logger), [logger]);
14481
14713
  const { data, error, updateData, resetData } = useDataFileContext(ToolboxConfigData);
14482
- useEffect9(() => {
14714
+ useEffect10(() => {
14483
14715
  if (error) {
14484
14716
  logger.warn("Resetting config to application default");
14485
14717
  resetData();
@@ -14488,13 +14720,20 @@ var App = ({
14488
14720
  const onUpdateConfig = (diff) => {
14489
14721
  updateData((prev) => patchJson(prev, diff) ?? DEFAULT_CONFIG);
14490
14722
  };
14491
- const [state, setState] = useState6({
14723
+ const [state, setState] = useState7({
14492
14724
  inputs: {},
14493
14725
  outputs: {},
14494
- generators: {}
14726
+ generators: {},
14727
+ updates: null
14495
14728
  });
14496
- const [handlers, setHandlers] = useState6({ children: {} });
14497
- const availableHandlers = useMemo5(
14729
+ const setUpdateState = useCallback7((updates) => {
14730
+ setState((prev) => ({
14731
+ ...prev,
14732
+ updates
14733
+ }));
14734
+ }, []);
14735
+ const [handlers, setHandlers] = useState7({ children: {} });
14736
+ const availableHandlers = useMemo6(
14498
14737
  () => mapTree(
14499
14738
  handlers,
14500
14739
  (node) => Object.fromEntries(
@@ -14503,7 +14742,7 @@ var App = ({
14503
14742
  ),
14504
14743
  [handlers]
14505
14744
  );
14506
- const callHandler = useCallback6(
14745
+ const callHandler = useCallback7(
14507
14746
  async (call) => {
14508
14747
  const handlerFunc = getTreeValue(handlers, call.path)?.[call.handler];
14509
14748
  if (handlerFunc) {
@@ -14515,6 +14754,54 @@ var App = ({
14515
14754
  },
14516
14755
  [handlers]
14517
14756
  );
14757
+ const license = useLicense();
14758
+ const appListenerConfig = useMemo6(
14759
+ () => ({
14760
+ default: {
14761
+ port: env.PORT
14762
+ }
14763
+ }),
14764
+ [env.PORT]
14765
+ );
14766
+ if (!license) {
14767
+ return;
14768
+ }
14769
+ const children = data.agreedToLicense === license.hash ? /* @__PURE__ */ jsxs2(Fragment4, { children: [
14770
+ /* @__PURE__ */ jsx9(
14771
+ C.ToolboxRoot,
14772
+ {
14773
+ config: data,
14774
+ state,
14775
+ handlers: availableHandlers,
14776
+ onUpdateConfig,
14777
+ onCallHandler: callHandler,
14778
+ license: license.text
14779
+ }
14780
+ ),
14781
+ /* @__PURE__ */ jsx9(InputConnections, { state, setState }),
14782
+ /* @__PURE__ */ jsx9(
14783
+ Generators,
14784
+ {
14785
+ state,
14786
+ setState,
14787
+ setHandlers
14788
+ }
14789
+ ),
14790
+ /* @__PURE__ */ jsx9(OutputConnections, { state, setState })
14791
+ ] }) : /* @__PURE__ */ jsx9(
14792
+ C.LicenseGate,
14793
+ {
14794
+ license: license.text,
14795
+ hash: license.hash,
14796
+ onAcceptLicense: (agreedToLicense) => {
14797
+ logger.info(`License accepted: ${agreedToLicense}`);
14798
+ updateData((current) => ({
14799
+ ...current,
14800
+ agreedToLicense
14801
+ }));
14802
+ }
14803
+ }
14804
+ );
14518
14805
  return /* @__PURE__ */ jsxs2(
14519
14806
  AppShell,
14520
14807
  {
@@ -14525,32 +14812,22 @@ var App = ({
14525
14812
  logEventEmitter,
14526
14813
  shutdownContext,
14527
14814
  children: [
14528
- /* @__PURE__ */ jsx9(
14529
- C.ToolboxRoot,
14815
+ children,
14816
+ data.checkForUpdates && /* @__PURE__ */ jsx9(
14817
+ UpdateChecker,
14530
14818
  {
14531
- config: data,
14532
- state,
14533
- handlers: availableHandlers,
14534
- onUpdateConfig,
14535
- onCallHandler: callHandler
14819
+ version: version2,
14820
+ edition,
14821
+ apiBaseUrl: env.API_BASE_URL,
14822
+ setUpdateState
14536
14823
  }
14537
14824
  ),
14538
- /* @__PURE__ */ jsx9(InputConnections, { state, setState }),
14539
- /* @__PURE__ */ jsx9(Generators, { state, setState, setHandlers }),
14540
- /* @__PURE__ */ jsx9(OutputConnections, { state, setState }),
14541
14825
  /* @__PURE__ */ jsx9(
14542
14826
  AppListenerManager,
14543
14827
  {
14544
14828
  toolkit,
14545
14829
  setWindowUrl,
14546
- listenerConfig: {
14547
- default: {
14548
- port: {
14549
- from: 4100,
14550
- to: 4200
14551
- }
14552
- }
14553
- }
14830
+ listenerConfig: appListenerConfig
14554
14831
  }
14555
14832
  )
14556
14833
  ]
@@ -14568,7 +14845,7 @@ var createApp = (props) => {
14568
14845
  };
14569
14846
 
14570
14847
  // package.json
14571
- var version = "0.1.0";
14848
+ var version = "0.1.2";
14572
14849
 
14573
14850
  // src/urls.ts
14574
14851
  var urls_exports = {};
@@ -14613,11 +14890,13 @@ var runTimecodeToolboxServer = ({
14613
14890
  logger,
14614
14891
  appProps,
14615
14892
  toolkitOptions,
14616
- title
14893
+ title,
14894
+ edition
14617
14895
  }) => runSigilApp({
14618
14896
  logger,
14619
14897
  title,
14620
14898
  version,
14899
+ edition,
14621
14900
  appProps,
14622
14901
  toolkitOptions,
14623
14902
  createApp,