@neat.is/core 0.5.3 → 0.5.4-dev.20260721

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.
package/dist/cli.js CHANGED
@@ -1,15 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- PROVIDER_DISPATCH,
4
3
  clearDaemonRecord,
5
- getProviderDispatch,
4
+ deprovisionConnector,
5
+ getProviderFieldSchema,
6
+ isPushProvider,
7
+ knownProviderNames,
6
8
  portFromListenAddress,
9
+ provisionConnector,
7
10
  readDaemonRecord,
8
11
  resolveHost,
9
12
  resolveNeatVersion,
10
13
  validateConnectorEntry,
11
14
  writeDaemonRecord
12
- } from "./chunk-X2AMX3QZ.js";
15
+ } from "./chunk-VR73QNJD.js";
13
16
  import {
14
17
  buildSearchIndex
15
18
  } from "./chunk-BIY46Q6U.js";
@@ -68,10 +71,10 @@ import {
68
71
  startPersistLoop,
69
72
  startStalenessLoop,
70
73
  upsertConnectorEntry
71
- } from "./chunk-GJHEZC5K.js";
74
+ } from "./chunk-PEFX3DBR.js";
72
75
  import {
73
76
  startOtelGrpcReceiver
74
- } from "./chunk-I72HTUOG.js";
77
+ } from "./chunk-4RU3AAOI.js";
75
78
  import {
76
79
  __dirname,
77
80
  __require,
@@ -79,7 +82,7 @@ import {
79
82
  buildOtelReceiver,
80
83
  listenSteppingOtlp,
81
84
  readAuthEnv
82
- } from "./chunk-CFDPIMRP.js";
85
+ } from "./chunk-I4NZ7PSN.js";
83
86
 
84
87
  // src/cli.ts
85
88
  import path10 from "path";
@@ -3566,6 +3569,8 @@ function parseConnectorArgs(args) {
3566
3569
  positional: [],
3567
3570
  skipValidate: false,
3568
3571
  plaintext: false,
3572
+ help: false,
3573
+ json: false,
3569
3574
  fields: {}
3570
3575
  };
3571
3576
  const positional = [];
@@ -3579,6 +3584,14 @@ function parseConnectorArgs(args) {
3579
3584
  out.plaintext = true;
3580
3585
  continue;
3581
3586
  }
3587
+ if (arg === "--help" || arg === "-h") {
3588
+ out.help = true;
3589
+ continue;
3590
+ }
3591
+ if (arg === "--json") {
3592
+ out.json = true;
3593
+ continue;
3594
+ }
3582
3595
  if (arg.startsWith("--")) {
3583
3596
  let flag = arg;
3584
3597
  let value;
@@ -3655,19 +3668,20 @@ function plaintextFields(ref) {
3655
3668
  async function connectorAdd(args, deps) {
3656
3669
  let provider = args.positional[0];
3657
3670
  if (!provider && deps.interactive) {
3658
- provider = (await deps.prompt(`Provider (${Object.keys(PROVIDER_DISPATCH).sort().join(", ")}):`)).trim();
3671
+ provider = (await deps.prompt(`Provider (${knownProviderNames().join(", ")}):`)).trim();
3659
3672
  }
3660
3673
  if (!provider) {
3661
3674
  deps.err("neat connector add: a provider is required (e.g. `neat connector add supabase`)");
3662
3675
  return 2;
3663
3676
  }
3664
- const dispatch = getProviderDispatch(provider);
3677
+ const dispatch = getProviderFieldSchema(provider);
3665
3678
  if (!dispatch) {
3666
3679
  deps.err(
3667
- `neat connector add: unknown provider "${provider}". known providers: ${Object.keys(PROVIDER_DISPATCH).sort().join(", ")}`
3680
+ `neat connector add: unknown provider "${provider}". known providers: ${knownProviderNames().join(", ")}`
3668
3681
  );
3669
3682
  return 2;
3670
3683
  }
3684
+ const push = isPushProvider(provider);
3671
3685
  let project = args.project;
3672
3686
  if (project === void 0 && deps.interactive) {
3673
3687
  const answer = (await deps.prompt("Project (blank = the project the daemon is bootstrapping):")).trim();
@@ -3706,7 +3720,7 @@ async function connectorAdd(args, deps) {
3706
3720
  credential,
3707
3721
  ...Object.keys(options).length > 0 ? { options } : {}
3708
3722
  };
3709
- if (!args.skipValidate) {
3723
+ if (!push && !args.skipValidate) {
3710
3724
  const outcome = await validateConnectorEntry(entry2, deps.env, deps.fetchImpl);
3711
3725
  const code = reportPreWriteValidation(outcome, deps);
3712
3726
  if (code !== 0) return code;
@@ -3717,14 +3731,32 @@ async function connectorAdd(args, deps) {
3717
3731
  `neat connector add: storing a literal secret at rest for ${plaintext.join(", ")} \u2014 prefer an env-var reference like \`$PROVIDER_TOKEN\` (pass --plaintext to silence this).`
3718
3732
  );
3719
3733
  }
3734
+ if (push) {
3735
+ if (args.skipValidate) {
3736
+ deps.out("note: --skip-validate has no effect for a push provider \u2014 provisioning the drain is the add.");
3737
+ }
3738
+ const outcome = await provisionConnector(entry2, deps.env, deps.fetchImpl);
3739
+ if (outcome.status !== "ok") {
3740
+ deps.err(
3741
+ `neat connector add: could not provision the ${provider} connector \u2014 ${outcome.reason}. Nothing was written.`
3742
+ );
3743
+ return 1;
3744
+ }
3745
+ if (outcome.options) entry2.options = { ...entry2.options ?? {}, ...outcome.options };
3746
+ if (outcome.note) deps.out(`note: ${outcome.note}`);
3747
+ }
3720
3748
  const { replaced } = await upsertConnectorEntry(entry2, deps.home);
3721
3749
  const verb = replaced ? "updated" : "added";
3722
3750
  const where = project ? `project "${project}"` : "the bootstrapping project";
3723
3751
  deps.out(`${verb} connector "${id}" (${provider}) for ${where}.`);
3724
- if (args.skipValidate) {
3725
- deps.out("skipped validation (--skip-validate) \u2014 the credential is checked at the next daemon poll.");
3752
+ if (push) {
3753
+ deps.out("The drain is live \u2014 traces arrive at the daemon's OTLP receiver. No poll or restart needed.");
3754
+ } else {
3755
+ if (args.skipValidate) {
3756
+ deps.out("skipped validation (--skip-validate) \u2014 the credential is checked at the next daemon poll.");
3757
+ }
3758
+ deps.out("Restart the project's daemon (or start it) to begin polling this connector.");
3726
3759
  }
3727
- deps.out("Restart the project's daemon (or start it) to begin polling this connector.");
3728
3760
  return 0;
3729
3761
  }
3730
3762
  function reportPreWriteValidation(outcome, deps) {
@@ -3750,10 +3782,26 @@ function reportPreWriteValidation(outcome, deps) {
3750
3782
  return 2;
3751
3783
  }
3752
3784
  }
3753
- async function connectorList(deps, filterProject) {
3785
+ async function connectorList(deps, filterProject, json = false) {
3754
3786
  const config = await readConnectorsConfig(deps.home);
3755
3787
  let entries = config.connectors;
3756
3788
  if (filterProject) entries = entries.filter((e) => e.project === filterProject);
3789
+ if (json) {
3790
+ const rows = entries.map((e) => ({
3791
+ id: e.id,
3792
+ provider: e.provider,
3793
+ project: e.project ?? null,
3794
+ kind: isPushProvider(e.provider) ? "push" : "pull",
3795
+ credential: describeCredential(e.credential, deps.env).map((c) => ({
3796
+ ...c.field ? { field: c.field } : {},
3797
+ ref: c.display,
3798
+ ...c.status ? { status: c.status } : { kind: c.kind }
3799
+ })),
3800
+ ...e.options ? { options: e.options } : {}
3801
+ }));
3802
+ deps.out(JSON.stringify(rows, null, 2));
3803
+ return 0;
3804
+ }
3757
3805
  if (entries.length === 0) {
3758
3806
  deps.out(
3759
3807
  filterProject ? `no connectors configured for project "${filterProject}".` : "no connectors configured. run `neat connector add <provider>` to add one."
@@ -3776,6 +3824,22 @@ async function connectorRemove(deps, id) {
3776
3824
  deps.err("neat connector remove: missing <id>. run `neat connector list` to see configured ids.");
3777
3825
  return 2;
3778
3826
  }
3827
+ const config = await readConnectorsConfig(deps.home);
3828
+ const entry2 = config.connectors.find((c) => c.id === id);
3829
+ if (!entry2) {
3830
+ deps.err(`neat connector remove: no connector with id "${id}". run \`neat connector list\` to see configured ids.`);
3831
+ return 1;
3832
+ }
3833
+ if (isPushProvider(entry2.provider)) {
3834
+ const outcome = await deprovisionConnector(entry2, deps.env, deps.fetchImpl);
3835
+ if (outcome.status !== "ok") {
3836
+ deps.err(
3837
+ `neat connector remove: could not delete the ${entry2.provider} drain \u2014 ${outcome.reason}. The entry was kept so you can retry (or delete the drain in the Vercel dashboard, then re-run).`
3838
+ );
3839
+ return 1;
3840
+ }
3841
+ if (outcome.note) deps.out(`note: ${outcome.note}`);
3842
+ }
3779
3843
  const removed = await removeConnectorEntry(id, deps.home);
3780
3844
  if (!removed) {
3781
3845
  deps.err(`neat connector remove: no connector with id "${id}". run \`neat connector list\` to see configured ids.`);
@@ -3816,13 +3880,20 @@ async function connectorTest(deps, id) {
3816
3880
  }
3817
3881
  function printConnectorUsage(write) {
3818
3882
  write("usage: neat connector <add|list|remove|test> [args]");
3883
+ write(` providers: ${knownProviderNames().join(", ")}`);
3884
+ write(" pull (polled): supabase, railway, firebase, cloudflare");
3885
+ write(" push (drains): vercel \u2014 provisions a Vercel trace Drain that forwards");
3886
+ write(" traces to the daemon's OTLP receiver; no app instrumentation");
3819
3887
  write(" add <provider> add a connector; validates the credential first (--skip-validate to skip)");
3820
3888
  write(" flags: --project <name> --credential/--token <$VAR|value> --id <id>");
3821
3889
  write(" --<option> <value> (provider-specific) --plaintext --skip-validate");
3890
+ write(" vercel: neat connector add vercel --token $VERCEL_TOKEN \\");
3891
+ write(" --otel-token $NEAT_OTEL_TOKEN --team-id <teamId> \\");
3892
+ write(" --endpoint https://<public-host>/v1/traces [--project-ids <id,id>]");
3822
3893
  write(" list list configured connectors (credentials shown redacted)");
3823
3894
  write(" flags: --project <name>");
3824
- write(" remove <id> remove a connector by id");
3825
- write(" test <id> re-run the credential validation for an existing connector");
3895
+ write(" remove <id> remove a connector by id (a push provider also has its drain deleted)");
3896
+ write(" test <id> re-run validation for an existing connector (a push provider re-tests its drain)");
3826
3897
  }
3827
3898
  async function runConnectorCommand(rawArgs, deps = {}) {
3828
3899
  const resolved = resolveDeps(deps);
@@ -3832,11 +3903,15 @@ async function runConnectorCommand(rawArgs, deps = {}) {
3832
3903
  return 2;
3833
3904
  }
3834
3905
  const a = parsed.value;
3906
+ if (a.help) {
3907
+ printConnectorUsage(resolved.out);
3908
+ return 0;
3909
+ }
3835
3910
  switch (a.subcommand) {
3836
3911
  case "add":
3837
3912
  return connectorAdd(a, resolved);
3838
3913
  case "list":
3839
- return connectorList(resolved, a.project);
3914
+ return connectorList(resolved, a.project, a.json);
3840
3915
  case "remove":
3841
3916
  return connectorRemove(resolved, a.positional[0]);
3842
3917
  case "test":
@@ -4787,8 +4862,9 @@ function usage2() {
4787
4862
  console.log(" --dry-run run extraction in-memory; do not write");
4788
4863
  console.log(" --no-instrument skip the SDK install apply step");
4789
4864
  console.log(" --json emit the delta summary as JSON");
4790
- console.log(" connector Configure pull-based OBSERVED connectors (supabase, railway,");
4791
- console.log(" firebase, cloudflare). Subcommands:");
4865
+ console.log(" connector Configure OBSERVED connectors \u2014 pull (supabase, railway,");
4866
+ console.log(" firebase, cloudflare) and push (vercel, via a trace Drain).");
4867
+ console.log(" Subcommands:");
4792
4868
  console.log(" add <provider> add a connector; validates the credential");
4793
4869
  console.log(" against the provider first (--skip-validate to skip)");
4794
4870
  console.log(" flags: --project <name>, --credential/--token <$VAR|value>,");