@hasna/contacts 0.6.31 → 0.6.33

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.
@@ -4513,10 +4513,13 @@ var require_data = __commonJS((exports, module) => {
4513
4513
  };
4514
4514
  });
4515
4515
 
4516
- // node_modules/fast-uri/lib/utils.js
4516
+ // vendor/fast-uri/lib/utils.js
4517
4517
  var require_utils = __commonJS((exports, module) => {
4518
4518
  var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
4519
4519
  var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
4520
+ var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
4521
+ var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
4522
+ var isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu);
4520
4523
  function stringArrayToHexStripped(input) {
4521
4524
  let acc = "";
4522
4525
  let code = 0;
@@ -4710,27 +4713,77 @@ var require_utils = __commonJS((exports, module) => {
4710
4713
  }
4711
4714
  return output.join("");
4712
4715
  }
4713
- function normalizeComponentEncoding(component, esc2) {
4714
- const func = esc2 !== true ? escape : unescape;
4715
- if (component.scheme !== undefined) {
4716
- component.scheme = func(component.scheme);
4717
- }
4718
- if (component.userinfo !== undefined) {
4719
- component.userinfo = func(component.userinfo);
4720
- }
4721
- if (component.host !== undefined) {
4722
- component.host = func(component.host);
4716
+ var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
4717
+ var HOST_DELIM_RE = /[@/?#:]/g;
4718
+ var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
4719
+ function reescapeHostDelimiters(host, isIP) {
4720
+ const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
4721
+ re.lastIndex = 0;
4722
+ return host.replace(re, (ch) => HOST_DELIMS[ch]);
4723
+ }
4724
+ function normalizePercentEncoding(input, decodeUnreserved = false) {
4725
+ if (input.indexOf("%") === -1) {
4726
+ return input;
4723
4727
  }
4724
- if (component.path !== undefined) {
4725
- component.path = func(component.path);
4728
+ let output = "";
4729
+ for (let i = 0;i < input.length; i++) {
4730
+ if (input[i] === "%" && i + 2 < input.length) {
4731
+ const hex = input.slice(i + 1, i + 3);
4732
+ if (isHexPair(hex)) {
4733
+ const normalizedHex = hex.toUpperCase();
4734
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
4735
+ if (decodeUnreserved && isUnreserved(decoded)) {
4736
+ output += decoded;
4737
+ } else {
4738
+ output += "%" + normalizedHex;
4739
+ }
4740
+ i += 2;
4741
+ continue;
4742
+ }
4743
+ }
4744
+ output += input[i];
4726
4745
  }
4727
- if (component.query !== undefined) {
4728
- component.query = func(component.query);
4746
+ return output;
4747
+ }
4748
+ function normalizePathEncoding(input) {
4749
+ let output = "";
4750
+ for (let i = 0;i < input.length; i++) {
4751
+ if (input[i] === "%" && i + 2 < input.length) {
4752
+ const hex = input.slice(i + 1, i + 3);
4753
+ if (isHexPair(hex)) {
4754
+ const normalizedHex = hex.toUpperCase();
4755
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
4756
+ if (decoded !== "." && isUnreserved(decoded)) {
4757
+ output += decoded;
4758
+ } else {
4759
+ output += "%" + normalizedHex;
4760
+ }
4761
+ i += 2;
4762
+ continue;
4763
+ }
4764
+ }
4765
+ if (isPathCharacter(input[i])) {
4766
+ output += input[i];
4767
+ } else {
4768
+ output += escape(input[i]);
4769
+ }
4729
4770
  }
4730
- if (component.fragment !== undefined) {
4731
- component.fragment = func(component.fragment);
4771
+ return output;
4772
+ }
4773
+ function escapePreservingEscapes(input) {
4774
+ let output = "";
4775
+ for (let i = 0;i < input.length; i++) {
4776
+ if (input[i] === "%" && i + 2 < input.length) {
4777
+ const hex = input.slice(i + 1, i + 3);
4778
+ if (isHexPair(hex)) {
4779
+ output += "%" + hex.toUpperCase();
4780
+ i += 2;
4781
+ continue;
4782
+ }
4783
+ }
4784
+ output += escape(input[i]);
4732
4785
  }
4733
- return component;
4786
+ return output;
4734
4787
  }
4735
4788
  function recomposeAuthority(component) {
4736
4789
  const uriTokens = [];
@@ -4745,7 +4798,7 @@ var require_utils = __commonJS((exports, module) => {
4745
4798
  if (ipV6res.isIPV6 === true) {
4746
4799
  host = `[${ipV6res.escapedHost}]`;
4747
4800
  } else {
4748
- host = component.host;
4801
+ host = reescapeHostDelimiters(host, false);
4749
4802
  }
4750
4803
  }
4751
4804
  uriTokens.push(host);
@@ -4759,7 +4812,10 @@ var require_utils = __commonJS((exports, module) => {
4759
4812
  module.exports = {
4760
4813
  nonSimpleDomain,
4761
4814
  recomposeAuthority,
4762
- normalizeComponentEncoding,
4815
+ reescapeHostDelimiters,
4816
+ normalizePercentEncoding,
4817
+ normalizePathEncoding,
4818
+ escapePreservingEscapes,
4763
4819
  removeDotSegments,
4764
4820
  isIPv4,
4765
4821
  isUUID,
@@ -4768,7 +4824,7 @@ var require_utils = __commonJS((exports, module) => {
4768
4824
  };
4769
4825
  });
4770
4826
 
4771
- // node_modules/fast-uri/lib/schemes.js
4827
+ // vendor/fast-uri/lib/schemes.js
4772
4828
  var require_schemes = __commonJS((exports, module) => {
4773
4829
  var { isUUID } = require_utils();
4774
4830
  var URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu;
@@ -4942,13 +4998,13 @@ var require_schemes = __commonJS((exports, module) => {
4942
4998
  };
4943
4999
  });
4944
5000
 
4945
- // node_modules/fast-uri/index.js
5001
+ // vendor/fast-uri/index.js
4946
5002
  var require_fast_uri = __commonJS((exports, module) => {
4947
- var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils();
5003
+ var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
4948
5004
  var { SCHEMES, getSchemeHandler } = require_schemes();
4949
5005
  function normalize(uri, options) {
4950
5006
  if (typeof uri === "string") {
4951
- uri = serialize(parse6(uri, options), options);
5007
+ uri = normalizeString(uri, options);
4952
5008
  } else if (typeof uri === "object") {
4953
5009
  uri = parse6(serialize(uri, options), options);
4954
5010
  }
@@ -5014,19 +5070,9 @@ var require_fast_uri = __commonJS((exports, module) => {
5014
5070
  return target;
5015
5071
  }
5016
5072
  function equal(uriA, uriB, options) {
5017
- if (typeof uriA === "string") {
5018
- uriA = unescape(uriA);
5019
- uriA = serialize(normalizeComponentEncoding(parse6(uriA, options), true), { ...options, skipEscape: true });
5020
- } else if (typeof uriA === "object") {
5021
- uriA = serialize(normalizeComponentEncoding(uriA, true), { ...options, skipEscape: true });
5022
- }
5023
- if (typeof uriB === "string") {
5024
- uriB = unescape(uriB);
5025
- uriB = serialize(normalizeComponentEncoding(parse6(uriB, options), true), { ...options, skipEscape: true });
5026
- } else if (typeof uriB === "object") {
5027
- uriB = serialize(normalizeComponentEncoding(uriB, true), { ...options, skipEscape: true });
5028
- }
5029
- return uriA.toLowerCase() === uriB.toLowerCase();
5073
+ const normalizedA = normalizeComparableURI(uriA, options);
5074
+ const normalizedB = normalizeComparableURI(uriB, options);
5075
+ return normalizedA !== undefined && normalizedB !== undefined && normalizedA.toLowerCase() === normalizedB.toLowerCase();
5030
5076
  }
5031
5077
  function serialize(cmpts, opts) {
5032
5078
  const component = {
@@ -5052,12 +5098,12 @@ var require_fast_uri = __commonJS((exports, module) => {
5052
5098
  schemeHandler.serialize(component, options);
5053
5099
  if (component.path !== undefined) {
5054
5100
  if (!options.skipEscape) {
5055
- component.path = escape(component.path);
5101
+ component.path = escapePreservingEscapes(component.path);
5056
5102
  if (component.scheme !== undefined) {
5057
5103
  component.path = component.path.split("%3A").join(":");
5058
5104
  }
5059
5105
  } else {
5060
- component.path = unescape(component.path);
5106
+ component.path = normalizePercentEncoding(component.path);
5061
5107
  }
5062
5108
  }
5063
5109
  if (options.reference !== "suffix" && component.scheme) {
@@ -5092,7 +5138,17 @@ var require_fast_uri = __commonJS((exports, module) => {
5092
5138
  return uriTokens.join("");
5093
5139
  }
5094
5140
  var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
5095
- function parse6(uri, opts) {
5141
+ var AUTHORITY_PREFIX = /^(?:[^#/:?]+:)?\/\/([^/?#]*)/;
5142
+ function getParseError(parsed, matches) {
5143
+ if (matches[2] !== undefined && parsed.path && parsed.path[0] !== "/") {
5144
+ return 'URI path must start with "/" when authority is present.';
5145
+ }
5146
+ if (typeof parsed.port === "number" && (parsed.port < 0 || parsed.port > 65535)) {
5147
+ return "URI port is malformed.";
5148
+ }
5149
+ return;
5150
+ }
5151
+ function parseWithStatus(uri, opts) {
5096
5152
  const options = Object.assign({}, opts);
5097
5153
  const parsed = {
5098
5154
  scheme: undefined,
@@ -5103,6 +5159,7 @@ var require_fast_uri = __commonJS((exports, module) => {
5103
5159
  query: undefined,
5104
5160
  fragment: undefined
5105
5161
  };
5162
+ let malformedAuthorityOrPort = false;
5106
5163
  let isIP = false;
5107
5164
  if (options.reference === "suffix") {
5108
5165
  if (options.scheme) {
@@ -5111,6 +5168,11 @@ var require_fast_uri = __commonJS((exports, module) => {
5111
5168
  uri = "//" + uri;
5112
5169
  }
5113
5170
  }
5171
+ const authorityMatch = uri.match(AUTHORITY_PREFIX);
5172
+ if (authorityMatch !== null && authorityMatch[1].indexOf("\\") !== -1) {
5173
+ parsed.error = "URI authority must not contain a literal backslash.";
5174
+ malformedAuthorityOrPort = true;
5175
+ }
5114
5176
  const matches = uri.match(URI_PARSE);
5115
5177
  if (matches) {
5116
5178
  parsed.scheme = matches[1];
@@ -5123,6 +5185,11 @@ var require_fast_uri = __commonJS((exports, module) => {
5123
5185
  if (isNaN(parsed.port)) {
5124
5186
  parsed.port = matches[5];
5125
5187
  }
5188
+ const parseError = getParseError(parsed, matches);
5189
+ if (parseError !== undefined) {
5190
+ parsed.error = parsed.error || parseError;
5191
+ malformedAuthorityOrPort = true;
5192
+ }
5126
5193
  if (parsed.host) {
5127
5194
  const ipv4result = isIPv4(parsed.host);
5128
5195
  if (ipv4result === false) {
@@ -5149,7 +5216,7 @@ var require_fast_uri = __commonJS((exports, module) => {
5149
5216
  if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
5150
5217
  if (parsed.host && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
5151
5218
  try {
5152
- parsed.host = URL.domainToASCII(parsed.host.toLowerCase());
5219
+ parsed.host = new URL("http://" + parsed.host).hostname;
5153
5220
  } catch (e) {
5154
5221
  parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
5155
5222
  }
@@ -5161,14 +5228,18 @@ var require_fast_uri = __commonJS((exports, module) => {
5161
5228
  parsed.scheme = unescape(parsed.scheme);
5162
5229
  }
5163
5230
  if (parsed.host !== undefined) {
5164
- parsed.host = unescape(parsed.host);
5231
+ parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
5165
5232
  }
5166
5233
  }
5167
5234
  if (parsed.path) {
5168
- parsed.path = escape(unescape(parsed.path));
5235
+ parsed.path = normalizePathEncoding(parsed.path);
5169
5236
  }
5170
5237
  if (parsed.fragment) {
5171
- parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
5238
+ try {
5239
+ parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
5240
+ } catch {
5241
+ parsed.error = parsed.error || "URI malformed";
5242
+ }
5172
5243
  }
5173
5244
  }
5174
5245
  if (schemeHandler && schemeHandler.parse) {
@@ -5177,7 +5248,29 @@ var require_fast_uri = __commonJS((exports, module) => {
5177
5248
  } else {
5178
5249
  parsed.error = parsed.error || "URI can not be parsed.";
5179
5250
  }
5180
- return parsed;
5251
+ return { parsed, malformedAuthorityOrPort };
5252
+ }
5253
+ function parse6(uri, opts) {
5254
+ return parseWithStatus(uri, opts).parsed;
5255
+ }
5256
+ function normalizeString(uri, opts) {
5257
+ return normalizeStringWithStatus(uri, opts).normalized;
5258
+ }
5259
+ function normalizeStringWithStatus(uri, opts) {
5260
+ const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
5261
+ return {
5262
+ normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
5263
+ malformedAuthorityOrPort
5264
+ };
5265
+ }
5266
+ function normalizeComparableURI(uri, opts) {
5267
+ if (typeof uri === "string") {
5268
+ const { normalized, malformedAuthorityOrPort } = normalizeStringWithStatus(uri, opts);
5269
+ return malformedAuthorityOrPort ? undefined : normalized;
5270
+ }
5271
+ if (typeof uri === "object") {
5272
+ return serialize(uri, opts);
5273
+ }
5181
5274
  }
5182
5275
  var fastUri = {
5183
5276
  SCHEMES,
@@ -8950,7 +9043,8 @@ function resolveSigningSecret(env = process.env) {
8950
9043
  return env.HASNA_CONTACTS_API_SIGNING_KEY || env.HASNA_API_SIGNING_KEY || env.API_KEY_SIGNING_SECRET || undefined;
8951
9044
  }
8952
9045
  function isCloudModeEnabled(env = process.env) {
8953
- return Boolean(resolveCloudDatabaseUrl(env));
9046
+ const mode = env.HASNA_CONTACTS_STORAGE_MODE || env.CONTACTS_STORAGE_MODE;
9047
+ return Boolean(resolveCloudDatabaseUrl(env)) || mode === "cloud" || mode === "self_hosted";
8954
9048
  }
8955
9049
  function getCloudClient() {
8956
9050
  if (cachedClient)
@@ -10084,7 +10178,7 @@ function getDocumentsDir() {
10084
10178
  return DOCUMENTS_DIR;
10085
10179
  }
10086
10180
 
10087
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/core.js
10181
+ // node_modules/zod/v4/core/core.js
10088
10182
  var NEVER = Object.freeze({
10089
10183
  status: "aborted"
10090
10184
  });
@@ -10144,7 +10238,7 @@ function config(newConfig) {
10144
10238
  Object.assign(globalConfig, newConfig);
10145
10239
  return globalConfig;
10146
10240
  }
10147
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/util.js
10241
+ // node_modules/zod/v4/core/util.js
10148
10242
  var exports_util = {};
10149
10243
  __export(exports_util, {
10150
10244
  unwrapMessage: () => unwrapMessage,
@@ -10658,7 +10752,7 @@ class Class {
10658
10752
  constructor(..._args) {}
10659
10753
  }
10660
10754
 
10661
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/errors.js
10755
+ // node_modules/zod/v4/core/errors.js
10662
10756
  var initializer = (inst, def) => {
10663
10757
  inst.name = "$ZodError";
10664
10758
  Object.defineProperty(inst, "_zod", {
@@ -10732,7 +10826,7 @@ function formatError(error, _mapper) {
10732
10826
  return fieldErrors;
10733
10827
  }
10734
10828
 
10735
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/parse.js
10829
+ // node_modules/zod/v4/core/parse.js
10736
10830
  var _parse = (_Err) => (schema, value, _ctx, _params) => {
10737
10831
  const ctx = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
10738
10832
  const result = schema._zod.run({ value, issues: [] }, ctx);
@@ -10783,7 +10877,7 @@ var _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
10783
10877
  } : { success: true, data: result.value };
10784
10878
  };
10785
10879
  var safeParseAsync = /* @__PURE__ */ _safeParseAsync($ZodRealError);
10786
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/regexes.js
10880
+ // node_modules/zod/v4/core/regexes.js
10787
10881
  var cuid = /^[cC][^\s-]{8,}$/;
10788
10882
  var cuid2 = /^[0-9a-z]+$/;
10789
10883
  var ulid = /^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/;
@@ -10841,7 +10935,7 @@ var _null = /null/i;
10841
10935
  var lowercase = /^[^A-Z]*$/;
10842
10936
  var uppercase = /^[^a-z]*$/;
10843
10937
 
10844
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/checks.js
10938
+ // node_modules/zod/v4/core/checks.js
10845
10939
  var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
10846
10940
  var _a;
10847
10941
  inst._zod ?? (inst._zod = {});
@@ -11225,7 +11319,7 @@ var $ZodCheckOverwrite = /* @__PURE__ */ $constructor("$ZodCheckOverwrite", (ins
11225
11319
  };
11226
11320
  });
11227
11321
 
11228
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/doc.js
11322
+ // node_modules/zod/v4/core/doc.js
11229
11323
  class Doc {
11230
11324
  constructor(args = []) {
11231
11325
  this.content = [];
@@ -11263,14 +11357,14 @@ class Doc {
11263
11357
  }
11264
11358
  }
11265
11359
 
11266
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/versions.js
11360
+ // node_modules/zod/v4/core/versions.js
11267
11361
  var version = {
11268
11362
  major: 4,
11269
11363
  minor: 0,
11270
11364
  patch: 0
11271
11365
  };
11272
11366
 
11273
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/schemas.js
11367
+ // node_modules/zod/v4/core/schemas.js
11274
11368
  var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
11275
11369
  var _a;
11276
11370
  inst ?? (inst = {});
@@ -12501,7 +12595,7 @@ function handleRefineResult(result, payload, input, inst) {
12501
12595
  payload.issues.push(issue(_iss));
12502
12596
  }
12503
12597
  }
12504
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/locales/en.js
12598
+ // node_modules/zod/v4/locales/en.js
12505
12599
  var parsedType = (data) => {
12506
12600
  const t = typeof data;
12507
12601
  switch (t) {
@@ -12618,7 +12712,7 @@ function en_default() {
12618
12712
  localeError: error()
12619
12713
  };
12620
12714
  }
12621
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/registries.js
12715
+ // node_modules/zod/v4/core/registries.js
12622
12716
  var $output = Symbol("ZodOutput");
12623
12717
  var $input = Symbol("ZodInput");
12624
12718
 
@@ -12668,7 +12762,7 @@ function registry() {
12668
12762
  return new $ZodRegistry;
12669
12763
  }
12670
12764
  var globalRegistry = /* @__PURE__ */ registry();
12671
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/api.js
12765
+ // node_modules/zod/v4/core/api.js
12672
12766
  function _string(Class2, params) {
12673
12767
  return new Class2({
12674
12768
  type: "string",
@@ -13103,7 +13197,7 @@ function _refine(Class2, fn, _params) {
13103
13197
  });
13104
13198
  return schema;
13105
13199
  }
13106
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/to-json-schema.js
13200
+ // node_modules/zod/v4/core/to-json-schema.js
13107
13201
  class JSONSchemaGenerator {
13108
13202
  constructor(params) {
13109
13203
  this.counter = 0;
@@ -13409,7 +13503,7 @@ class JSONSchemaGenerator {
13409
13503
  if (val === undefined) {
13410
13504
  if (this.unrepresentable === "throw") {
13411
13505
  throw new Error("Literal `undefined` cannot be represented in JSON Schema");
13412
- } else {}
13506
+ }
13413
13507
  } else if (typeof val === "bigint") {
13414
13508
  if (this.unrepresentable === "throw") {
13415
13509
  throw new Error("BigInt literals cannot be represented in JSON Schema");
@@ -13855,7 +13949,7 @@ function isTransforming(_schema, _ctx) {
13855
13949
  }
13856
13950
  throw new Error(`Unknown schema type: ${def.type}`);
13857
13951
  }
13858
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/iso.js
13952
+ // node_modules/zod/v4/classic/iso.js
13859
13953
  var exports_iso = {};
13860
13954
  __export(exports_iso, {
13861
13955
  time: () => time2,
@@ -13896,7 +13990,7 @@ function duration2(params) {
13896
13990
  return _isoDuration(ZodISODuration, params);
13897
13991
  }
13898
13992
 
13899
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/errors.js
13993
+ // node_modules/zod/v4/classic/errors.js
13900
13994
  var initializer2 = (inst, issues) => {
13901
13995
  $ZodError.init(inst, issues);
13902
13996
  inst.name = "ZodError";
@@ -13925,13 +14019,13 @@ var ZodRealError = $constructor("ZodError", initializer2, {
13925
14019
  Parent: Error
13926
14020
  });
13927
14021
 
13928
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/parse.js
14022
+ // node_modules/zod/v4/classic/parse.js
13929
14023
  var parse3 = /* @__PURE__ */ _parse(ZodRealError);
13930
14024
  var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
13931
14025
  var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
13932
14026
  var safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
13933
14027
 
13934
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/schemas.js
14028
+ // node_modules/zod/v4/classic/schemas.js
13935
14029
  var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
13936
14030
  $ZodType.init(inst, def);
13937
14031
  inst.def = def;
@@ -14536,7 +14630,7 @@ function superRefine(fn) {
14536
14630
  function preprocess(fn, schema) {
14537
14631
  return pipe(transform(fn), schema);
14538
14632
  }
14539
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/external.js
14633
+ // node_modules/zod/v4/classic/external.js
14540
14634
  config(en_default());
14541
14635
 
14542
14636
  // node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
@@ -15967,7 +16061,7 @@ function startMcpHttpServer(options) {
15967
16061
  import { readFileSync as readFileSync5 } from "fs";
15968
16062
  import { join as join5 } from "path";
15969
16063
 
15970
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
16064
+ // node_modules/zod/v3/external.js
15971
16065
  var exports_external = {};
15972
16066
  __export(exports_external, {
15973
16067
  void: () => voidType,
@@ -16079,7 +16173,7 @@ __export(exports_external, {
16079
16173
  BRAND: () => BRAND
16080
16174
  });
16081
16175
 
16082
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
16176
+ // node_modules/zod/v3/helpers/util.js
16083
16177
  var util;
16084
16178
  (function(util2) {
16085
16179
  util2.assertEqual = (_) => {};
@@ -16210,7 +16304,7 @@ var getParsedType2 = (data) => {
16210
16304
  }
16211
16305
  };
16212
16306
 
16213
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js
16307
+ // node_modules/zod/v3/ZodError.js
16214
16308
  var ZodIssueCode = util.arrayToEnum([
16215
16309
  "invalid_type",
16216
16310
  "invalid_literal",
@@ -16329,7 +16423,7 @@ ZodError2.create = (issues) => {
16329
16423
  return error2;
16330
16424
  };
16331
16425
 
16332
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js
16426
+ // node_modules/zod/v3/locales/en.js
16333
16427
  var errorMap = (issue2, _ctx) => {
16334
16428
  let message;
16335
16429
  switch (issue2.code) {
@@ -16432,7 +16526,7 @@ var errorMap = (issue2, _ctx) => {
16432
16526
  };
16433
16527
  var en_default2 = errorMap;
16434
16528
 
16435
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js
16529
+ // node_modules/zod/v3/errors.js
16436
16530
  var overrideErrorMap = en_default2;
16437
16531
  function setErrorMap(map) {
16438
16532
  overrideErrorMap = map;
@@ -16440,7 +16534,7 @@ function setErrorMap(map) {
16440
16534
  function getErrorMap() {
16441
16535
  return overrideErrorMap;
16442
16536
  }
16443
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
16537
+ // node_modules/zod/v3/helpers/parseUtil.js
16444
16538
  var makeIssue = (params) => {
16445
16539
  const { data, path, errorMaps, issueData } = params;
16446
16540
  const fullPath = [...path, ...issueData.path || []];
@@ -16546,14 +16640,14 @@ var isAborted = (x) => x.status === "aborted";
16546
16640
  var isDirty = (x) => x.status === "dirty";
16547
16641
  var isValid = (x) => x.status === "valid";
16548
16642
  var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
16549
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js
16643
+ // node_modules/zod/v3/helpers/errorUtil.js
16550
16644
  var errorUtil;
16551
16645
  (function(errorUtil2) {
16552
16646
  errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
16553
16647
  errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
16554
16648
  })(errorUtil || (errorUtil = {}));
16555
16649
 
16556
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
16650
+ // node_modules/zod/v3/types.js
16557
16651
  class ParseInputLazyPath {
16558
16652
  constructor(parent, value, path, key) {
16559
16653
  this._cachedPath = [];
@@ -19940,7 +20034,7 @@ var coerce = {
19940
20034
  date: (arg) => ZodDate.create({ ...arg, coerce: true })
19941
20035
  };
19942
20036
  var NEVER2 = INVALID;
19943
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/mini/schemas.js
20037
+ // node_modules/zod/v4/mini/schemas.js
19944
20038
  var ZodMiniType = /* @__PURE__ */ $constructor("ZodMiniType", (inst, def) => {
19945
20039
  if (!inst._zod)
19946
20040
  throw new Error("Uninitialized schema in ZodMiniType.");
@@ -27071,17 +27165,19 @@ class ApiStore {
27071
27165
  const res = await this.client.list("tags");
27072
27166
  return pick2(res, "tags") ?? [];
27073
27167
  }
27074
- async getTagByName() {
27075
- return unavailable("getTagByName");
27168
+ async getTagByName(name) {
27169
+ const res = await this.client.list("tags", { query: { name } });
27170
+ const tags = pick2(res, "tags") ?? [];
27171
+ return tags.find((tag) => tag?.name === name) ?? null;
27076
27172
  }
27077
27173
  async deleteTag(id) {
27078
27174
  await this.client.delete("tags", id);
27079
27175
  }
27080
- async addTagToContact() {
27081
- return unavailable("addTagToContact");
27176
+ async addTagToContact(contactId, tagId) {
27177
+ await this.client.transport.put(`/contacts/${this.enc(contactId)}/tags/${this.enc(tagId)}`);
27082
27178
  }
27083
- async removeTagFromContact() {
27084
- return unavailable("removeTagFromContact");
27179
+ async removeTagFromContact(contactId, tagId) {
27180
+ await this.del(`/contacts/${this.enc(contactId)}/tags/${this.enc(tagId)}`);
27085
27181
  }
27086
27182
  async addTagToCompany() {
27087
27183
  return unavailable("addTagToCompany");
@@ -31017,8 +31113,13 @@ async function main() {
31017
31113
  await buildServer().connect(transport);
31018
31114
  console.error("Contacts MCP server running on stdio");
31019
31115
  }
31020
- var isDirectRun = import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("mcp/index.ts") || process.argv[1]?.endsWith("mcp/index.js");
31021
- if (isDirectRun) {
31116
+ function isDirectMcpEntry(entry = process.argv[1]) {
31117
+ if (!entry)
31118
+ return false;
31119
+ const normalized = entry.replaceAll("\\", "/");
31120
+ return normalized.endsWith("/mcp/index.ts") || normalized.endsWith("/mcp/index.js");
31121
+ }
31122
+ if (isDirectMcpEntry()) {
31022
31123
  main().catch((err2) => {
31023
31124
  console.error("Fatal error:", err2);
31024
31125
  process.exit(1);
@@ -31440,6 +31541,10 @@ class ContactsPgStore {
31440
31541
  const row = await this.client.get(`SELECT * FROM tags WHERE id = $1`, [id]);
31441
31542
  return row ? mapTag(row) : null;
31442
31543
  }
31544
+ async getTagByName(name) {
31545
+ const row = await this.client.get(`SELECT * FROM tags WHERE name = $1`, [name]);
31546
+ return row ? mapTag(row) : null;
31547
+ }
31443
31548
  async createTag(input) {
31444
31549
  const id = uuid3();
31445
31550
  const row = await this.client.get(`INSERT INTO tags (id, name, color, description) VALUES ($1,$2,$3,$4) RETURNING *`, [id, input.name, input.color ?? "#6366f1", input.description ?? null]);
@@ -31463,6 +31568,14 @@ class ContactsPgStore {
31463
31568
  const result = await this.client.query(`DELETE FROM tags WHERE id = $1`, [id]);
31464
31569
  return result.rowCount > 0;
31465
31570
  }
31571
+ async addTagToContact(contactId, tagId) {
31572
+ await this.client.execute(`INSERT INTO contact_tags (contact_id, tag_id) VALUES ($1, $2)
31573
+ ON CONFLICT (contact_id, tag_id) DO NOTHING`, [contactId, tagId]);
31574
+ }
31575
+ async removeTagFromContact(contactId, tagId) {
31576
+ const result = await this.client.query(`DELETE FROM contact_tags WHERE contact_id = $1 AND tag_id = $2`, [contactId, tagId]);
31577
+ return result.rowCount > 0;
31578
+ }
31466
31579
  async stats() {
31467
31580
  const row = await this.client.get(`SELECT
31468
31581
  (SELECT COUNT(*) FROM contacts)::text AS contacts,
@@ -32820,7 +32933,12 @@ async function handleV1Request(req, url) {
32820
32933
  }
32821
32934
  await ensureCloudSchemaBestEffort();
32822
32935
  const store = getContactsPgStore(getCloudClient());
32823
- const segments = path.split("/").filter(Boolean);
32936
+ let segments;
32937
+ try {
32938
+ segments = path.split("/").filter(Boolean).map((segment) => decodeURIComponent(segment));
32939
+ } catch {
32940
+ return error2(400, "invalid URL path encoding");
32941
+ }
32824
32942
  const resource = segments[1];
32825
32943
  const id = segments[2];
32826
32944
  const sub = segments[3];
@@ -32831,6 +32949,20 @@ async function handleV1Request(req, url) {
32831
32949
  };
32832
32950
  try {
32833
32951
  if (resource === "contacts" && id && sub) {
32952
+ if (sub === "tags") {
32953
+ const tagId = segments[4];
32954
+ if (!tagId)
32955
+ return error2(400, "tag id required");
32956
+ if (method === "PUT") {
32957
+ await store.addTagToContact(id, tagId);
32958
+ return json5({ attached: true, contact_id: id, tag_id: tagId });
32959
+ }
32960
+ if (method === "DELETE") {
32961
+ const removed = await store.removeTagFromContact(id, tagId);
32962
+ return json5({ removed, contact_id: id, tag_id: tagId });
32963
+ }
32964
+ return error2(405, `method ${method} not allowed on /v1/contacts/:contact_id/tags/:tag_id`);
32965
+ }
32834
32966
  if (method === "GET" && sub === "timeline")
32835
32967
  return json5({ timeline: await store.getContactTimeline(id, qn("limit") ?? 50) });
32836
32968
  if (method === "GET" && sub === "brief")
@@ -32970,7 +33102,9 @@ async function handleV1Request(req, url) {
32970
33102
  if (resource === "tags") {
32971
33103
  if (!id) {
32972
33104
  if (method === "GET") {
32973
- const tags = await store.listTags();
33105
+ const name = url.searchParams.get("name");
33106
+ const tag = name !== null ? await store.getTagByName(name) : null;
33107
+ const tags = name !== null ? tag ? [tag] : [] : await store.listTags();
32974
33108
  return json5({ tags, count: tags.length });
32975
33109
  }
32976
33110
  if (method === "POST") {
@@ -33815,6 +33949,7 @@ function buildV1OpenApiDocument(version2 = getPackageVersion()) {
33815
33949
  get: {
33816
33950
  operationId: "listTags",
33817
33951
  summary: "List tags",
33952
+ parameters: [{ name: "name", in: "query", schema: { type: "string" } }],
33818
33953
  responses: objResponse({
33819
33954
  tags: { type: "array", items: { $ref: "#/components/schemas/Tag" } },
33820
33955
  count: { type: "number" }
@@ -33862,6 +33997,34 @@ function buildV1OpenApiDocument(version2 = getPackageVersion()) {
33862
33997
  responses: objResponse({ deleted: { type: "boolean" }, id: { type: "string" } })
33863
33998
  }
33864
33999
  },
34000
+ "/v1/contacts/{contact_id}/tags/{tag_id}": {
34001
+ put: {
34002
+ operationId: "addTagToContact",
34003
+ summary: "Attach a tag to a contact idempotently",
34004
+ parameters: [
34005
+ { name: "contact_id", in: "path", required: true, schema: { type: "string" } },
34006
+ { name: "tag_id", in: "path", required: true, schema: { type: "string" } }
34007
+ ],
34008
+ responses: objResponse({
34009
+ attached: { type: "boolean" },
34010
+ contact_id: { type: "string" },
34011
+ tag_id: { type: "string" }
34012
+ })
34013
+ },
34014
+ delete: {
34015
+ operationId: "removeTagFromContact",
34016
+ summary: "Remove a tag from a contact",
34017
+ parameters: [
34018
+ { name: "contact_id", in: "path", required: true, schema: { type: "string" } },
34019
+ { name: "tag_id", in: "path", required: true, schema: { type: "string" } }
34020
+ ],
34021
+ responses: objResponse({
34022
+ removed: { type: "boolean" },
34023
+ contact_id: { type: "string" },
34024
+ tag_id: { type: "string" }
34025
+ })
34026
+ }
34027
+ },
33865
34028
  "/v1/stats": {
33866
34029
  get: {
33867
34030
  operationId: "getStats",
@@ -34251,7 +34414,7 @@ function createContactsRequestHandler(options = {}) {
34251
34414
  const localRequest = Boolean(options.trustedLoopbackBind);
34252
34415
  const corsHeaders = {
34253
34416
  "Access-Control-Allow-Origin": localRequest ? "*" : "null",
34254
- "Access-Control-Allow-Methods": "GET, POST, PATCH, DELETE, OPTIONS",
34417
+ "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
34255
34418
  "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Contacts-Token, x-api-key"
34256
34419
  };
34257
34420
  if (req.method === "OPTIONS") {