@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.js CHANGED
@@ -1810,6 +1810,7 @@ var runSigilApp = ({
1810
1810
  logger: upstreamLogger,
1811
1811
  title,
1812
1812
  version: version2,
1813
+ edition,
1813
1814
  appProps,
1814
1815
  toolkitOptions,
1815
1816
  createApp: createApp2,
@@ -1868,10 +1869,10 @@ var runSigilApp = ({
1868
1869
  logger.info(`${title} ready to start listening`);
1869
1870
  }
1870
1871
  });
1871
- let api = null;
1872
+ let api2 = null;
1872
1873
  const apiListeners = /* @__PURE__ */ new Set();
1873
1874
  const setAppApi = (value) => {
1874
- api = value;
1875
+ api2 = value;
1875
1876
  for (const listener of apiListeners) {
1876
1877
  listener(value);
1877
1878
  }
@@ -1904,6 +1905,7 @@ var runSigilApp = ({
1904
1905
  createApp2({
1905
1906
  title,
1906
1907
  version: version2,
1908
+ edition,
1907
1909
  toolkit,
1908
1910
  logger,
1909
1911
  logEventEmitter,
@@ -1923,8 +1925,8 @@ var runSigilApp = ({
1923
1925
  if (event === "apiChange") {
1924
1926
  const apiListener = listener;
1925
1927
  apiListeners.add(apiListener);
1926
- if (api) {
1927
- apiListener(api);
1928
+ if (api2) {
1929
+ apiListener(api2);
1928
1930
  }
1929
1931
  return;
1930
1932
  }
@@ -2137,7 +2139,7 @@ var AppListenerManager = ({
2137
2139
  };
2138
2140
 
2139
2141
  // src/app.tsx
2140
- var import_react9 = require("react");
2142
+ var import_react10 = require("react");
2141
2143
 
2142
2144
  // src/components/backend/index.ts
2143
2145
  var import_react_toolkit3 = require("@arcanejs/react-toolkit");
@@ -6189,8 +6191,7 @@ var NEVER = INVALID;
6189
6191
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js
6190
6192
  var zod_default = external_exports;
6191
6193
 
6192
- // ../../packages/sigil/dist/chunk-H4U4Z4GM.js
6193
- var import_react4 = require("react");
6194
+ // ../../packages/sigil/dist/chunk-WYUGJOEB.js
6194
6195
  var SIGIL_COLOR = external_exports.enum([
6195
6196
  "purple",
6196
6197
  "blue",
@@ -6285,12 +6286,18 @@ var OUTPUT_CONFIG = zod_default.object({
6285
6286
  var TOOLBOX_CONFIG = zod_default.object({
6286
6287
  inputs: zod_default.record(zod_default.string(), INPUT_CONFIG),
6287
6288
  generators: zod_default.record(zod_default.string(), GENERATOR_CONFIG),
6288
- outputs: zod_default.record(zod_default.string(), OUTPUT_CONFIG)
6289
+ outputs: zod_default.record(zod_default.string(), OUTPUT_CONFIG),
6290
+ /**
6291
+ * Hash of the license the user has agreed to.
6292
+ */
6293
+ agreedToLicense: zod_default.string().optional(),
6294
+ checkForUpdates: zod_default.boolean().optional().default(true)
6289
6295
  });
6290
6296
  var DEFAULT_CONFIG = {
6291
6297
  inputs: {},
6292
6298
  generators: {},
6293
- outputs: {}
6299
+ outputs: {},
6300
+ checkForUpdates: true
6294
6301
  };
6295
6302
  var isPlaying = (state) => state.state === "playing" || state.state === "lagging";
6296
6303
  var isStopped = (state) => state.state === "stopped";
@@ -6306,9 +6313,11 @@ var DEFAULT_PROPS2 = {
6306
6313
  state: {
6307
6314
  inputs: {},
6308
6315
  outputs: {},
6309
- generators: {}
6316
+ generators: {},
6317
+ updates: null
6310
6318
  },
6311
- handlers: { children: {} }
6319
+ handlers: { children: {} },
6320
+ license: ""
6312
6321
  };
6313
6322
  var ToolboxRoot = class extends import_base2.Base {
6314
6323
  /** @hidden */
@@ -6336,7 +6345,8 @@ var ToolboxRoot = class extends import_base2.Base {
6336
6345
  key: idMap.getId(this),
6337
6346
  config: this.props.config,
6338
6347
  state: this.props.state,
6339
- handlers: this.props.handlers
6348
+ handlers: this.props.handlers,
6349
+ license: this.props.license
6340
6350
  };
6341
6351
  }
6342
6352
  /** @hidden */
@@ -6365,9 +6375,53 @@ var ToolboxRoot = class extends import_base2.Base {
6365
6375
  };
6366
6376
  };
6367
6377
 
6378
+ // src/components/backend/license-gate.ts
6379
+ var import_base3 = require("@arcanejs/toolkit/components/base");
6380
+ var DEFAULT_PROPS3 = {
6381
+ license: "",
6382
+ hash: ""
6383
+ };
6384
+ var LicenseGate = class extends import_base3.Base {
6385
+ /** @hidden */
6386
+ events = new import_base3.EventEmitter();
6387
+ constructor(props) {
6388
+ super(DEFAULT_PROPS3, props, {
6389
+ onPropsUpdated: (oldProps) => this.events.processPropChanges(
6390
+ {
6391
+ onAcceptLicense: "acceptLicense"
6392
+ },
6393
+ oldProps,
6394
+ this.props
6395
+ )
6396
+ });
6397
+ this.triggerInitialPropsUpdate();
6398
+ }
6399
+ addListener = this.events.addListener;
6400
+ removeListener = this.events.removeListener;
6401
+ /** @hidden */
6402
+ getProtoInfo(idMap) {
6403
+ return {
6404
+ namespace: "timecode-toolbox",
6405
+ component: "license-gate",
6406
+ key: idMap.getId(this),
6407
+ license: this.props.license,
6408
+ hash: this.props.hash
6409
+ };
6410
+ }
6411
+ /** @hidden */
6412
+ handleMessage = (message) => {
6413
+ if (isTimecodeToolboxComponentMessage(message, "license-gate")) {
6414
+ if (message.action === "accept-license") {
6415
+ this.events.emit("acceptLicense", message.hash);
6416
+ }
6417
+ }
6418
+ };
6419
+ };
6420
+
6368
6421
  // src/components/backend/index.ts
6369
6422
  var C = (0, import_react_toolkit3.prepareComponents)("timecode-toolbox", {
6370
- ToolboxRoot
6423
+ ToolboxRoot,
6424
+ LicenseGate
6371
6425
  });
6372
6426
 
6373
6427
  // src/config.ts
@@ -6432,7 +6486,7 @@ var patchJson = (old, diff) => {
6432
6486
 
6433
6487
  // src/inputs/artnet.tsx
6434
6488
  var import_data3 = require("@arcanejs/react-toolkit/data");
6435
- var import_react5 = require("react");
6489
+ var import_react4 = require("react");
6436
6490
 
6437
6491
  // ../../packages/artnet/dist/chunk-J2HDMITA.js
6438
6492
  var ARTNET_PORT = 6454;
@@ -6762,12 +6816,12 @@ var ArtnetInputConnection = ({
6762
6816
  setState
6763
6817
  }) => {
6764
6818
  const log = useLogger();
6765
- const [artnetInstance, setArtnetInstance] = (0, import_react5.useState)(null);
6766
- const delayRef = (0, import_react5.useRef)(delayMs ?? 0);
6767
- (0, import_react5.useEffect)(() => {
6819
+ const [artnetInstance, setArtnetInstance] = (0, import_react4.useState)(null);
6820
+ const delayRef = (0, import_react4.useRef)(delayMs ?? 0);
6821
+ (0, import_react4.useEffect)(() => {
6768
6822
  delayRef.current = delayMs ?? 0;
6769
6823
  }, [delayMs]);
6770
- const setConnection = (0, import_react5.useCallback)(
6824
+ const setConnection = (0, import_react4.useCallback)(
6771
6825
  (state) => setState((current) => ({
6772
6826
  ...current,
6773
6827
  inputs: {
@@ -6777,7 +6831,7 @@ var ArtnetInputConnection = ({
6777
6831
  })),
6778
6832
  [setState, uuid]
6779
6833
  );
6780
- (0, import_react5.useEffect)(() => {
6834
+ (0, import_react4.useEffect)(() => {
6781
6835
  const connectionConfig = {
6782
6836
  timecode: {
6783
6837
  name: null,
@@ -6830,7 +6884,7 @@ var ArtnetInputConnection = ({
6830
6884
  }
6831
6885
  };
6832
6886
  }, [setConnection, uuid, iface, port, log]);
6833
- (0, import_react5.useEffect)(() => {
6887
+ (0, import_react4.useEffect)(() => {
6834
6888
  let lastTimecode = null;
6835
6889
  let lastUsedTimecode = lastTimecode;
6836
6890
  let timecode = null;
@@ -6919,7 +6973,7 @@ var ArtnetInputConnection = ({
6919
6973
  artnetInstance?.removeListener("timecode", onTimecode);
6920
6974
  };
6921
6975
  }, [artnetInstance, log, iface, name, setConnection]);
6922
- (0, import_react5.useEffect)(() => {
6976
+ (0, import_react4.useEffect)(() => {
6923
6977
  return () => {
6924
6978
  setState((current) => {
6925
6979
  const { [uuid]: _, ...rest } = current.inputs;
@@ -6954,7 +7008,7 @@ var ArtnetInputConnections = (props) => {
6954
7008
 
6955
7009
  // src/inputs/tcnet.tsx
6956
7010
  var import_data4 = require("@arcanejs/react-toolkit/data");
6957
- var import_react6 = require("react");
7011
+ var import_react5 = require("react");
6958
7012
 
6959
7013
  // ../../packages/tcnet/dist/chunk-VXAKTGOW.js
6960
7014
  var __create2 = Object.create;
@@ -13834,14 +13888,14 @@ var TcnetInputConnection = ({
13834
13888
  setState
13835
13889
  }) => {
13836
13890
  const logger = useLogger();
13837
- const appInformation = (0, import_react6.useContext)(AppInformationContext);
13838
- const nodeRef = (0, import_react6.useRef)(null);
13839
- const isMountedRef = (0, import_react6.useRef)(true);
13840
- const delayRef = (0, import_react6.useRef)(delayMs ?? 0);
13841
- (0, import_react6.useEffect)(() => {
13891
+ const appInformation = (0, import_react5.useContext)(AppInformationContext);
13892
+ const nodeRef = (0, import_react5.useRef)(null);
13893
+ const isMountedRef = (0, import_react5.useRef)(true);
13894
+ const delayRef = (0, import_react5.useRef)(delayMs ?? 0);
13895
+ (0, import_react5.useEffect)(() => {
13842
13896
  delayRef.current = delayMs ?? 0;
13843
13897
  }, [delayMs]);
13844
- const setConnection = (0, import_react6.useCallback)(
13898
+ const setConnection = (0, import_react5.useCallback)(
13845
13899
  (state) => setState((current) => ({
13846
13900
  ...current,
13847
13901
  inputs: {
@@ -13851,7 +13905,7 @@ var TcnetInputConnection = ({
13851
13905
  })),
13852
13906
  [setState, uuid]
13853
13907
  );
13854
- const updateState = (0, import_react6.useMemo)(() => {
13908
+ const updateState = (0, import_react5.useMemo)(() => {
13855
13909
  return (connections, nodes, timecodeGroup) => {
13856
13910
  if (!isMountedRef.current) {
13857
13911
  return;
@@ -13878,7 +13932,7 @@ var TcnetInputConnection = ({
13878
13932
  });
13879
13933
  };
13880
13934
  }, [setConnection]);
13881
- (0, import_react6.useEffect)(() => {
13935
+ (0, import_react5.useEffect)(() => {
13882
13936
  const node = createTCNetNode({
13883
13937
  logger,
13884
13938
  networkInterface: iface,
@@ -13972,7 +14026,7 @@ var TcnetInputConnection = ({
13972
14026
  await nodeRef.current.destroy();
13973
14027
  }
13974
14028
  });
13975
- (0, import_react6.useEffect)(() => {
14029
+ (0, import_react5.useEffect)(() => {
13976
14030
  return () => {
13977
14031
  isMountedRef.current = false;
13978
14032
  setState((current) => {
@@ -14017,7 +14071,7 @@ var InputConnections = (props) => {
14017
14071
 
14018
14072
  // src/outputs/artnet.tsx
14019
14073
  var import_data5 = require("@arcanejs/react-toolkit/data");
14020
- var import_react7 = require("react");
14074
+ var import_react6 = require("react");
14021
14075
 
14022
14076
  // src/util.ts
14023
14077
  var getTimecodeInstance = (state, id) => {
@@ -14062,8 +14116,8 @@ var ArtnetOutputConnection = ({
14062
14116
  state
14063
14117
  }) => {
14064
14118
  const log = useLogger();
14065
- const [artnetInstance, setArtnetInstance] = (0, import_react7.useState)(null);
14066
- const setConnection = (0, import_react7.useCallback)(
14119
+ const [artnetInstance, setArtnetInstance] = (0, import_react6.useState)(null);
14120
+ const setConnection = (0, import_react6.useCallback)(
14067
14121
  (state2) => setState((current) => ({
14068
14122
  ...current,
14069
14123
  outputs: {
@@ -14073,7 +14127,7 @@ var ArtnetOutputConnection = ({
14073
14127
  })),
14074
14128
  [setState, uuid]
14075
14129
  );
14076
- (0, import_react7.useEffect)(() => {
14130
+ (0, import_react6.useEffect)(() => {
14077
14131
  let artnet = null;
14078
14132
  setConnection({ status: "connecting" });
14079
14133
  const created = createArtnet({
@@ -14110,7 +14164,7 @@ var ArtnetOutputConnection = ({
14110
14164
  }
14111
14165
  };
14112
14166
  }, [setConnection, uuid, target, log]);
14113
- (0, import_react7.useEffect)(() => {
14167
+ (0, import_react6.useEffect)(() => {
14114
14168
  return () => {
14115
14169
  setState((current) => {
14116
14170
  const { [uuid]: _, ...rest } = current.outputs;
@@ -14121,15 +14175,15 @@ var ArtnetOutputConnection = ({
14121
14175
  });
14122
14176
  };
14123
14177
  }, [setState, uuid]);
14124
- const tcInstance = (0, import_react7.useMemo)(
14178
+ const tcInstance = (0, import_react6.useMemo)(
14125
14179
  () => config.link && getTimecodeInstance(state, config.link),
14126
14180
  [state, config.link]
14127
14181
  );
14128
- const timecodeState = (0, import_react7.useMemo)(
14182
+ const timecodeState = (0, import_react6.useMemo)(
14129
14183
  () => tcInstance?.state ? adjustTimecodeForDelay(tcInstance.state, config.delayMs ?? 0) : null,
14130
14184
  [tcInstance?.state, config.delayMs]
14131
14185
  );
14132
- (0, import_react7.useEffect)(() => {
14186
+ (0, import_react6.useEffect)(() => {
14133
14187
  if (!artnetInstance) {
14134
14188
  return;
14135
14189
  }
@@ -14175,7 +14229,7 @@ var OutputConnections = (props) => {
14175
14229
  };
14176
14230
 
14177
14231
  // src/generators/clock.tsx
14178
- var import_react8 = require("react");
14232
+ var import_react7 = require("react");
14179
14233
  var import_data6 = require("@arcanejs/react-toolkit/data");
14180
14234
 
14181
14235
  // src/tree.ts
@@ -14289,13 +14343,13 @@ var ClockGenerator = ({
14289
14343
  setState,
14290
14344
  setHandlers
14291
14345
  }) => {
14292
- const id = (0, import_react8.useMemo)(() => ["generator", uuid], [uuid]);
14293
- const [state, setLocalState] = (0, import_react8.useState)({
14346
+ const id = (0, import_react7.useMemo)(() => ["generator", uuid], [uuid]);
14347
+ const [state, setLocalState] = (0, import_react7.useState)({
14294
14348
  state: "stopped",
14295
14349
  positionMillis: 0
14296
14350
  });
14297
14351
  const { speed } = generator;
14298
- const play = (0, import_react8.useCallback)(() => {
14352
+ const play = (0, import_react7.useCallback)(() => {
14299
14353
  setLocalState((current) => {
14300
14354
  if (isPlaying(current)) {
14301
14355
  return current;
@@ -14309,7 +14363,7 @@ var ClockGenerator = ({
14309
14363
  };
14310
14364
  });
14311
14365
  }, [speed]);
14312
- const pause = (0, import_react8.useCallback)(() => {
14366
+ const pause = (0, import_react7.useCallback)(() => {
14313
14367
  setLocalState((current) => {
14314
14368
  if (!isPlaying(current)) {
14315
14369
  return current;
@@ -14321,7 +14375,7 @@ var ClockGenerator = ({
14321
14375
  };
14322
14376
  });
14323
14377
  }, [speed]);
14324
- const seekRelative = (0, import_react8.useCallback)(
14378
+ const seekRelative = (0, import_react7.useCallback)(
14325
14379
  (deltaMillis) => {
14326
14380
  setLocalState((current) => {
14327
14381
  if (current.state === "none") {
@@ -14346,7 +14400,7 @@ var ClockGenerator = ({
14346
14400
  },
14347
14401
  [speed]
14348
14402
  );
14349
- const beginning = (0, import_react8.useCallback)(() => {
14403
+ const beginning = (0, import_react7.useCallback)(() => {
14350
14404
  setLocalState((current) => {
14351
14405
  if (current.state === "none") {
14352
14406
  return current;
@@ -14365,7 +14419,7 @@ var ClockGenerator = ({
14365
14419
  }
14366
14420
  });
14367
14421
  }, []);
14368
- (0, import_react8.useEffect)(() => {
14422
+ (0, import_react7.useEffect)(() => {
14369
14423
  setLocalState((current) => {
14370
14424
  if (current.state === "none" || current.state === "stopped") {
14371
14425
  return current;
@@ -14380,12 +14434,12 @@ var ClockGenerator = ({
14380
14434
  };
14381
14435
  });
14382
14436
  }, [speed]);
14383
- (0, import_react8.useEffect)(() => {
14437
+ (0, import_react7.useEffect)(() => {
14384
14438
  setHandlers(
14385
14439
  (current) => updateTreeState(current, id, { play, pause, seekRelative, beginning })
14386
14440
  );
14387
14441
  }, [setHandlers, id, play, pause, seekRelative, beginning]);
14388
- (0, import_react8.useEffect)(
14442
+ (0, import_react7.useEffect)(
14389
14443
  () => setState((current) => ({
14390
14444
  ...current,
14391
14445
  generators: {
@@ -14406,7 +14460,7 @@ var ClockGenerator = ({
14406
14460
  })),
14407
14461
  [setState, uuid, state, config.name]
14408
14462
  );
14409
- (0, import_react8.useEffect)(
14463
+ (0, import_react7.useEffect)(
14410
14464
  () => () => {
14411
14465
  setState((current) => {
14412
14466
  const { [uuid]: _, ...rest } = current.generators;
@@ -14447,11 +14501,179 @@ var Generators = (props) => {
14447
14501
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ClockGenerators, { ...props }) });
14448
14502
  };
14449
14503
 
14504
+ // src/license.ts
14505
+ var import_node_crypto = require("crypto");
14506
+ var import_promises = require("fs/promises");
14507
+ var import_react8 = require("react");
14508
+ var getLicense = async () => {
14509
+ const licenseText = await (0, import_promises.readFile)(require.resolve("../LICENSE"), "utf-8");
14510
+ const hash = (0, import_node_crypto.createHash)("sha256").update(licenseText).digest("hex");
14511
+ return { text: licenseText, hash };
14512
+ };
14513
+ var useLicense = () => {
14514
+ const [license, setLicense] = (0, import_react8.useState)(null);
14515
+ (0, import_react8.useEffect)(() => {
14516
+ getLicense().then(setLicense);
14517
+ }, []);
14518
+ return license;
14519
+ };
14520
+
14521
+ // src/updates.tsx
14522
+ var import_react9 = require("react");
14523
+
14524
+ // ../../packages/apis/dist/index.js
14525
+ var APP_PLATFORM = zod_default.enum(["windows", "macos", "linux"]);
14526
+ var APP_ARCHITECTURE = zod_default.enum(["x64", "arm64"]);
14527
+ var APP_EDITION = zod_default.enum(["desktop", "cli"]);
14528
+ var CHECK_FOR_UPDATES_REQUEST = zod_default.object({
14529
+ app: zod_default.string(),
14530
+ edition: APP_EDITION,
14531
+ platform: APP_PLATFORM,
14532
+ architecture: APP_ARCHITECTURE,
14533
+ currentVersion: zod_default.string()
14534
+ });
14535
+ var CHECK_FOR_UPDATES_VERSION = zod_default.object({
14536
+ version: zod_default.string(),
14537
+ releaseNotes: zod_default.string()
14538
+ });
14539
+ var CHECK_FOR_UPDATES_RESPONSE = zod_default.object({
14540
+ downloadUrl: zod_default.string().optional(),
14541
+ latestVersion: zod_default.string(),
14542
+ newVersions: zod_default.array(CHECK_FOR_UPDATES_VERSION).optional()
14543
+ });
14544
+ var ApiError = class extends Error {
14545
+ constructor(message, response) {
14546
+ super(message);
14547
+ this.response = response;
14548
+ this.name = "ApiError";
14549
+ }
14550
+ };
14551
+ var api = (baseUrl) => {
14552
+ const checkForUpdates = async (request) => {
14553
+ const response = await fetch(new URL("/api/v1/updates", baseUrl), {
14554
+ method: "POST",
14555
+ headers: { "Content-Type": "application/json" },
14556
+ body: JSON.stringify(request)
14557
+ });
14558
+ if (!response.ok) {
14559
+ throw new ApiError(
14560
+ `Failed to check for updates: ${response.statusText} - ${await response.text()}`,
14561
+ response
14562
+ );
14563
+ }
14564
+ const responseData = await response.json();
14565
+ return CHECK_FOR_UPDATES_RESPONSE.parse(responseData);
14566
+ };
14567
+ return {
14568
+ checkForUpdates
14569
+ };
14570
+ };
14571
+
14572
+ // src/updates.tsx
14573
+ var getAppPlatform = () => {
14574
+ switch (process.platform) {
14575
+ case "win32":
14576
+ return "windows";
14577
+ case "darwin":
14578
+ return "macos";
14579
+ case "linux":
14580
+ return "linux";
14581
+ default:
14582
+ throw new Error(`Unsupported platform: ${process.platform}`);
14583
+ }
14584
+ };
14585
+ var getAppArchitecture = () => {
14586
+ switch (process.arch) {
14587
+ case "x64":
14588
+ return "x64";
14589
+ case "arm64":
14590
+ return "arm64";
14591
+ default:
14592
+ throw new Error(`Unsupported architecture: ${process.arch}`);
14593
+ }
14594
+ };
14595
+ var UpdateChecker = ({
14596
+ apiBaseUrl,
14597
+ version: version2,
14598
+ edition,
14599
+ setUpdateState
14600
+ }) => {
14601
+ const a = (0, import_react9.useMemo)(() => api(apiBaseUrl), [apiBaseUrl]);
14602
+ const logger = useLogger();
14603
+ const checkForUpdates = (0, import_react9.useCallback)(() => {
14604
+ const lastCheckedMillis = Date.now();
14605
+ setUpdateState({ type: "loading" });
14606
+ a.checkForUpdates({
14607
+ app: "timecode-toolbox",
14608
+ edition,
14609
+ platform: getAppPlatform(),
14610
+ architecture: getAppArchitecture(),
14611
+ currentVersion: version2
14612
+ }).then((response) => {
14613
+ if (!response.newVersions || response.newVersions.length === 0) {
14614
+ setUpdateState({ type: "up-to-date", lastCheckedMillis });
14615
+ logger.info("No updates available");
14616
+ return;
14617
+ }
14618
+ setUpdateState({
14619
+ type: "updates-available",
14620
+ lastCheckedMillis,
14621
+ response
14622
+ });
14623
+ logger.info(
14624
+ `Update available: ${response.latestVersion} - Download at ${response.downloadUrl}`
14625
+ );
14626
+ }).catch((error) => {
14627
+ const err = new Error("Failed to check for updates");
14628
+ err.cause = error instanceof Error ? error : new Error(String(error));
14629
+ setUpdateState({
14630
+ lastCheckedMillis,
14631
+ type: "error",
14632
+ error: String(err)
14633
+ });
14634
+ logger.error(err);
14635
+ });
14636
+ }, [a, setUpdateState, edition, logger, version2]);
14637
+ (0, import_react9.useEffect)(() => {
14638
+ checkForUpdates();
14639
+ const interval = setInterval(checkForUpdates, 1e3 * 60 * 60);
14640
+ return () => clearInterval(interval);
14641
+ }, [checkForUpdates]);
14642
+ (0, import_react9.useEffect)(() => {
14643
+ return () => {
14644
+ setUpdateState(null);
14645
+ };
14646
+ }, [setUpdateState]);
14647
+ return null;
14648
+ };
14649
+
14650
+ // src/env.ts
14651
+ var getEnv = (logger) => {
14652
+ const PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : {
14653
+ from: 4100,
14654
+ to: 4200
14655
+ };
14656
+ let API_BASE_URL;
14657
+ try {
14658
+ API_BASE_URL = process.env.API_BASE_URL ? new URL(process.env.API_BASE_URL) : new URL("https://arcanewizards.com");
14659
+ } catch (error) {
14660
+ const err = new Error(`Invalid API_BASE_URL: ${process.env.API_BASE_URL}`);
14661
+ err.cause = error instanceof Error ? error : new Error(String(error));
14662
+ logger.error(err);
14663
+ throw err;
14664
+ }
14665
+ return {
14666
+ PORT,
14667
+ API_BASE_URL
14668
+ };
14669
+ };
14670
+
14450
14671
  // src/app.tsx
14451
14672
  var import_jsx_runtime9 = require("react/jsx-runtime");
14452
14673
  var App = ({
14453
14674
  title,
14454
14675
  version: version2,
14676
+ edition,
14455
14677
  toolkit,
14456
14678
  dataDirectory,
14457
14679
  logger,
@@ -14459,8 +14681,9 @@ var App = ({
14459
14681
  setWindowUrl,
14460
14682
  shutdownContext
14461
14683
  }) => {
14684
+ const env = (0, import_react10.useMemo)(() => getEnv(logger), [logger]);
14462
14685
  const { data, error, updateData, resetData } = (0, import_data7.useDataFileContext)(ToolboxConfigData);
14463
- (0, import_react9.useEffect)(() => {
14686
+ (0, import_react10.useEffect)(() => {
14464
14687
  if (error) {
14465
14688
  logger.warn("Resetting config to application default");
14466
14689
  resetData();
@@ -14469,13 +14692,20 @@ var App = ({
14469
14692
  const onUpdateConfig = (diff) => {
14470
14693
  updateData((prev) => patchJson(prev, diff) ?? DEFAULT_CONFIG);
14471
14694
  };
14472
- const [state, setState] = (0, import_react9.useState)({
14695
+ const [state, setState] = (0, import_react10.useState)({
14473
14696
  inputs: {},
14474
14697
  outputs: {},
14475
- generators: {}
14698
+ generators: {},
14699
+ updates: null
14476
14700
  });
14477
- const [handlers, setHandlers] = (0, import_react9.useState)({ children: {} });
14478
- const availableHandlers = (0, import_react9.useMemo)(
14701
+ const setUpdateState = (0, import_react10.useCallback)((updates) => {
14702
+ setState((prev) => ({
14703
+ ...prev,
14704
+ updates
14705
+ }));
14706
+ }, []);
14707
+ const [handlers, setHandlers] = (0, import_react10.useState)({ children: {} });
14708
+ const availableHandlers = (0, import_react10.useMemo)(
14479
14709
  () => mapTree(
14480
14710
  handlers,
14481
14711
  (node) => Object.fromEntries(
@@ -14484,7 +14714,7 @@ var App = ({
14484
14714
  ),
14485
14715
  [handlers]
14486
14716
  );
14487
- const callHandler = (0, import_react9.useCallback)(
14717
+ const callHandler = (0, import_react10.useCallback)(
14488
14718
  async (call) => {
14489
14719
  const handlerFunc = getTreeValue(handlers, call.path)?.[call.handler];
14490
14720
  if (handlerFunc) {
@@ -14496,6 +14726,54 @@ var App = ({
14496
14726
  },
14497
14727
  [handlers]
14498
14728
  );
14729
+ const license = useLicense();
14730
+ const appListenerConfig = (0, import_react10.useMemo)(
14731
+ () => ({
14732
+ default: {
14733
+ port: env.PORT
14734
+ }
14735
+ }),
14736
+ [env.PORT]
14737
+ );
14738
+ if (!license) {
14739
+ return;
14740
+ }
14741
+ const children = data.agreedToLicense === license.hash ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
14742
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14743
+ C.ToolboxRoot,
14744
+ {
14745
+ config: data,
14746
+ state,
14747
+ handlers: availableHandlers,
14748
+ onUpdateConfig,
14749
+ onCallHandler: callHandler,
14750
+ license: license.text
14751
+ }
14752
+ ),
14753
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(InputConnections, { state, setState }),
14754
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14755
+ Generators,
14756
+ {
14757
+ state,
14758
+ setState,
14759
+ setHandlers
14760
+ }
14761
+ ),
14762
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(OutputConnections, { state, setState })
14763
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14764
+ C.LicenseGate,
14765
+ {
14766
+ license: license.text,
14767
+ hash: license.hash,
14768
+ onAcceptLicense: (agreedToLicense) => {
14769
+ logger.info(`License accepted: ${agreedToLicense}`);
14770
+ updateData((current) => ({
14771
+ ...current,
14772
+ agreedToLicense
14773
+ }));
14774
+ }
14775
+ }
14776
+ );
14499
14777
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
14500
14778
  AppShell,
14501
14779
  {
@@ -14506,32 +14784,22 @@ var App = ({
14506
14784
  logEventEmitter,
14507
14785
  shutdownContext,
14508
14786
  children: [
14509
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14510
- C.ToolboxRoot,
14787
+ children,
14788
+ data.checkForUpdates && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14789
+ UpdateChecker,
14511
14790
  {
14512
- config: data,
14513
- state,
14514
- handlers: availableHandlers,
14515
- onUpdateConfig,
14516
- onCallHandler: callHandler
14791
+ version: version2,
14792
+ edition,
14793
+ apiBaseUrl: env.API_BASE_URL,
14794
+ setUpdateState
14517
14795
  }
14518
14796
  ),
14519
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(InputConnections, { state, setState }),
14520
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Generators, { state, setState, setHandlers }),
14521
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(OutputConnections, { state, setState }),
14522
14797
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14523
14798
  AppListenerManager,
14524
14799
  {
14525
14800
  toolkit,
14526
14801
  setWindowUrl,
14527
- listenerConfig: {
14528
- default: {
14529
- port: {
14530
- from: 4100,
14531
- to: 4200
14532
- }
14533
- }
14534
- }
14802
+ listenerConfig: appListenerConfig
14535
14803
  }
14536
14804
  )
14537
14805
  ]
@@ -14549,7 +14817,7 @@ var createApp = (props) => {
14549
14817
  };
14550
14818
 
14551
14819
  // package.json
14552
- var version = "0.1.0";
14820
+ var version = "0.1.2";
14553
14821
 
14554
14822
  // src/urls.ts
14555
14823
  var urls_exports = {};
@@ -14594,11 +14862,13 @@ var runTimecodeToolboxServer = ({
14594
14862
  logger,
14595
14863
  appProps,
14596
14864
  toolkitOptions,
14597
- title
14865
+ title,
14866
+ edition
14598
14867
  }) => runSigilApp({
14599
14868
  logger,
14600
14869
  title,
14601
14870
  version,
14871
+ edition,
14602
14872
  appProps,
14603
14873
  toolkitOptions,
14604
14874
  createApp,