@hitch42/cli 0.1.0-beta.3 → 0.1.0-beta.9

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 (2) hide show
  1. package/dist/hitch.js +34 -33
  2. package/package.json +2 -2
package/dist/hitch.js CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { registerHooks } from "node:module";
2
+ import { createRequire, registerHooks } from "node:module";
3
3
  import { access, chmod, mkdir, readFile, readdir, realpath, rm, stat, writeFile } from "node:fs/promises";
4
4
  import { basename, dirname, join, resolve } from "node:path";
5
5
  import { pathToFileURL } from "node:url";
6
6
  import { spawn } from "node:child_process";
7
7
  import { homedir } from "node:os";
8
+ import { existsSync } from "node:fs";
8
9
  import { os } from "@orpc/server";
9
10
  import { createCli } from "trpc-cli";
10
11
  import { createInterface } from "node:readline/promises";
@@ -13,7 +14,6 @@ import { isContractProcedure } from "@orpc/contract";
13
14
  import { OpenAPILink } from "@orpc/openapi-client/fetch";
14
15
  import { z } from "zod";
15
16
  import { createClient } from "@hey-api/openapi-ts";
16
- import { readFileSync } from "node:fs";
17
17
  //#region ../shared/auth/src/store.mts
18
18
  const DEFAULT_INSTANCE_URL = "https://app.hitch42.com";
19
19
  var AuthenticationError = class extends Error {};
@@ -187,7 +187,7 @@ async function resolveAuth(instanceUrl, options = {}, orgCode) {
187
187
  const soleOrg = orgCodes.at(0);
188
188
  if (soleOrg === void 0) return void 0;
189
189
  if (orgCodes.length === 1) return resolvedStoredAuth(credentialsByOrg[soleOrg]);
190
- throw new AuthenticationError(`Multiple organizations are stored for ${normalizedUrl}: ${orgCodes.join(", ")}. Use --org, a workspace hitch.org, or HITCH_DEFAULT_ORG to choose one.`);
190
+ throw new AuthenticationError(`Multiple organizations are stored for ${normalizedUrl}: ${orgCodes.join(", ")}. Use --org, the workspace hitch.config.ts, or HITCH_DEFAULT_ORG to choose one.`);
191
191
  }
192
192
  function rejectEnvironmentKey(response, auth) {
193
193
  if (auth.source === "environment" && response.status === 401) throw new AuthenticationError("HITCH_API_KEY was rejected.");
@@ -402,6 +402,33 @@ async function loginWithDevice(instanceUrl, options = {}) {
402
402
  };
403
403
  }
404
404
  //#endregion
405
+ //#region ../shared/auth/src/workspace.mts
406
+ const ORG_CODE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
407
+ const require = createRequire(import.meta.url);
408
+ function readWorkspaceConfig(dir) {
409
+ const path = resolve(dir, "hitch.config.ts");
410
+ if (!existsSync(path)) return void 0;
411
+ let module;
412
+ try {
413
+ module = require(path);
414
+ } catch (error) {
415
+ throw new Error(`Failed to load ${path}.`, { cause: error });
416
+ }
417
+ const config = module !== null && typeof module === "object" && "default" in module ? module.default : module;
418
+ if (config === null || typeof config !== "object" || !("sdk" in config) || typeof config.sdk !== "string" || config.sdk.length === 0 || !("org" in config) || typeof config.org !== "string" || !ORG_CODE_PATTERN.test(config.org)) throw new Error(`Invalid Hitch config in ${path}: "sdk" must be a package spec and "org" an organization code.`);
419
+ const githubWorkflow = "githubWorkflow" in config ? config.githubWorkflow : void 0;
420
+ if (githubWorkflow !== void 0 && typeof githubWorkflow !== "boolean") throw new Error(`Invalid Hitch config in ${path}: "githubWorkflow" must be a boolean.`);
421
+ return {
422
+ sdk: config.sdk,
423
+ org: config.org,
424
+ githubWorkflow
425
+ };
426
+ }
427
+ function findWorkspaceConfig(cwd) {
428
+ const appletsDir = dirname(cwd);
429
+ return readWorkspaceConfig(cwd) ?? (basename(appletsDir) === "applets" ? readWorkspaceConfig(dirname(appletsDir)) : void 0);
430
+ }
431
+ //#endregion
405
432
  //#region src/bridge.ts
406
433
  async function defaultPrompt$1(message) {
407
434
  const readline = createInterface({
@@ -529,7 +556,7 @@ function createBridgeRouter(contract, options) {
529
556
  }
530
557
  //#endregion
531
558
  //#region src/generate.ts
532
- const RECORD_ROUTE = /^\/v1\/([^/]+)(?:\/(\{id\}|query|update|aggregate))?$/;
559
+ const RECORD_ROUTE = /^\/v1\/([^/]+)(?:\/(\{id\}(?:\/history)?|query|update|aggregate))?$/;
533
560
  const BATCH_PATH = "/v1/batch";
534
561
  const BATCH_ITEM_PATH = "paths./v1/batch.post.requestBody.content.application/json.schema.properties.requests.items";
535
562
  const BATCH_ID_PATH = /^\^\/v1\/([^/]+)\/\[0-9a-fA-F-\]\{36\}\$$/;
@@ -537,6 +564,7 @@ const VERBS = {
537
564
  "get:": "list",
538
565
  "post:": "create",
539
566
  "get:{id}": "get",
567
+ "get:{id}/history": "history",
540
568
  "patch:{id}": "update",
541
569
  "delete:{id}": "delete",
542
570
  "post:query": "query",
@@ -646,7 +674,7 @@ function prepareRecordSpec(spec) {
646
674
  const prepared = flattenTrivialAllOf(cloned, isObject$1(cloned.components) && isObject$1(cloned.components.schemas) ? cloned.components.schemas : {});
647
675
  prepared.paths = Object.fromEntries(Object.entries(prepared.paths).flatMap(([path, pathItem]) => {
648
676
  if (path === BATCH_PATH) {
649
- if (!isObject$1(pathItem) || pathItem.post === void 0) return [];
677
+ if (!isObject$1(pathItem)) return [];
650
678
  const operation = prepareBatchOperation(pathItem.post);
651
679
  return operation === void 0 ? [] : [[path, { post: operation }]];
652
680
  }
@@ -968,40 +996,13 @@ function createStaticRouter(activeInstanceUrl, dependencies = {}, selectedOrg) {
968
996
  }
969
997
  //#endregion
970
998
  //#region src/organization.ts
971
- const ORG_CODE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
972
- function readOrg(dir) {
973
- const path = resolve(dir, "package.json");
974
- let source;
975
- try {
976
- source = readFileSync(path, "utf8");
977
- } catch (error) {
978
- if (error instanceof Error && "code" in error && error.code === "ENOENT") return void 0;
979
- throw error;
980
- }
981
- let packageJson;
982
- try {
983
- packageJson = JSON.parse(source);
984
- } catch (error) {
985
- throw new Error(`Invalid JSON in ${path}.`, { cause: error });
986
- }
987
- if (packageJson === null || typeof packageJson !== "object" || !("hitch" in packageJson)) return;
988
- const hitch = packageJson.hitch;
989
- if (hitch === null || typeof hitch !== "object" || !("org" in hitch) || typeof hitch.org !== "string" || !ORG_CODE_PATTERN.test(hitch.org)) throw new Error(`Invalid "hitch.org" in ${path}.`);
990
- return hitch.org;
991
- }
992
- function readWorkspaceOrg(cwd) {
993
- const localOrg = readOrg(cwd);
994
- if (localOrg !== void 0) return localOrg;
995
- const appletsDir = dirname(cwd);
996
- return basename(appletsDir) === "applets" ? readOrg(dirname(appletsDir)) : void 0;
997
- }
998
999
  function validateOrg(orgCode, source) {
999
1000
  if (!ORG_CODE_PATTERN.test(orgCode)) throw new Error(`Invalid organization in ${source}.`);
1000
1001
  return orgCode;
1001
1002
  }
1002
1003
  function resolveOrganization(explicitOrg, cwd, env) {
1003
1004
  const cliOrg = explicitOrg === void 0 ? void 0 : validateOrg(explicitOrg, "--org");
1004
- const workspaceOrg = readWorkspaceOrg(cwd);
1005
+ const workspaceOrg = findWorkspaceConfig(cwd)?.org;
1005
1006
  if (cliOrg !== void 0 && workspaceOrg !== void 0 && cliOrg !== workspaceOrg) throw new Error(`--org "${cliOrg}" does not match workspace organization "${workspaceOrg}".`);
1006
1007
  if (cliOrg !== void 0 || workspaceOrg !== void 0) return cliOrg ?? workspaceOrg;
1007
1008
  const defaultOrg = env.HITCH_DEFAULT_ORG;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hitch42/cli",
3
- "version": "0.1.0-beta.3",
3
+ "version": "0.1.0-beta.9",
4
4
  "license": "MIT",
5
5
  "bin": {
6
6
  "hitch": "./dist/hitch.js"
@@ -19,7 +19,7 @@
19
19
  "zod": "^4.4.3"
20
20
  },
21
21
  "engines": {
22
- "node": ">=22"
22
+ "node": ">=22.18"
23
23
  },
24
24
  "repository": {
25
25
  "type": "git",