@arcanewizards/timecode-toolbox 0.1.0 → 0.1.1

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 (58) hide show
  1. package/LICENSE +21 -0
  2. package/dist/components/frontend/index.js +865 -272
  3. package/dist/components/frontend/index.mjs +855 -262
  4. package/dist/entrypoint.css +163 -53
  5. package/dist/entrypoint.js +1474 -493
  6. package/dist/entrypoint.js.map +4 -4
  7. package/dist/frontend.js +1474 -493
  8. package/dist/frontend.js.map +4 -4
  9. package/dist/index.d.mts +3 -1
  10. package/dist/index.d.ts +3 -1
  11. package/dist/index.js +308 -37
  12. package/dist/index.mjs +329 -49
  13. package/dist/start.d.mts +1 -2
  14. package/dist/start.d.ts +1 -2
  15. package/dist/start.js +311 -38
  16. package/dist/start.mjs +332 -50
  17. package/package.json +12 -6
  18. package/.turbo/turbo-build.log +0 -58
  19. package/.turbo/turbo-lint.log +0 -4
  20. package/CHANGELOG.md +0 -40
  21. package/eslint.config.mjs +0 -49
  22. package/src/app.tsx +0 -147
  23. package/src/components/backend/index.ts +0 -6
  24. package/src/components/backend/toolbox-root.ts +0 -119
  25. package/src/components/frontend/constants.ts +0 -81
  26. package/src/components/frontend/entrypoint.ts +0 -12
  27. package/src/components/frontend/frontend.css +0 -108
  28. package/src/components/frontend/index.tsx +0 -46
  29. package/src/components/frontend/toolbox/content.tsx +0 -45
  30. package/src/components/frontend/toolbox/context.tsx +0 -63
  31. package/src/components/frontend/toolbox/core/size-aware-div.tsx +0 -51
  32. package/src/components/frontend/toolbox/core/timecode-display.tsx +0 -592
  33. package/src/components/frontend/toolbox/generators.tsx +0 -318
  34. package/src/components/frontend/toolbox/inputs.tsx +0 -484
  35. package/src/components/frontend/toolbox/outputs.tsx +0 -581
  36. package/src/components/frontend/toolbox/preferences.ts +0 -25
  37. package/src/components/frontend/toolbox/root.tsx +0 -335
  38. package/src/components/frontend/toolbox/settings.tsx +0 -54
  39. package/src/components/frontend/toolbox/types.ts +0 -28
  40. package/src/components/frontend/toolbox/util.tsx +0 -61
  41. package/src/components/proto.ts +0 -420
  42. package/src/config.ts +0 -7
  43. package/src/generators/clock.tsx +0 -206
  44. package/src/generators/index.tsx +0 -15
  45. package/src/index.ts +0 -38
  46. package/src/inputs/artnet.tsx +0 -305
  47. package/src/inputs/index.tsx +0 -13
  48. package/src/inputs/tcnet.tsx +0 -272
  49. package/src/outputs/artnet.tsx +0 -170
  50. package/src/outputs/index.tsx +0 -11
  51. package/src/start.ts +0 -47
  52. package/src/tree.ts +0 -133
  53. package/src/types.ts +0 -12
  54. package/src/urls.ts +0 -49
  55. package/src/util.ts +0 -82
  56. package/tailwind.config.cjs +0 -7
  57. package/tsconfig.json +0 -10
  58. 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_react11 = require("react");
2141
2144
 
2142
2145
  // src/components/backend/index.ts
2143
2146
  var import_react_toolkit3 = require("@arcanejs/react-toolkit");
@@ -6285,12 +6288,18 @@ var OUTPUT_CONFIG = zod_default.object({
6285
6288
  var TOOLBOX_CONFIG = zod_default.object({
6286
6289
  inputs: zod_default.record(zod_default.string(), INPUT_CONFIG),
6287
6290
  generators: zod_default.record(zod_default.string(), GENERATOR_CONFIG),
6288
- outputs: zod_default.record(zod_default.string(), OUTPUT_CONFIG)
6291
+ outputs: zod_default.record(zod_default.string(), OUTPUT_CONFIG),
6292
+ /**
6293
+ * Hash of the license the user has agreed to.
6294
+ */
6295
+ agreedToLicense: zod_default.string().optional(),
6296
+ checkForUpdates: zod_default.boolean().optional().default(true)
6289
6297
  });
6290
6298
  var DEFAULT_CONFIG = {
6291
6299
  inputs: {},
6292
6300
  generators: {},
6293
- outputs: {}
6301
+ outputs: {},
6302
+ checkForUpdates: true
6294
6303
  };
6295
6304
  var isPlaying = (state) => state.state === "playing" || state.state === "lagging";
6296
6305
  var isStopped = (state) => state.state === "stopped";
@@ -6306,9 +6315,11 @@ var DEFAULT_PROPS2 = {
6306
6315
  state: {
6307
6316
  inputs: {},
6308
6317
  outputs: {},
6309
- generators: {}
6318
+ generators: {},
6319
+ updates: null
6310
6320
  },
6311
- handlers: { children: {} }
6321
+ handlers: { children: {} },
6322
+ license: ""
6312
6323
  };
6313
6324
  var ToolboxRoot = class extends import_base2.Base {
6314
6325
  /** @hidden */
@@ -6336,7 +6347,8 @@ var ToolboxRoot = class extends import_base2.Base {
6336
6347
  key: idMap.getId(this),
6337
6348
  config: this.props.config,
6338
6349
  state: this.props.state,
6339
- handlers: this.props.handlers
6350
+ handlers: this.props.handlers,
6351
+ license: this.props.license
6340
6352
  };
6341
6353
  }
6342
6354
  /** @hidden */
@@ -6365,9 +6377,53 @@ var ToolboxRoot = class extends import_base2.Base {
6365
6377
  };
6366
6378
  };
6367
6379
 
6380
+ // src/components/backend/license-gate.ts
6381
+ var import_base3 = require("@arcanejs/toolkit/components/base");
6382
+ var DEFAULT_PROPS3 = {
6383
+ license: "",
6384
+ hash: ""
6385
+ };
6386
+ var LicenseGate = class extends import_base3.Base {
6387
+ /** @hidden */
6388
+ events = new import_base3.EventEmitter();
6389
+ constructor(props) {
6390
+ super(DEFAULT_PROPS3, props, {
6391
+ onPropsUpdated: (oldProps) => this.events.processPropChanges(
6392
+ {
6393
+ onAcceptLicense: "acceptLicense"
6394
+ },
6395
+ oldProps,
6396
+ this.props
6397
+ )
6398
+ });
6399
+ this.triggerInitialPropsUpdate();
6400
+ }
6401
+ addListener = this.events.addListener;
6402
+ removeListener = this.events.removeListener;
6403
+ /** @hidden */
6404
+ getProtoInfo(idMap) {
6405
+ return {
6406
+ namespace: "timecode-toolbox",
6407
+ component: "license-gate",
6408
+ key: idMap.getId(this),
6409
+ license: this.props.license,
6410
+ hash: this.props.hash
6411
+ };
6412
+ }
6413
+ /** @hidden */
6414
+ handleMessage = (message) => {
6415
+ if (isTimecodeToolboxComponentMessage(message, "license-gate")) {
6416
+ if (message.action === "accept-license") {
6417
+ this.events.emit("acceptLicense", message.hash);
6418
+ }
6419
+ }
6420
+ };
6421
+ };
6422
+
6368
6423
  // src/components/backend/index.ts
6369
6424
  var C = (0, import_react_toolkit3.prepareComponents)("timecode-toolbox", {
6370
- ToolboxRoot
6425
+ ToolboxRoot,
6426
+ LicenseGate
6371
6427
  });
6372
6428
 
6373
6429
  // src/config.ts
@@ -14447,11 +14503,179 @@ var Generators = (props) => {
14447
14503
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ClockGenerators, { ...props }) });
14448
14504
  };
14449
14505
 
14506
+ // src/license.ts
14507
+ var import_node_crypto = require("crypto");
14508
+ var import_promises = require("fs/promises");
14509
+ var import_react9 = require("react");
14510
+ var getLicense = async () => {
14511
+ const licenseText = await (0, import_promises.readFile)(require.resolve("../LICENSE"), "utf-8");
14512
+ const hash = (0, import_node_crypto.createHash)("sha256").update(licenseText).digest("hex");
14513
+ return { text: licenseText, hash };
14514
+ };
14515
+ var useLicense = () => {
14516
+ const [license, setLicense] = (0, import_react9.useState)(null);
14517
+ (0, import_react9.useEffect)(() => {
14518
+ getLicense().then(setLicense);
14519
+ }, []);
14520
+ return license;
14521
+ };
14522
+
14523
+ // src/updates.tsx
14524
+ var import_react10 = require("react");
14525
+
14526
+ // ../../packages/apis/dist/index.js
14527
+ var APP_PLATFORM = zod_default.enum(["windows", "macos", "linux"]);
14528
+ var APP_ARCHITECTURE = zod_default.enum(["x64", "arm64"]);
14529
+ var APP_EDITION = zod_default.enum(["desktop", "cli"]);
14530
+ var CHECK_FOR_UPDATES_REQUEST = zod_default.object({
14531
+ app: zod_default.string(),
14532
+ edition: APP_EDITION,
14533
+ platform: APP_PLATFORM,
14534
+ architecture: APP_ARCHITECTURE,
14535
+ currentVersion: zod_default.string()
14536
+ });
14537
+ var CHECK_FOR_UPDATES_VERSION = zod_default.object({
14538
+ version: zod_default.string(),
14539
+ releaseNotes: zod_default.string()
14540
+ });
14541
+ var CHECK_FOR_UPDATES_RESPONSE = zod_default.object({
14542
+ downloadUrl: zod_default.string().optional(),
14543
+ latestVersion: zod_default.string(),
14544
+ newVersions: zod_default.array(CHECK_FOR_UPDATES_VERSION).optional()
14545
+ });
14546
+ var ApiError = class extends Error {
14547
+ constructor(message, response) {
14548
+ super(message);
14549
+ this.response = response;
14550
+ this.name = "ApiError";
14551
+ }
14552
+ };
14553
+ var api = (baseUrl) => {
14554
+ const checkForUpdates = async (request) => {
14555
+ const response = await fetch(new URL("/api/v1/updates", baseUrl), {
14556
+ method: "POST",
14557
+ headers: { "Content-Type": "application/json" },
14558
+ body: JSON.stringify(request)
14559
+ });
14560
+ if (!response.ok) {
14561
+ throw new ApiError(
14562
+ `Failed to check for updates: ${response.statusText} - ${await response.text()}`,
14563
+ response
14564
+ );
14565
+ }
14566
+ const responseData = await response.json();
14567
+ return CHECK_FOR_UPDATES_RESPONSE.parse(responseData);
14568
+ };
14569
+ return {
14570
+ checkForUpdates
14571
+ };
14572
+ };
14573
+
14574
+ // src/updates.tsx
14575
+ var getAppPlatform = () => {
14576
+ switch (process.platform) {
14577
+ case "win32":
14578
+ return "windows";
14579
+ case "darwin":
14580
+ return "macos";
14581
+ case "linux":
14582
+ return "linux";
14583
+ default:
14584
+ throw new Error(`Unsupported platform: ${process.platform}`);
14585
+ }
14586
+ };
14587
+ var getAppArchitecture = () => {
14588
+ switch (process.arch) {
14589
+ case "x64":
14590
+ return "x64";
14591
+ case "arm64":
14592
+ return "arm64";
14593
+ default:
14594
+ throw new Error(`Unsupported architecture: ${process.arch}`);
14595
+ }
14596
+ };
14597
+ var UpdateChecker = ({
14598
+ apiBaseUrl,
14599
+ version: version2,
14600
+ edition,
14601
+ setUpdateState
14602
+ }) => {
14603
+ const a = (0, import_react10.useMemo)(() => api(apiBaseUrl), [apiBaseUrl]);
14604
+ const logger2 = useLogger();
14605
+ const checkForUpdates = (0, import_react10.useCallback)(() => {
14606
+ const lastCheckedMillis = Date.now();
14607
+ setUpdateState({ type: "loading" });
14608
+ a.checkForUpdates({
14609
+ app: "timecode-toolbox",
14610
+ edition,
14611
+ platform: getAppPlatform(),
14612
+ architecture: getAppArchitecture(),
14613
+ currentVersion: version2
14614
+ }).then((response) => {
14615
+ if (!response.newVersions || response.newVersions.length === 0) {
14616
+ setUpdateState({ type: "up-to-date", lastCheckedMillis });
14617
+ logger2.info("No updates available");
14618
+ return;
14619
+ }
14620
+ setUpdateState({
14621
+ type: "updates-available",
14622
+ lastCheckedMillis,
14623
+ response
14624
+ });
14625
+ logger2.info(
14626
+ `Update available: ${response.latestVersion} - Download at ${response.downloadUrl}`
14627
+ );
14628
+ }).catch((error) => {
14629
+ const err = new Error("Failed to check for updates");
14630
+ err.cause = error instanceof Error ? error : new Error(String(error));
14631
+ setUpdateState({
14632
+ lastCheckedMillis,
14633
+ type: "error",
14634
+ error: String(err)
14635
+ });
14636
+ logger2.error(err);
14637
+ });
14638
+ }, [a, setUpdateState, edition, logger2, version2]);
14639
+ (0, import_react10.useEffect)(() => {
14640
+ checkForUpdates();
14641
+ const interval = setInterval(checkForUpdates, 1e3 * 60 * 60);
14642
+ return () => clearInterval(interval);
14643
+ }, [checkForUpdates]);
14644
+ (0, import_react10.useEffect)(() => {
14645
+ return () => {
14646
+ setUpdateState(null);
14647
+ };
14648
+ }, [setUpdateState]);
14649
+ return null;
14650
+ };
14651
+
14652
+ // src/env.ts
14653
+ var getEnv = (logger2) => {
14654
+ const PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : {
14655
+ from: 4100,
14656
+ to: 4200
14657
+ };
14658
+ let API_BASE_URL;
14659
+ try {
14660
+ API_BASE_URL = process.env.API_BASE_URL ? new URL(process.env.API_BASE_URL) : new URL("https://arcanewizards.com");
14661
+ } catch (error) {
14662
+ const err = new Error(`Invalid API_BASE_URL: ${process.env.API_BASE_URL}`);
14663
+ err.cause = error instanceof Error ? error : new Error(String(error));
14664
+ logger2.error(err);
14665
+ throw err;
14666
+ }
14667
+ return {
14668
+ PORT,
14669
+ API_BASE_URL
14670
+ };
14671
+ };
14672
+
14450
14673
  // src/app.tsx
14451
14674
  var import_jsx_runtime9 = require("react/jsx-runtime");
14452
14675
  var App = ({
14453
14676
  title,
14454
14677
  version: version2,
14678
+ edition,
14455
14679
  toolkit,
14456
14680
  dataDirectory,
14457
14681
  logger: logger2,
@@ -14459,8 +14683,9 @@ var App = ({
14459
14683
  setWindowUrl,
14460
14684
  shutdownContext
14461
14685
  }) => {
14686
+ const env = (0, import_react11.useMemo)(() => getEnv(logger2), [logger2]);
14462
14687
  const { data, error, updateData, resetData } = (0, import_data7.useDataFileContext)(ToolboxConfigData);
14463
- (0, import_react9.useEffect)(() => {
14688
+ (0, import_react11.useEffect)(() => {
14464
14689
  if (error) {
14465
14690
  logger2.warn("Resetting config to application default");
14466
14691
  resetData();
@@ -14469,13 +14694,20 @@ var App = ({
14469
14694
  const onUpdateConfig = (diff) => {
14470
14695
  updateData((prev) => patchJson(prev, diff) ?? DEFAULT_CONFIG);
14471
14696
  };
14472
- const [state, setState] = (0, import_react9.useState)({
14697
+ const [state, setState] = (0, import_react11.useState)({
14473
14698
  inputs: {},
14474
14699
  outputs: {},
14475
- generators: {}
14700
+ generators: {},
14701
+ updates: null
14476
14702
  });
14477
- const [handlers, setHandlers] = (0, import_react9.useState)({ children: {} });
14478
- const availableHandlers = (0, import_react9.useMemo)(
14703
+ const setUpdateState = (0, import_react11.useCallback)((updates) => {
14704
+ setState((prev) => ({
14705
+ ...prev,
14706
+ updates
14707
+ }));
14708
+ }, []);
14709
+ const [handlers, setHandlers] = (0, import_react11.useState)({ children: {} });
14710
+ const availableHandlers = (0, import_react11.useMemo)(
14479
14711
  () => mapTree(
14480
14712
  handlers,
14481
14713
  (node) => Object.fromEntries(
@@ -14484,7 +14716,7 @@ var App = ({
14484
14716
  ),
14485
14717
  [handlers]
14486
14718
  );
14487
- const callHandler = (0, import_react9.useCallback)(
14719
+ const callHandler = (0, import_react11.useCallback)(
14488
14720
  async (call) => {
14489
14721
  const handlerFunc = getTreeValue(handlers, call.path)?.[call.handler];
14490
14722
  if (handlerFunc) {
@@ -14496,6 +14728,54 @@ var App = ({
14496
14728
  },
14497
14729
  [handlers]
14498
14730
  );
14731
+ const license = useLicense();
14732
+ const appListenerConfig = (0, import_react11.useMemo)(
14733
+ () => ({
14734
+ default: {
14735
+ port: env.PORT
14736
+ }
14737
+ }),
14738
+ [env.PORT]
14739
+ );
14740
+ if (!license) {
14741
+ return;
14742
+ }
14743
+ const children = data.agreedToLicense === license.hash ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
14744
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14745
+ C.ToolboxRoot,
14746
+ {
14747
+ config: data,
14748
+ state,
14749
+ handlers: availableHandlers,
14750
+ onUpdateConfig,
14751
+ onCallHandler: callHandler,
14752
+ license: license.text
14753
+ }
14754
+ ),
14755
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(InputConnections, { state, setState }),
14756
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14757
+ Generators,
14758
+ {
14759
+ state,
14760
+ setState,
14761
+ setHandlers
14762
+ }
14763
+ ),
14764
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(OutputConnections, { state, setState })
14765
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14766
+ C.LicenseGate,
14767
+ {
14768
+ license: license.text,
14769
+ hash: license.hash,
14770
+ onAcceptLicense: (agreedToLicense) => {
14771
+ logger2.info(`License accepted: ${agreedToLicense}`);
14772
+ updateData((current) => ({
14773
+ ...current,
14774
+ agreedToLicense
14775
+ }));
14776
+ }
14777
+ }
14778
+ );
14499
14779
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
14500
14780
  AppShell,
14501
14781
  {
@@ -14506,32 +14786,22 @@ var App = ({
14506
14786
  logEventEmitter,
14507
14787
  shutdownContext,
14508
14788
  children: [
14509
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14510
- C.ToolboxRoot,
14789
+ children,
14790
+ data.checkForUpdates && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14791
+ UpdateChecker,
14511
14792
  {
14512
- config: data,
14513
- state,
14514
- handlers: availableHandlers,
14515
- onUpdateConfig,
14516
- onCallHandler: callHandler
14793
+ version: version2,
14794
+ edition,
14795
+ apiBaseUrl: env.API_BASE_URL,
14796
+ setUpdateState
14517
14797
  }
14518
14798
  ),
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
14799
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14523
14800
  AppListenerManager,
14524
14801
  {
14525
14802
  toolkit,
14526
14803
  setWindowUrl,
14527
- listenerConfig: {
14528
- default: {
14529
- port: {
14530
- from: 4100,
14531
- to: 4200
14532
- }
14533
- }
14534
- }
14804
+ listenerConfig: appListenerConfig
14535
14805
  }
14536
14806
  )
14537
14807
  ]
@@ -14549,18 +14819,20 @@ var createApp = (props) => {
14549
14819
  };
14550
14820
 
14551
14821
  // package.json
14552
- var version = "0.1.0";
14822
+ var version = "0.1.1";
14553
14823
 
14554
14824
  // src/index.ts
14555
14825
  var runTimecodeToolboxServer = ({
14556
14826
  logger: logger2,
14557
14827
  appProps,
14558
14828
  toolkitOptions,
14559
- title
14829
+ title,
14830
+ edition
14560
14831
  }) => runSigilApp({
14561
14832
  logger: logger2,
14562
14833
  title,
14563
14834
  version,
14835
+ edition,
14564
14836
  appProps,
14565
14837
  toolkitOptions,
14566
14838
  createApp,
@@ -14584,7 +14856,8 @@ var server = runTimecodeToolboxServer({
14584
14856
  toolkitOptions: {
14585
14857
  entrypointJsFile: import_path.default.join(import_path.default.dirname(__dirname), "dist/entrypoint.js")
14586
14858
  },
14587
- title: "Timecode Toolbox Server"
14859
+ title: "Timecode Toolbox Server",
14860
+ edition: "cli"
14588
14861
  });
14589
14862
  var shutdown = () => server.shutdown().catch((err) => {
14590
14863
  logger.error({ err }, "Error during shutdown");