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