@gzoo/cortex 0.5.13 → 0.5.15

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/cortex.mjs CHANGED
@@ -1,13 +1,36 @@
1
1
  #!/usr/bin/env node
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
8
  var __esm = (fn, res) => function __init() {
5
9
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
10
  };
11
+ var __commonJS = (cb, mod) => function __require() {
12
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
13
+ };
7
14
  var __export = (target, all) => {
8
15
  for (var name in all)
9
16
  __defProp(target, name, { get: all[name], enumerable: true });
10
17
  };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
27
+ // If the importer is in node compatibility mode or this is not an ESM
28
+ // file that has been converted to a CommonJS file using a Babel-
29
+ // compatible transform (i.e. "__esModule" has not been set), then set
30
+ // "default" to the CommonJS "module.exports" for node compatibility.
31
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
32
+ mod
33
+ ));
11
34
 
12
35
  // packages/core/dist/types/llm.js
13
36
  var LLMTask;
@@ -4931,249 +4954,2682 @@ var init_dist4 = __esm({
4931
4954
  }
4932
4955
  });
4933
4956
 
4934
- // packages/server/dist/routes/entities.js
4935
- import { Router as Router2 } from "express";
4936
- function createEntityRoutes(bundle) {
4937
- const router = Router2();
4938
- const { store } = bundle;
4939
- router.get("/", async (req, res) => {
4940
- try {
4941
- const { type, project, search, limit: rawLimit = "50", offset: rawOffset = "0", status = "active" } = req.query;
4942
- const parsedLimit = Math.max(1, Math.min(Number(rawLimit) || 50, 500));
4943
- const parsedOffset = Math.max(0, Number(rawOffset) || 0);
4944
- if (search && typeof search === "string") {
4945
- const results = await store.searchEntities(search, parsedLimit);
4946
- res.json({ success: true, data: results, meta: { total: results.length, limit: parsedLimit, offset: 0 } });
4947
- return;
4957
+ // node_modules/ip-address/dist/common.js
4958
+ var require_common = __commonJS({
4959
+ "node_modules/ip-address/dist/common.js"(exports) {
4960
+ "use strict";
4961
+ Object.defineProperty(exports, "__esModule", { value: true });
4962
+ exports.isInSubnet = isInSubnet;
4963
+ exports.isCorrect = isCorrect;
4964
+ exports.numberToPaddedHex = numberToPaddedHex;
4965
+ exports.stringToPaddedHex = stringToPaddedHex;
4966
+ exports.testBit = testBit;
4967
+ function isInSubnet(address) {
4968
+ if (this.subnetMask < address.subnetMask) {
4969
+ return false;
4948
4970
  }
4949
- const entities = await store.findEntities({
4950
- type,
4951
- projectId: project,
4952
- status,
4953
- limit: parsedLimit,
4954
- offset: parsedOffset
4955
- });
4956
- res.json({ success: true, data: entities, meta: { limit: parsedLimit, offset: parsedOffset } });
4957
- } catch (err) {
4958
- logger26.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
4959
- res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
4960
- }
4961
- });
4962
- router.get("/:id", async (req, res) => {
4963
- try {
4964
- const entity = await store.getEntity(req.params.id);
4965
- if (!entity) {
4966
- res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "Entity not found" } });
4967
- return;
4971
+ if (this.mask(address.subnetMask) === address.mask()) {
4972
+ return true;
4968
4973
  }
4969
- res.json({ success: true, data: entity });
4970
- } catch (err) {
4971
- logger26.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
4972
- res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
4974
+ return false;
4973
4975
  }
4974
- });
4975
- router.get("/:id/relationships", async (req, res) => {
4976
- try {
4977
- const { direction = "both" } = req.query;
4978
- const relationships = await store.getRelationshipsForEntity(req.params.id, direction);
4979
- res.json({ success: true, data: relationships });
4980
- } catch (err) {
4981
- logger26.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
4982
- res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
4976
+ function isCorrect(defaultBits) {
4977
+ return function() {
4978
+ if (this.addressMinusSuffix !== this.correctForm()) {
4979
+ return false;
4980
+ }
4981
+ if (this.subnetMask === defaultBits && !this.parsedSubnet) {
4982
+ return true;
4983
+ }
4984
+ return this.parsedSubnet === String(this.subnetMask);
4985
+ };
4983
4986
  }
4984
- });
4985
- return router;
4986
- }
4987
- var logger26;
4988
- var init_entities = __esm({
4989
- "packages/server/dist/routes/entities.js"() {
4990
- "use strict";
4991
- init_dist();
4992
- logger26 = createLogger("server:entities");
4993
- }
4994
- });
4995
-
4996
- // packages/server/dist/routes/relationships.js
4997
- import { Router as Router3 } from "express";
4998
- function createRelationshipRoutes(bundle) {
4999
- const router = Router3();
5000
- const { store } = bundle;
5001
- router.get("/", async (req, res) => {
5002
- try {
5003
- const { type, sourceId, targetId, limit: rawLimit = "100" } = req.query;
5004
- const parsedLimit = Math.max(1, Math.min(Number(rawLimit) || 100, 500));
5005
- if (sourceId && typeof sourceId === "string") {
5006
- const rels = await store.getRelationshipsForEntity(sourceId, "out");
5007
- const filtered = type ? rels.filter((r) => r.type === type) : rels;
5008
- res.json({ success: true, data: filtered.slice(0, parsedLimit) });
5009
- return;
5010
- }
5011
- if (targetId && typeof targetId === "string") {
5012
- const rels = await store.getRelationshipsForEntity(targetId, "in");
5013
- const filtered = type ? rels.filter((r) => r.type === type) : rels;
5014
- res.json({ success: true, data: filtered.slice(0, parsedLimit) });
5015
- return;
5016
- }
5017
- res.json({
5018
- success: true,
5019
- data: [],
5020
- meta: { message: "Provide sourceId or targetId to query relationships" }
5021
- });
5022
- } catch (err) {
5023
- logger27.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
5024
- res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
4987
+ function numberToPaddedHex(number) {
4988
+ return number.toString(16).padStart(2, "0");
5025
4989
  }
5026
- });
5027
- router.get("/:id", async (req, res) => {
5028
- try {
5029
- const rel = await store.getRelationship(req.params.id);
5030
- if (!rel) {
5031
- res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "Relationship not found" } });
5032
- return;
4990
+ function stringToPaddedHex(numberString) {
4991
+ return numberToPaddedHex(parseInt(numberString, 10));
4992
+ }
4993
+ function testBit(binaryValue, position) {
4994
+ const { length } = binaryValue;
4995
+ if (position > length) {
4996
+ return false;
5033
4997
  }
5034
- res.json({ success: true, data: rel });
5035
- } catch (err) {
5036
- logger27.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
5037
- res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
4998
+ const positionInString = length - position;
4999
+ return binaryValue.substring(positionInString, positionInString + 1) === "1";
5038
5000
  }
5039
- });
5040
- return router;
5041
- }
5042
- var logger27;
5043
- var init_relationships = __esm({
5044
- "packages/server/dist/routes/relationships.js"() {
5001
+ }
5002
+ });
5003
+
5004
+ // node_modules/ip-address/dist/v4/constants.js
5005
+ var require_constants = __commonJS({
5006
+ "node_modules/ip-address/dist/v4/constants.js"(exports) {
5045
5007
  "use strict";
5046
- init_dist();
5047
- logger27 = createLogger("server:relationships");
5008
+ Object.defineProperty(exports, "__esModule", { value: true });
5009
+ exports.RE_SUBNET_STRING = exports.RE_ADDRESS = exports.GROUPS = exports.BITS = void 0;
5010
+ exports.BITS = 32;
5011
+ exports.GROUPS = 4;
5012
+ exports.RE_ADDRESS = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/g;
5013
+ exports.RE_SUBNET_STRING = /\/\d{1,2}$/;
5048
5014
  }
5049
5015
  });
5050
5016
 
5051
- // packages/server/dist/routes/projects.js
5052
- import { Router as Router4 } from "express";
5053
- function createProjectRoutes(bundle) {
5054
- const router = Router4();
5055
- const { store } = bundle;
5056
- router.get("/", async (_req, res) => {
5057
- try {
5058
- const projects = await store.listProjects();
5059
- res.json({ success: true, data: projects });
5060
- } catch (err) {
5061
- logger28.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
5062
- res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
5063
- }
5064
- });
5065
- router.get("/:id", async (req, res) => {
5066
- try {
5067
- const project = await store.getProject(req.params.id);
5068
- if (!project) {
5069
- res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "Project not found" } });
5070
- return;
5071
- }
5072
- res.json({ success: true, data: project });
5073
- } catch (err) {
5074
- logger28.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
5075
- res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
5076
- }
5077
- });
5078
- return router;
5079
- }
5080
- var logger28;
5081
- var init_projects = __esm({
5082
- "packages/server/dist/routes/projects.js"() {
5017
+ // node_modules/ip-address/dist/address-error.js
5018
+ var require_address_error = __commonJS({
5019
+ "node_modules/ip-address/dist/address-error.js"(exports) {
5083
5020
  "use strict";
5084
- init_dist();
5085
- logger28 = createLogger("server:projects");
5021
+ Object.defineProperty(exports, "__esModule", { value: true });
5022
+ exports.AddressError = void 0;
5023
+ var AddressError = class extends Error {
5024
+ constructor(message, parseMessage) {
5025
+ super(message);
5026
+ this.name = "AddressError";
5027
+ this.parseMessage = parseMessage;
5028
+ }
5029
+ };
5030
+ exports.AddressError = AddressError;
5086
5031
  }
5087
5032
  });
5088
5033
 
5089
- // packages/server/dist/routes/query.js
5090
- import { Router as Router5 } from "express";
5091
- function createQueryRoutes(bundle) {
5092
- const router = Router5();
5093
- const { store, queryEngine, router: llmRouter } = bundle;
5094
- router.post("/", async (req, res) => {
5095
- try {
5096
- const { query, projectId, stream = false } = req.body;
5097
- if (!query || typeof query !== "string") {
5098
- res.status(400).json({ success: false, error: { code: "BAD_REQUEST", message: "query is required" } });
5099
- return;
5034
+ // node_modules/ip-address/dist/ipv4.js
5035
+ var require_ipv4 = __commonJS({
5036
+ "node_modules/ip-address/dist/ipv4.js"(exports) {
5037
+ "use strict";
5038
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
5039
+ if (k2 === void 0) k2 = k;
5040
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5041
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
5042
+ desc = { enumerable: true, get: function() {
5043
+ return m[k];
5044
+ } };
5045
+ }
5046
+ Object.defineProperty(o, k2, desc);
5047
+ }) : (function(o, m, k, k2) {
5048
+ if (k2 === void 0) k2 = k;
5049
+ o[k2] = m[k];
5050
+ }));
5051
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
5052
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
5053
+ }) : function(o, v) {
5054
+ o["default"] = v;
5055
+ });
5056
+ var __importStar = exports && exports.__importStar || function(mod) {
5057
+ if (mod && mod.__esModule) return mod;
5058
+ var result = {};
5059
+ if (mod != null) {
5060
+ for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
5061
+ }
5062
+ __setModuleDefault(result, mod);
5063
+ return result;
5064
+ };
5065
+ Object.defineProperty(exports, "__esModule", { value: true });
5066
+ exports.Address4 = void 0;
5067
+ var common = __importStar(require_common());
5068
+ var constants = __importStar(require_constants());
5069
+ var address_error_1 = require_address_error();
5070
+ var Address4 = class _Address4 {
5071
+ constructor(address) {
5072
+ this.groups = constants.GROUPS;
5073
+ this.parsedAddress = [];
5074
+ this.parsedSubnet = "";
5075
+ this.subnet = "/32";
5076
+ this.subnetMask = 32;
5077
+ this.v4 = true;
5078
+ this.isCorrect = common.isCorrect(constants.BITS);
5079
+ this.isInSubnet = common.isInSubnet;
5080
+ this.address = address;
5081
+ const subnet = constants.RE_SUBNET_STRING.exec(address);
5082
+ if (subnet) {
5083
+ this.parsedSubnet = subnet[0].replace("/", "");
5084
+ this.subnetMask = parseInt(this.parsedSubnet, 10);
5085
+ this.subnet = `/${this.subnetMask}`;
5086
+ if (this.subnetMask < 0 || this.subnetMask > constants.BITS) {
5087
+ throw new address_error_1.AddressError("Invalid subnet mask.");
5088
+ }
5089
+ address = address.replace(constants.RE_SUBNET_STRING, "");
5090
+ }
5091
+ this.addressMinusSuffix = address;
5092
+ this.parsedAddress = this.parse(address);
5100
5093
  }
5101
- if (projectId && typeof projectId === "string") {
5102
- const project = await store.getProject(projectId);
5103
- if (!project) {
5104
- res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "Project not found" } });
5105
- return;
5094
+ static isValid(address) {
5095
+ try {
5096
+ new _Address4(address);
5097
+ return true;
5098
+ } catch (e) {
5099
+ return false;
5106
5100
  }
5107
5101
  }
5108
- const context = await queryEngine.assembleContext(query, void 0, projectId);
5109
- if (stream) {
5110
- res.setHeader("Content-Type", "text/event-stream");
5111
- res.setHeader("Cache-Control", "no-cache");
5112
- res.setHeader("Connection", "keep-alive");
5113
- const systemPrompt8 = buildQuerySystemPrompt(context);
5114
- const gen = llmRouter.stream({
5115
- systemPrompt: systemPrompt8,
5116
- userPrompt: query,
5117
- promptId: "conversational_query",
5118
- promptVersion: "1.0",
5119
- task: LLMTask.CONVERSATIONAL_QUERY,
5120
- modelPreference: "primary",
5121
- temperature: 0.7
5122
- });
5123
- for await (const chunk of gen) {
5124
- res.write(`data: ${JSON.stringify({ type: "chunk", content: chunk })}
5125
-
5126
- `);
5102
+ /*
5103
+ * Parses a v4 address
5104
+ */
5105
+ parse(address) {
5106
+ const groups = address.split(".");
5107
+ if (!address.match(constants.RE_ADDRESS)) {
5108
+ throw new address_error_1.AddressError("Invalid IPv4 address.");
5127
5109
  }
5128
- res.write(`data: ${JSON.stringify({ type: "sources", entities: context.entities.slice(0, 10) })}
5129
-
5130
- `);
5131
- res.write(`data: ${JSON.stringify({ type: "complete" })}
5132
-
5133
- `);
5134
- res.end();
5135
- return;
5110
+ return groups;
5136
5111
  }
5137
- const systemPrompt7 = buildQuerySystemPrompt(context);
5138
- const result = await llmRouter.complete({
5139
- systemPrompt: systemPrompt7,
5140
- userPrompt: query,
5141
- promptId: "conversational_query",
5142
- promptVersion: "1.0",
5143
- task: LLMTask.CONVERSATIONAL_QUERY,
5144
- modelPreference: "primary",
5145
- temperature: 0.7
5146
- });
5147
- res.json({
5148
- success: true,
5149
- data: {
5150
- answer: result.content,
5151
- sources: context.entities.slice(0, 10),
5152
- relationships: context.relationships,
5153
- model: result.model,
5154
- tokens: { input: result.inputTokens, output: result.outputTokens }
5112
+ /**
5113
+ * Returns the correct form of an address
5114
+ * @memberof Address4
5115
+ * @instance
5116
+ * @returns {String}
5117
+ */
5118
+ correctForm() {
5119
+ return this.parsedAddress.map((part) => parseInt(part, 10)).join(".");
5120
+ }
5121
+ /**
5122
+ * Converts a hex string to an IPv4 address object
5123
+ * @memberof Address4
5124
+ * @static
5125
+ * @param {string} hex - a hex string to convert
5126
+ * @returns {Address4}
5127
+ */
5128
+ static fromHex(hex) {
5129
+ const padded = hex.replace(/:/g, "").padStart(8, "0");
5130
+ const groups = [];
5131
+ let i;
5132
+ for (i = 0; i < 8; i += 2) {
5133
+ const h = padded.slice(i, i + 2);
5134
+ groups.push(parseInt(h, 16));
5155
5135
  }
5156
- });
5157
- } catch (err) {
5158
- logger29.error("Query failed", { error: err instanceof Error ? err.message : String(err) });
5159
- res.status(500).json({ success: false, error: { code: "QUERY_FAILED", message: "Query processing failed" } });
5160
- }
5161
- });
5162
- return router;
5163
- }
5164
- function buildQuerySystemPrompt(context) {
5165
- const entityContext = context.entities.map((e, i) => `[${i + 1}] ${e.type}: ${e.name}
5166
- ${e.summary ?? e.content}`).join("\n\n");
5167
- return `You are Cortex, a knowledge graph assistant. Answer questions using ONLY the context below. Cite sources as [N].
5168
-
5169
- ## Knowledge Context
5170
- ${entityContext || "No relevant entities found."}
5171
-
5172
- ## Instructions
5173
- - Answer concisely and accurately based on the context
5174
- - Cite sources using [N] notation
5175
- - If the context doesn't contain enough information, say so
5176
- - Suggest follow-up questions the user might ask`;
5136
+ return new _Address4(groups.join("."));
5137
+ }
5138
+ /**
5139
+ * Converts an integer into a IPv4 address object
5140
+ * @memberof Address4
5141
+ * @static
5142
+ * @param {integer} integer - a number to convert
5143
+ * @returns {Address4}
5144
+ */
5145
+ static fromInteger(integer) {
5146
+ return _Address4.fromHex(integer.toString(16));
5147
+ }
5148
+ /**
5149
+ * Return an address from in-addr.arpa form
5150
+ * @memberof Address4
5151
+ * @static
5152
+ * @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address
5153
+ * @returns {Adress4}
5154
+ * @example
5155
+ * var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.)
5156
+ * address.correctForm(); // '192.0.2.42'
5157
+ */
5158
+ static fromArpa(arpaFormAddress) {
5159
+ const leader = arpaFormAddress.replace(/(\.in-addr\.arpa)?\.$/, "");
5160
+ const address = leader.split(".").reverse().join(".");
5161
+ return new _Address4(address);
5162
+ }
5163
+ /**
5164
+ * Converts an IPv4 address object to a hex string
5165
+ * @memberof Address4
5166
+ * @instance
5167
+ * @returns {String}
5168
+ */
5169
+ toHex() {
5170
+ return this.parsedAddress.map((part) => common.stringToPaddedHex(part)).join(":");
5171
+ }
5172
+ /**
5173
+ * Converts an IPv4 address object to an array of bytes
5174
+ * @memberof Address4
5175
+ * @instance
5176
+ * @returns {Array}
5177
+ */
5178
+ toArray() {
5179
+ return this.parsedAddress.map((part) => parseInt(part, 10));
5180
+ }
5181
+ /**
5182
+ * Converts an IPv4 address object to an IPv6 address group
5183
+ * @memberof Address4
5184
+ * @instance
5185
+ * @returns {String}
5186
+ */
5187
+ toGroup6() {
5188
+ const output = [];
5189
+ let i;
5190
+ for (i = 0; i < constants.GROUPS; i += 2) {
5191
+ output.push(`${common.stringToPaddedHex(this.parsedAddress[i])}${common.stringToPaddedHex(this.parsedAddress[i + 1])}`);
5192
+ }
5193
+ return output.join(":");
5194
+ }
5195
+ /**
5196
+ * Returns the address as a `bigint`
5197
+ * @memberof Address4
5198
+ * @instance
5199
+ * @returns {bigint}
5200
+ */
5201
+ bigInt() {
5202
+ return BigInt(`0x${this.parsedAddress.map((n) => common.stringToPaddedHex(n)).join("")}`);
5203
+ }
5204
+ /**
5205
+ * Helper function getting start address.
5206
+ * @memberof Address4
5207
+ * @instance
5208
+ * @returns {bigint}
5209
+ */
5210
+ _startAddress() {
5211
+ return BigInt(`0b${this.mask() + "0".repeat(constants.BITS - this.subnetMask)}`);
5212
+ }
5213
+ /**
5214
+ * The first address in the range given by this address' subnet.
5215
+ * Often referred to as the Network Address.
5216
+ * @memberof Address4
5217
+ * @instance
5218
+ * @returns {Address4}
5219
+ */
5220
+ startAddress() {
5221
+ return _Address4.fromBigInt(this._startAddress());
5222
+ }
5223
+ /**
5224
+ * The first host address in the range given by this address's subnet ie
5225
+ * the first address after the Network Address
5226
+ * @memberof Address4
5227
+ * @instance
5228
+ * @returns {Address4}
5229
+ */
5230
+ startAddressExclusive() {
5231
+ const adjust = BigInt("1");
5232
+ return _Address4.fromBigInt(this._startAddress() + adjust);
5233
+ }
5234
+ /**
5235
+ * Helper function getting end address.
5236
+ * @memberof Address4
5237
+ * @instance
5238
+ * @returns {bigint}
5239
+ */
5240
+ _endAddress() {
5241
+ return BigInt(`0b${this.mask() + "1".repeat(constants.BITS - this.subnetMask)}`);
5242
+ }
5243
+ /**
5244
+ * The last address in the range given by this address' subnet
5245
+ * Often referred to as the Broadcast
5246
+ * @memberof Address4
5247
+ * @instance
5248
+ * @returns {Address4}
5249
+ */
5250
+ endAddress() {
5251
+ return _Address4.fromBigInt(this._endAddress());
5252
+ }
5253
+ /**
5254
+ * The last host address in the range given by this address's subnet ie
5255
+ * the last address prior to the Broadcast Address
5256
+ * @memberof Address4
5257
+ * @instance
5258
+ * @returns {Address4}
5259
+ */
5260
+ endAddressExclusive() {
5261
+ const adjust = BigInt("1");
5262
+ return _Address4.fromBigInt(this._endAddress() - adjust);
5263
+ }
5264
+ /**
5265
+ * Converts a BigInt to a v4 address object
5266
+ * @memberof Address4
5267
+ * @static
5268
+ * @param {bigint} bigInt - a BigInt to convert
5269
+ * @returns {Address4}
5270
+ */
5271
+ static fromBigInt(bigInt) {
5272
+ return _Address4.fromHex(bigInt.toString(16));
5273
+ }
5274
+ /**
5275
+ * Returns the first n bits of the address, defaulting to the
5276
+ * subnet mask
5277
+ * @memberof Address4
5278
+ * @instance
5279
+ * @returns {String}
5280
+ */
5281
+ mask(mask) {
5282
+ if (mask === void 0) {
5283
+ mask = this.subnetMask;
5284
+ }
5285
+ return this.getBitsBase2(0, mask);
5286
+ }
5287
+ /**
5288
+ * Returns the bits in the given range as a base-2 string
5289
+ * @memberof Address4
5290
+ * @instance
5291
+ * @returns {string}
5292
+ */
5293
+ getBitsBase2(start, end) {
5294
+ return this.binaryZeroPad().slice(start, end);
5295
+ }
5296
+ /**
5297
+ * Return the reversed ip6.arpa form of the address
5298
+ * @memberof Address4
5299
+ * @param {Object} options
5300
+ * @param {boolean} options.omitSuffix - omit the "in-addr.arpa" suffix
5301
+ * @instance
5302
+ * @returns {String}
5303
+ */
5304
+ reverseForm(options) {
5305
+ if (!options) {
5306
+ options = {};
5307
+ }
5308
+ const reversed = this.correctForm().split(".").reverse().join(".");
5309
+ if (options.omitSuffix) {
5310
+ return reversed;
5311
+ }
5312
+ return `${reversed}.in-addr.arpa.`;
5313
+ }
5314
+ /**
5315
+ * Returns true if the given address is a multicast address
5316
+ * @memberof Address4
5317
+ * @instance
5318
+ * @returns {boolean}
5319
+ */
5320
+ isMulticast() {
5321
+ return this.isInSubnet(new _Address4("224.0.0.0/4"));
5322
+ }
5323
+ /**
5324
+ * Returns a zero-padded base-2 string representation of the address
5325
+ * @memberof Address4
5326
+ * @instance
5327
+ * @returns {string}
5328
+ */
5329
+ binaryZeroPad() {
5330
+ return this.bigInt().toString(2).padStart(constants.BITS, "0");
5331
+ }
5332
+ /**
5333
+ * Groups an IPv4 address for inclusion at the end of an IPv6 address
5334
+ * @returns {String}
5335
+ */
5336
+ groupForV6() {
5337
+ const segments = this.parsedAddress;
5338
+ return this.address.replace(constants.RE_ADDRESS, `<span class="hover-group group-v4 group-6">${segments.slice(0, 2).join(".")}</span>.<span class="hover-group group-v4 group-7">${segments.slice(2, 4).join(".")}</span>`);
5339
+ }
5340
+ };
5341
+ exports.Address4 = Address4;
5342
+ }
5343
+ });
5344
+
5345
+ // node_modules/ip-address/dist/v6/constants.js
5346
+ var require_constants2 = __commonJS({
5347
+ "node_modules/ip-address/dist/v6/constants.js"(exports) {
5348
+ "use strict";
5349
+ Object.defineProperty(exports, "__esModule", { value: true });
5350
+ exports.RE_URL_WITH_PORT = exports.RE_URL = exports.RE_ZONE_STRING = exports.RE_SUBNET_STRING = exports.RE_BAD_ADDRESS = exports.RE_BAD_CHARACTERS = exports.TYPES = exports.SCOPES = exports.GROUPS = exports.BITS = void 0;
5351
+ exports.BITS = 128;
5352
+ exports.GROUPS = 8;
5353
+ exports.SCOPES = {
5354
+ 0: "Reserved",
5355
+ 1: "Interface local",
5356
+ 2: "Link local",
5357
+ 4: "Admin local",
5358
+ 5: "Site local",
5359
+ 8: "Organization local",
5360
+ 14: "Global",
5361
+ 15: "Reserved"
5362
+ };
5363
+ exports.TYPES = {
5364
+ "ff01::1/128": "Multicast (All nodes on this interface)",
5365
+ "ff01::2/128": "Multicast (All routers on this interface)",
5366
+ "ff02::1/128": "Multicast (All nodes on this link)",
5367
+ "ff02::2/128": "Multicast (All routers on this link)",
5368
+ "ff05::2/128": "Multicast (All routers in this site)",
5369
+ "ff02::5/128": "Multicast (OSPFv3 AllSPF routers)",
5370
+ "ff02::6/128": "Multicast (OSPFv3 AllDR routers)",
5371
+ "ff02::9/128": "Multicast (RIP routers)",
5372
+ "ff02::a/128": "Multicast (EIGRP routers)",
5373
+ "ff02::d/128": "Multicast (PIM routers)",
5374
+ "ff02::16/128": "Multicast (MLDv2 reports)",
5375
+ "ff01::fb/128": "Multicast (mDNSv6)",
5376
+ "ff02::fb/128": "Multicast (mDNSv6)",
5377
+ "ff05::fb/128": "Multicast (mDNSv6)",
5378
+ "ff02::1:2/128": "Multicast (All DHCP servers and relay agents on this link)",
5379
+ "ff05::1:2/128": "Multicast (All DHCP servers and relay agents in this site)",
5380
+ "ff02::1:3/128": "Multicast (All DHCP servers on this link)",
5381
+ "ff05::1:3/128": "Multicast (All DHCP servers in this site)",
5382
+ "::/128": "Unspecified",
5383
+ "::1/128": "Loopback",
5384
+ "ff00::/8": "Multicast",
5385
+ "fe80::/10": "Link-local unicast"
5386
+ };
5387
+ exports.RE_BAD_CHARACTERS = /([^0-9a-f:/%])/gi;
5388
+ exports.RE_BAD_ADDRESS = /([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]|\/$)/gi;
5389
+ exports.RE_SUBNET_STRING = /\/\d{1,3}(?=%|$)/;
5390
+ exports.RE_ZONE_STRING = /%.*$/;
5391
+ exports.RE_URL = /^\[{0,1}([0-9a-f:]+)\]{0,1}/;
5392
+ exports.RE_URL_WITH_PORT = /\[([0-9a-f:]+)\]:([0-9]{1,5})/;
5393
+ }
5394
+ });
5395
+
5396
+ // node_modules/ip-address/dist/v6/helpers.js
5397
+ var require_helpers = __commonJS({
5398
+ "node_modules/ip-address/dist/v6/helpers.js"(exports) {
5399
+ "use strict";
5400
+ Object.defineProperty(exports, "__esModule", { value: true });
5401
+ exports.spanAllZeroes = spanAllZeroes;
5402
+ exports.spanAll = spanAll;
5403
+ exports.spanLeadingZeroes = spanLeadingZeroes;
5404
+ exports.simpleGroup = simpleGroup;
5405
+ function spanAllZeroes(s) {
5406
+ return s.replace(/(0+)/g, '<span class="zero">$1</span>');
5407
+ }
5408
+ function spanAll(s, offset = 0) {
5409
+ const letters = s.split("");
5410
+ return letters.map((n, i) => `<span class="digit value-${n} position-${i + offset}">${spanAllZeroes(n)}</span>`).join("");
5411
+ }
5412
+ function spanLeadingZeroesSimple(group) {
5413
+ return group.replace(/^(0+)/, '<span class="zero">$1</span>');
5414
+ }
5415
+ function spanLeadingZeroes(address) {
5416
+ const groups = address.split(":");
5417
+ return groups.map((g) => spanLeadingZeroesSimple(g)).join(":");
5418
+ }
5419
+ function simpleGroup(addressString, offset = 0) {
5420
+ const groups = addressString.split(":");
5421
+ return groups.map((g, i) => {
5422
+ if (/group-v4/.test(g)) {
5423
+ return g;
5424
+ }
5425
+ return `<span class="hover-group group-${i + offset}">${spanLeadingZeroesSimple(g)}</span>`;
5426
+ });
5427
+ }
5428
+ }
5429
+ });
5430
+
5431
+ // node_modules/ip-address/dist/v6/regular-expressions.js
5432
+ var require_regular_expressions = __commonJS({
5433
+ "node_modules/ip-address/dist/v6/regular-expressions.js"(exports) {
5434
+ "use strict";
5435
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
5436
+ if (k2 === void 0) k2 = k;
5437
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5438
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
5439
+ desc = { enumerable: true, get: function() {
5440
+ return m[k];
5441
+ } };
5442
+ }
5443
+ Object.defineProperty(o, k2, desc);
5444
+ }) : (function(o, m, k, k2) {
5445
+ if (k2 === void 0) k2 = k;
5446
+ o[k2] = m[k];
5447
+ }));
5448
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
5449
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
5450
+ }) : function(o, v) {
5451
+ o["default"] = v;
5452
+ });
5453
+ var __importStar = exports && exports.__importStar || function(mod) {
5454
+ if (mod && mod.__esModule) return mod;
5455
+ var result = {};
5456
+ if (mod != null) {
5457
+ for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
5458
+ }
5459
+ __setModuleDefault(result, mod);
5460
+ return result;
5461
+ };
5462
+ Object.defineProperty(exports, "__esModule", { value: true });
5463
+ exports.ADDRESS_BOUNDARY = void 0;
5464
+ exports.groupPossibilities = groupPossibilities;
5465
+ exports.padGroup = padGroup;
5466
+ exports.simpleRegularExpression = simpleRegularExpression;
5467
+ exports.possibleElisions = possibleElisions;
5468
+ var v6 = __importStar(require_constants2());
5469
+ function groupPossibilities(possibilities) {
5470
+ return `(${possibilities.join("|")})`;
5471
+ }
5472
+ function padGroup(group) {
5473
+ if (group.length < 4) {
5474
+ return `0{0,${4 - group.length}}${group}`;
5475
+ }
5476
+ return group;
5477
+ }
5478
+ exports.ADDRESS_BOUNDARY = "[^A-Fa-f0-9:]";
5479
+ function simpleRegularExpression(groups) {
5480
+ const zeroIndexes = [];
5481
+ groups.forEach((group, i) => {
5482
+ const groupInteger = parseInt(group, 16);
5483
+ if (groupInteger === 0) {
5484
+ zeroIndexes.push(i);
5485
+ }
5486
+ });
5487
+ const possibilities = zeroIndexes.map((zeroIndex) => groups.map((group, i) => {
5488
+ if (i === zeroIndex) {
5489
+ const elision = i === 0 || i === v6.GROUPS - 1 ? ":" : "";
5490
+ return groupPossibilities([padGroup(group), elision]);
5491
+ }
5492
+ return padGroup(group);
5493
+ }).join(":"));
5494
+ possibilities.push(groups.map(padGroup).join(":"));
5495
+ return groupPossibilities(possibilities);
5496
+ }
5497
+ function possibleElisions(elidedGroups, moreLeft, moreRight) {
5498
+ const left = moreLeft ? "" : ":";
5499
+ const right = moreRight ? "" : ":";
5500
+ const possibilities = [];
5501
+ if (!moreLeft && !moreRight) {
5502
+ possibilities.push("::");
5503
+ }
5504
+ if (moreLeft && moreRight) {
5505
+ possibilities.push("");
5506
+ }
5507
+ if (moreRight && !moreLeft || !moreRight && moreLeft) {
5508
+ possibilities.push(":");
5509
+ }
5510
+ possibilities.push(`${left}(:0{1,4}){1,${elidedGroups - 1}}`);
5511
+ possibilities.push(`(0{1,4}:){1,${elidedGroups - 1}}${right}`);
5512
+ possibilities.push(`(0{1,4}:){${elidedGroups - 1}}0{1,4}`);
5513
+ for (let groups = 1; groups < elidedGroups - 1; groups++) {
5514
+ for (let position = 1; position < elidedGroups - groups; position++) {
5515
+ possibilities.push(`(0{1,4}:){${position}}:(0{1,4}:){${elidedGroups - position - groups - 1}}0{1,4}`);
5516
+ }
5517
+ }
5518
+ return groupPossibilities(possibilities);
5519
+ }
5520
+ }
5521
+ });
5522
+
5523
+ // node_modules/ip-address/dist/ipv6.js
5524
+ var require_ipv6 = __commonJS({
5525
+ "node_modules/ip-address/dist/ipv6.js"(exports) {
5526
+ "use strict";
5527
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
5528
+ if (k2 === void 0) k2 = k;
5529
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5530
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
5531
+ desc = { enumerable: true, get: function() {
5532
+ return m[k];
5533
+ } };
5534
+ }
5535
+ Object.defineProperty(o, k2, desc);
5536
+ }) : (function(o, m, k, k2) {
5537
+ if (k2 === void 0) k2 = k;
5538
+ o[k2] = m[k];
5539
+ }));
5540
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
5541
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
5542
+ }) : function(o, v) {
5543
+ o["default"] = v;
5544
+ });
5545
+ var __importStar = exports && exports.__importStar || function(mod) {
5546
+ if (mod && mod.__esModule) return mod;
5547
+ var result = {};
5548
+ if (mod != null) {
5549
+ for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
5550
+ }
5551
+ __setModuleDefault(result, mod);
5552
+ return result;
5553
+ };
5554
+ Object.defineProperty(exports, "__esModule", { value: true });
5555
+ exports.Address6 = void 0;
5556
+ var common = __importStar(require_common());
5557
+ var constants4 = __importStar(require_constants());
5558
+ var constants6 = __importStar(require_constants2());
5559
+ var helpers = __importStar(require_helpers());
5560
+ var ipv4_1 = require_ipv4();
5561
+ var regular_expressions_1 = require_regular_expressions();
5562
+ var address_error_1 = require_address_error();
5563
+ var common_1 = require_common();
5564
+ function assert(condition) {
5565
+ if (!condition) {
5566
+ throw new Error("Assertion failed.");
5567
+ }
5568
+ }
5569
+ function addCommas(number) {
5570
+ const r = /(\d+)(\d{3})/;
5571
+ while (r.test(number)) {
5572
+ number = number.replace(r, "$1,$2");
5573
+ }
5574
+ return number;
5575
+ }
5576
+ function spanLeadingZeroes4(n) {
5577
+ n = n.replace(/^(0{1,})([1-9]+)$/, '<span class="parse-error">$1</span>$2');
5578
+ n = n.replace(/^(0{1,})(0)$/, '<span class="parse-error">$1</span>$2');
5579
+ return n;
5580
+ }
5581
+ function compact(address, slice) {
5582
+ const s1 = [];
5583
+ const s2 = [];
5584
+ let i;
5585
+ for (i = 0; i < address.length; i++) {
5586
+ if (i < slice[0]) {
5587
+ s1.push(address[i]);
5588
+ } else if (i > slice[1]) {
5589
+ s2.push(address[i]);
5590
+ }
5591
+ }
5592
+ return s1.concat(["compact"]).concat(s2);
5593
+ }
5594
+ function paddedHex(octet) {
5595
+ return parseInt(octet, 16).toString(16).padStart(4, "0");
5596
+ }
5597
+ function unsignByte(b) {
5598
+ return b & 255;
5599
+ }
5600
+ var Address62 = class _Address6 {
5601
+ constructor(address, optionalGroups) {
5602
+ this.addressMinusSuffix = "";
5603
+ this.parsedSubnet = "";
5604
+ this.subnet = "/128";
5605
+ this.subnetMask = 128;
5606
+ this.v4 = false;
5607
+ this.zone = "";
5608
+ this.isInSubnet = common.isInSubnet;
5609
+ this.isCorrect = common.isCorrect(constants6.BITS);
5610
+ if (optionalGroups === void 0) {
5611
+ this.groups = constants6.GROUPS;
5612
+ } else {
5613
+ this.groups = optionalGroups;
5614
+ }
5615
+ this.address = address;
5616
+ const subnet = constants6.RE_SUBNET_STRING.exec(address);
5617
+ if (subnet) {
5618
+ this.parsedSubnet = subnet[0].replace("/", "");
5619
+ this.subnetMask = parseInt(this.parsedSubnet, 10);
5620
+ this.subnet = `/${this.subnetMask}`;
5621
+ if (Number.isNaN(this.subnetMask) || this.subnetMask < 0 || this.subnetMask > constants6.BITS) {
5622
+ throw new address_error_1.AddressError("Invalid subnet mask.");
5623
+ }
5624
+ address = address.replace(constants6.RE_SUBNET_STRING, "");
5625
+ } else if (/\//.test(address)) {
5626
+ throw new address_error_1.AddressError("Invalid subnet mask.");
5627
+ }
5628
+ const zone = constants6.RE_ZONE_STRING.exec(address);
5629
+ if (zone) {
5630
+ this.zone = zone[0];
5631
+ address = address.replace(constants6.RE_ZONE_STRING, "");
5632
+ }
5633
+ this.addressMinusSuffix = address;
5634
+ this.parsedAddress = this.parse(this.addressMinusSuffix);
5635
+ }
5636
+ static isValid(address) {
5637
+ try {
5638
+ new _Address6(address);
5639
+ return true;
5640
+ } catch (e) {
5641
+ return false;
5642
+ }
5643
+ }
5644
+ /**
5645
+ * Convert a BigInt to a v6 address object
5646
+ * @memberof Address6
5647
+ * @static
5648
+ * @param {bigint} bigInt - a BigInt to convert
5649
+ * @returns {Address6}
5650
+ * @example
5651
+ * var bigInt = BigInt('1000000000000');
5652
+ * var address = Address6.fromBigInt(bigInt);
5653
+ * address.correctForm(); // '::e8:d4a5:1000'
5654
+ */
5655
+ static fromBigInt(bigInt) {
5656
+ const hex = bigInt.toString(16).padStart(32, "0");
5657
+ const groups = [];
5658
+ let i;
5659
+ for (i = 0; i < constants6.GROUPS; i++) {
5660
+ groups.push(hex.slice(i * 4, (i + 1) * 4));
5661
+ }
5662
+ return new _Address6(groups.join(":"));
5663
+ }
5664
+ /**
5665
+ * Convert a URL (with optional port number) to an address object
5666
+ * @memberof Address6
5667
+ * @static
5668
+ * @param {string} url - a URL with optional port number
5669
+ * @example
5670
+ * var addressAndPort = Address6.fromURL('http://[ffff::]:8080/foo/');
5671
+ * addressAndPort.address.correctForm(); // 'ffff::'
5672
+ * addressAndPort.port; // 8080
5673
+ */
5674
+ static fromURL(url) {
5675
+ let host;
5676
+ let port = null;
5677
+ let result;
5678
+ if (url.indexOf("[") !== -1 && url.indexOf("]:") !== -1) {
5679
+ result = constants6.RE_URL_WITH_PORT.exec(url);
5680
+ if (result === null) {
5681
+ return {
5682
+ error: "failed to parse address with port",
5683
+ address: null,
5684
+ port: null
5685
+ };
5686
+ }
5687
+ host = result[1];
5688
+ port = result[2];
5689
+ } else if (url.indexOf("/") !== -1) {
5690
+ url = url.replace(/^[a-z0-9]+:\/\//, "");
5691
+ result = constants6.RE_URL.exec(url);
5692
+ if (result === null) {
5693
+ return {
5694
+ error: "failed to parse address from URL",
5695
+ address: null,
5696
+ port: null
5697
+ };
5698
+ }
5699
+ host = result[1];
5700
+ } else {
5701
+ host = url;
5702
+ }
5703
+ if (port) {
5704
+ port = parseInt(port, 10);
5705
+ if (port < 0 || port > 65536) {
5706
+ port = null;
5707
+ }
5708
+ } else {
5709
+ port = null;
5710
+ }
5711
+ return {
5712
+ address: new _Address6(host),
5713
+ port
5714
+ };
5715
+ }
5716
+ /**
5717
+ * Create an IPv6-mapped address given an IPv4 address
5718
+ * @memberof Address6
5719
+ * @static
5720
+ * @param {string} address - An IPv4 address string
5721
+ * @returns {Address6}
5722
+ * @example
5723
+ * var address = Address6.fromAddress4('192.168.0.1');
5724
+ * address.correctForm(); // '::ffff:c0a8:1'
5725
+ * address.to4in6(); // '::ffff:192.168.0.1'
5726
+ */
5727
+ static fromAddress4(address) {
5728
+ const address4 = new ipv4_1.Address4(address);
5729
+ const mask6 = constants6.BITS - (constants4.BITS - address4.subnetMask);
5730
+ return new _Address6(`::ffff:${address4.correctForm()}/${mask6}`);
5731
+ }
5732
+ /**
5733
+ * Return an address from ip6.arpa form
5734
+ * @memberof Address6
5735
+ * @static
5736
+ * @param {string} arpaFormAddress - an 'ip6.arpa' form address
5737
+ * @returns {Adress6}
5738
+ * @example
5739
+ * var address = Address6.fromArpa(e.f.f.f.3.c.2.6.f.f.f.e.6.6.8.e.1.0.6.7.9.4.e.c.0.0.0.0.1.0.0.2.ip6.arpa.)
5740
+ * address.correctForm(); // '2001:0:ce49:7601:e866:efff:62c3:fffe'
5741
+ */
5742
+ static fromArpa(arpaFormAddress) {
5743
+ let address = arpaFormAddress.replace(/(\.ip6\.arpa)?\.$/, "");
5744
+ const semicolonAmount = 7;
5745
+ if (address.length !== 63) {
5746
+ throw new address_error_1.AddressError("Invalid 'ip6.arpa' form.");
5747
+ }
5748
+ const parts = address.split(".").reverse();
5749
+ for (let i = semicolonAmount; i > 0; i--) {
5750
+ const insertIndex = i * 4;
5751
+ parts.splice(insertIndex, 0, ":");
5752
+ }
5753
+ address = parts.join("");
5754
+ return new _Address6(address);
5755
+ }
5756
+ /**
5757
+ * Return the Microsoft UNC transcription of the address
5758
+ * @memberof Address6
5759
+ * @instance
5760
+ * @returns {String} the Microsoft UNC transcription of the address
5761
+ */
5762
+ microsoftTranscription() {
5763
+ return `${this.correctForm().replace(/:/g, "-")}.ipv6-literal.net`;
5764
+ }
5765
+ /**
5766
+ * Return the first n bits of the address, defaulting to the subnet mask
5767
+ * @memberof Address6
5768
+ * @instance
5769
+ * @param {number} [mask=subnet] - the number of bits to mask
5770
+ * @returns {String} the first n bits of the address as a string
5771
+ */
5772
+ mask(mask = this.subnetMask) {
5773
+ return this.getBitsBase2(0, mask);
5774
+ }
5775
+ /**
5776
+ * Return the number of possible subnets of a given size in the address
5777
+ * @memberof Address6
5778
+ * @instance
5779
+ * @param {number} [subnetSize=128] - the subnet size
5780
+ * @returns {String}
5781
+ */
5782
+ // TODO: probably useful to have a numeric version of this too
5783
+ possibleSubnets(subnetSize = 128) {
5784
+ const availableBits = constants6.BITS - this.subnetMask;
5785
+ const subnetBits = Math.abs(subnetSize - constants6.BITS);
5786
+ const subnetPowers = availableBits - subnetBits;
5787
+ if (subnetPowers < 0) {
5788
+ return "0";
5789
+ }
5790
+ return addCommas((BigInt("2") ** BigInt(subnetPowers)).toString(10));
5791
+ }
5792
+ /**
5793
+ * Helper function getting start address.
5794
+ * @memberof Address6
5795
+ * @instance
5796
+ * @returns {bigint}
5797
+ */
5798
+ _startAddress() {
5799
+ return BigInt(`0b${this.mask() + "0".repeat(constants6.BITS - this.subnetMask)}`);
5800
+ }
5801
+ /**
5802
+ * The first address in the range given by this address' subnet
5803
+ * Often referred to as the Network Address.
5804
+ * @memberof Address6
5805
+ * @instance
5806
+ * @returns {Address6}
5807
+ */
5808
+ startAddress() {
5809
+ return _Address6.fromBigInt(this._startAddress());
5810
+ }
5811
+ /**
5812
+ * The first host address in the range given by this address's subnet ie
5813
+ * the first address after the Network Address
5814
+ * @memberof Address6
5815
+ * @instance
5816
+ * @returns {Address6}
5817
+ */
5818
+ startAddressExclusive() {
5819
+ const adjust = BigInt("1");
5820
+ return _Address6.fromBigInt(this._startAddress() + adjust);
5821
+ }
5822
+ /**
5823
+ * Helper function getting end address.
5824
+ * @memberof Address6
5825
+ * @instance
5826
+ * @returns {bigint}
5827
+ */
5828
+ _endAddress() {
5829
+ return BigInt(`0b${this.mask() + "1".repeat(constants6.BITS - this.subnetMask)}`);
5830
+ }
5831
+ /**
5832
+ * The last address in the range given by this address' subnet
5833
+ * Often referred to as the Broadcast
5834
+ * @memberof Address6
5835
+ * @instance
5836
+ * @returns {Address6}
5837
+ */
5838
+ endAddress() {
5839
+ return _Address6.fromBigInt(this._endAddress());
5840
+ }
5841
+ /**
5842
+ * The last host address in the range given by this address's subnet ie
5843
+ * the last address prior to the Broadcast Address
5844
+ * @memberof Address6
5845
+ * @instance
5846
+ * @returns {Address6}
5847
+ */
5848
+ endAddressExclusive() {
5849
+ const adjust = BigInt("1");
5850
+ return _Address6.fromBigInt(this._endAddress() - adjust);
5851
+ }
5852
+ /**
5853
+ * Return the scope of the address
5854
+ * @memberof Address6
5855
+ * @instance
5856
+ * @returns {String}
5857
+ */
5858
+ getScope() {
5859
+ let scope = constants6.SCOPES[parseInt(this.getBits(12, 16).toString(10), 10)];
5860
+ if (this.getType() === "Global unicast" && scope !== "Link local") {
5861
+ scope = "Global";
5862
+ }
5863
+ return scope || "Unknown";
5864
+ }
5865
+ /**
5866
+ * Return the type of the address
5867
+ * @memberof Address6
5868
+ * @instance
5869
+ * @returns {String}
5870
+ */
5871
+ getType() {
5872
+ for (const subnet of Object.keys(constants6.TYPES)) {
5873
+ if (this.isInSubnet(new _Address6(subnet))) {
5874
+ return constants6.TYPES[subnet];
5875
+ }
5876
+ }
5877
+ return "Global unicast";
5878
+ }
5879
+ /**
5880
+ * Return the bits in the given range as a BigInt
5881
+ * @memberof Address6
5882
+ * @instance
5883
+ * @returns {bigint}
5884
+ */
5885
+ getBits(start, end) {
5886
+ return BigInt(`0b${this.getBitsBase2(start, end)}`);
5887
+ }
5888
+ /**
5889
+ * Return the bits in the given range as a base-2 string
5890
+ * @memberof Address6
5891
+ * @instance
5892
+ * @returns {String}
5893
+ */
5894
+ getBitsBase2(start, end) {
5895
+ return this.binaryZeroPad().slice(start, end);
5896
+ }
5897
+ /**
5898
+ * Return the bits in the given range as a base-16 string
5899
+ * @memberof Address6
5900
+ * @instance
5901
+ * @returns {String}
5902
+ */
5903
+ getBitsBase16(start, end) {
5904
+ const length = end - start;
5905
+ if (length % 4 !== 0) {
5906
+ throw new Error("Length of bits to retrieve must be divisible by four");
5907
+ }
5908
+ return this.getBits(start, end).toString(16).padStart(length / 4, "0");
5909
+ }
5910
+ /**
5911
+ * Return the bits that are set past the subnet mask length
5912
+ * @memberof Address6
5913
+ * @instance
5914
+ * @returns {String}
5915
+ */
5916
+ getBitsPastSubnet() {
5917
+ return this.getBitsBase2(this.subnetMask, constants6.BITS);
5918
+ }
5919
+ /**
5920
+ * Return the reversed ip6.arpa form of the address
5921
+ * @memberof Address6
5922
+ * @param {Object} options
5923
+ * @param {boolean} options.omitSuffix - omit the "ip6.arpa" suffix
5924
+ * @instance
5925
+ * @returns {String}
5926
+ */
5927
+ reverseForm(options) {
5928
+ if (!options) {
5929
+ options = {};
5930
+ }
5931
+ const characters = Math.floor(this.subnetMask / 4);
5932
+ const reversed = this.canonicalForm().replace(/:/g, "").split("").slice(0, characters).reverse().join(".");
5933
+ if (characters > 0) {
5934
+ if (options.omitSuffix) {
5935
+ return reversed;
5936
+ }
5937
+ return `${reversed}.ip6.arpa.`;
5938
+ }
5939
+ if (options.omitSuffix) {
5940
+ return "";
5941
+ }
5942
+ return "ip6.arpa.";
5943
+ }
5944
+ /**
5945
+ * Return the correct form of the address
5946
+ * @memberof Address6
5947
+ * @instance
5948
+ * @returns {String}
5949
+ */
5950
+ correctForm() {
5951
+ let i;
5952
+ let groups = [];
5953
+ let zeroCounter = 0;
5954
+ const zeroes = [];
5955
+ for (i = 0; i < this.parsedAddress.length; i++) {
5956
+ const value = parseInt(this.parsedAddress[i], 16);
5957
+ if (value === 0) {
5958
+ zeroCounter++;
5959
+ }
5960
+ if (value !== 0 && zeroCounter > 0) {
5961
+ if (zeroCounter > 1) {
5962
+ zeroes.push([i - zeroCounter, i - 1]);
5963
+ }
5964
+ zeroCounter = 0;
5965
+ }
5966
+ }
5967
+ if (zeroCounter > 1) {
5968
+ zeroes.push([this.parsedAddress.length - zeroCounter, this.parsedAddress.length - 1]);
5969
+ }
5970
+ const zeroLengths = zeroes.map((n) => n[1] - n[0] + 1);
5971
+ if (zeroes.length > 0) {
5972
+ const index = zeroLengths.indexOf(Math.max(...zeroLengths));
5973
+ groups = compact(this.parsedAddress, zeroes[index]);
5974
+ } else {
5975
+ groups = this.parsedAddress;
5976
+ }
5977
+ for (i = 0; i < groups.length; i++) {
5978
+ if (groups[i] !== "compact") {
5979
+ groups[i] = parseInt(groups[i], 16).toString(16);
5980
+ }
5981
+ }
5982
+ let correct = groups.join(":");
5983
+ correct = correct.replace(/^compact$/, "::");
5984
+ correct = correct.replace(/(^compact)|(compact$)/, ":");
5985
+ correct = correct.replace(/compact/, "");
5986
+ return correct;
5987
+ }
5988
+ /**
5989
+ * Return a zero-padded base-2 string representation of the address
5990
+ * @memberof Address6
5991
+ * @instance
5992
+ * @returns {String}
5993
+ * @example
5994
+ * var address = new Address6('2001:4860:4001:803::1011');
5995
+ * address.binaryZeroPad();
5996
+ * // '0010000000000001010010000110000001000000000000010000100000000011
5997
+ * // 0000000000000000000000000000000000000000000000000001000000010001'
5998
+ */
5999
+ binaryZeroPad() {
6000
+ return this.bigInt().toString(2).padStart(constants6.BITS, "0");
6001
+ }
6002
+ // TODO: Improve the semantics of this helper function
6003
+ parse4in6(address) {
6004
+ const groups = address.split(":");
6005
+ const lastGroup = groups.slice(-1)[0];
6006
+ const address4 = lastGroup.match(constants4.RE_ADDRESS);
6007
+ if (address4) {
6008
+ this.parsedAddress4 = address4[0];
6009
+ this.address4 = new ipv4_1.Address4(this.parsedAddress4);
6010
+ for (let i = 0; i < this.address4.groups; i++) {
6011
+ if (/^0[0-9]+/.test(this.address4.parsedAddress[i])) {
6012
+ throw new address_error_1.AddressError("IPv4 addresses can't have leading zeroes.", address.replace(constants4.RE_ADDRESS, this.address4.parsedAddress.map(spanLeadingZeroes4).join(".")));
6013
+ }
6014
+ }
6015
+ this.v4 = true;
6016
+ groups[groups.length - 1] = this.address4.toGroup6();
6017
+ address = groups.join(":");
6018
+ }
6019
+ return address;
6020
+ }
6021
+ // TODO: Make private?
6022
+ parse(address) {
6023
+ address = this.parse4in6(address);
6024
+ const badCharacters = address.match(constants6.RE_BAD_CHARACTERS);
6025
+ if (badCharacters) {
6026
+ throw new address_error_1.AddressError(`Bad character${badCharacters.length > 1 ? "s" : ""} detected in address: ${badCharacters.join("")}`, address.replace(constants6.RE_BAD_CHARACTERS, '<span class="parse-error">$1</span>'));
6027
+ }
6028
+ const badAddress = address.match(constants6.RE_BAD_ADDRESS);
6029
+ if (badAddress) {
6030
+ throw new address_error_1.AddressError(`Address failed regex: ${badAddress.join("")}`, address.replace(constants6.RE_BAD_ADDRESS, '<span class="parse-error">$1</span>'));
6031
+ }
6032
+ let groups = [];
6033
+ const halves = address.split("::");
6034
+ if (halves.length === 2) {
6035
+ let first = halves[0].split(":");
6036
+ let last = halves[1].split(":");
6037
+ if (first.length === 1 && first[0] === "") {
6038
+ first = [];
6039
+ }
6040
+ if (last.length === 1 && last[0] === "") {
6041
+ last = [];
6042
+ }
6043
+ const remaining = this.groups - (first.length + last.length);
6044
+ if (!remaining) {
6045
+ throw new address_error_1.AddressError("Error parsing groups");
6046
+ }
6047
+ this.elidedGroups = remaining;
6048
+ this.elisionBegin = first.length;
6049
+ this.elisionEnd = first.length + this.elidedGroups;
6050
+ groups = groups.concat(first);
6051
+ for (let i = 0; i < remaining; i++) {
6052
+ groups.push("0");
6053
+ }
6054
+ groups = groups.concat(last);
6055
+ } else if (halves.length === 1) {
6056
+ groups = address.split(":");
6057
+ this.elidedGroups = 0;
6058
+ } else {
6059
+ throw new address_error_1.AddressError("Too many :: groups found");
6060
+ }
6061
+ groups = groups.map((group) => parseInt(group, 16).toString(16));
6062
+ if (groups.length !== this.groups) {
6063
+ throw new address_error_1.AddressError("Incorrect number of groups found");
6064
+ }
6065
+ return groups;
6066
+ }
6067
+ /**
6068
+ * Return the canonical form of the address
6069
+ * @memberof Address6
6070
+ * @instance
6071
+ * @returns {String}
6072
+ */
6073
+ canonicalForm() {
6074
+ return this.parsedAddress.map(paddedHex).join(":");
6075
+ }
6076
+ /**
6077
+ * Return the decimal form of the address
6078
+ * @memberof Address6
6079
+ * @instance
6080
+ * @returns {String}
6081
+ */
6082
+ decimal() {
6083
+ return this.parsedAddress.map((n) => parseInt(n, 16).toString(10).padStart(5, "0")).join(":");
6084
+ }
6085
+ /**
6086
+ * Return the address as a BigInt
6087
+ * @memberof Address6
6088
+ * @instance
6089
+ * @returns {bigint}
6090
+ */
6091
+ bigInt() {
6092
+ return BigInt(`0x${this.parsedAddress.map(paddedHex).join("")}`);
6093
+ }
6094
+ /**
6095
+ * Return the last two groups of this address as an IPv4 address string
6096
+ * @memberof Address6
6097
+ * @instance
6098
+ * @returns {Address4}
6099
+ * @example
6100
+ * var address = new Address6('2001:4860:4001::1825:bf11');
6101
+ * address.to4().correctForm(); // '24.37.191.17'
6102
+ */
6103
+ to4() {
6104
+ const binary = this.binaryZeroPad().split("");
6105
+ return ipv4_1.Address4.fromHex(BigInt(`0b${binary.slice(96, 128).join("")}`).toString(16));
6106
+ }
6107
+ /**
6108
+ * Return the v4-in-v6 form of the address
6109
+ * @memberof Address6
6110
+ * @instance
6111
+ * @returns {String}
6112
+ */
6113
+ to4in6() {
6114
+ const address4 = this.to4();
6115
+ const address6 = new _Address6(this.parsedAddress.slice(0, 6).join(":"), 6);
6116
+ const correct = address6.correctForm();
6117
+ let infix = "";
6118
+ if (!/:$/.test(correct)) {
6119
+ infix = ":";
6120
+ }
6121
+ return correct + infix + address4.address;
6122
+ }
6123
+ /**
6124
+ * Return an object containing the Teredo properties of the address
6125
+ * @memberof Address6
6126
+ * @instance
6127
+ * @returns {Object}
6128
+ */
6129
+ inspectTeredo() {
6130
+ const prefix = this.getBitsBase16(0, 32);
6131
+ const bitsForUdpPort = this.getBits(80, 96);
6132
+ const udpPort = (bitsForUdpPort ^ BigInt("0xffff")).toString();
6133
+ const server4 = ipv4_1.Address4.fromHex(this.getBitsBase16(32, 64));
6134
+ const bitsForClient4 = this.getBits(96, 128);
6135
+ const client4 = ipv4_1.Address4.fromHex((bitsForClient4 ^ BigInt("0xffffffff")).toString(16));
6136
+ const flagsBase2 = this.getBitsBase2(64, 80);
6137
+ const coneNat = (0, common_1.testBit)(flagsBase2, 15);
6138
+ const reserved = (0, common_1.testBit)(flagsBase2, 14);
6139
+ const groupIndividual = (0, common_1.testBit)(flagsBase2, 8);
6140
+ const universalLocal = (0, common_1.testBit)(flagsBase2, 9);
6141
+ const nonce = BigInt(`0b${flagsBase2.slice(2, 6) + flagsBase2.slice(8, 16)}`).toString(10);
6142
+ return {
6143
+ prefix: `${prefix.slice(0, 4)}:${prefix.slice(4, 8)}`,
6144
+ server4: server4.address,
6145
+ client4: client4.address,
6146
+ flags: flagsBase2,
6147
+ coneNat,
6148
+ microsoft: {
6149
+ reserved,
6150
+ universalLocal,
6151
+ groupIndividual,
6152
+ nonce
6153
+ },
6154
+ udpPort
6155
+ };
6156
+ }
6157
+ /**
6158
+ * Return an object containing the 6to4 properties of the address
6159
+ * @memberof Address6
6160
+ * @instance
6161
+ * @returns {Object}
6162
+ */
6163
+ inspect6to4() {
6164
+ const prefix = this.getBitsBase16(0, 16);
6165
+ const gateway = ipv4_1.Address4.fromHex(this.getBitsBase16(16, 48));
6166
+ return {
6167
+ prefix: prefix.slice(0, 4),
6168
+ gateway: gateway.address
6169
+ };
6170
+ }
6171
+ /**
6172
+ * Return a v6 6to4 address from a v6 v4inv6 address
6173
+ * @memberof Address6
6174
+ * @instance
6175
+ * @returns {Address6}
6176
+ */
6177
+ to6to4() {
6178
+ if (!this.is4()) {
6179
+ return null;
6180
+ }
6181
+ const addr6to4 = [
6182
+ "2002",
6183
+ this.getBitsBase16(96, 112),
6184
+ this.getBitsBase16(112, 128),
6185
+ "",
6186
+ "/16"
6187
+ ].join(":");
6188
+ return new _Address6(addr6to4);
6189
+ }
6190
+ /**
6191
+ * Return a byte array
6192
+ * @memberof Address6
6193
+ * @instance
6194
+ * @returns {Array}
6195
+ */
6196
+ toByteArray() {
6197
+ const valueWithoutPadding = this.bigInt().toString(16);
6198
+ const leadingPad = "0".repeat(valueWithoutPadding.length % 2);
6199
+ const value = `${leadingPad}${valueWithoutPadding}`;
6200
+ const bytes = [];
6201
+ for (let i = 0, length = value.length; i < length; i += 2) {
6202
+ bytes.push(parseInt(value.substring(i, i + 2), 16));
6203
+ }
6204
+ return bytes;
6205
+ }
6206
+ /**
6207
+ * Return an unsigned byte array
6208
+ * @memberof Address6
6209
+ * @instance
6210
+ * @returns {Array}
6211
+ */
6212
+ toUnsignedByteArray() {
6213
+ return this.toByteArray().map(unsignByte);
6214
+ }
6215
+ /**
6216
+ * Convert a byte array to an Address6 object
6217
+ * @memberof Address6
6218
+ * @static
6219
+ * @returns {Address6}
6220
+ */
6221
+ static fromByteArray(bytes) {
6222
+ return this.fromUnsignedByteArray(bytes.map(unsignByte));
6223
+ }
6224
+ /**
6225
+ * Convert an unsigned byte array to an Address6 object
6226
+ * @memberof Address6
6227
+ * @static
6228
+ * @returns {Address6}
6229
+ */
6230
+ static fromUnsignedByteArray(bytes) {
6231
+ const BYTE_MAX = BigInt("256");
6232
+ let result = BigInt("0");
6233
+ let multiplier = BigInt("1");
6234
+ for (let i = bytes.length - 1; i >= 0; i--) {
6235
+ result += multiplier * BigInt(bytes[i].toString(10));
6236
+ multiplier *= BYTE_MAX;
6237
+ }
6238
+ return _Address6.fromBigInt(result);
6239
+ }
6240
+ /**
6241
+ * Returns true if the address is in the canonical form, false otherwise
6242
+ * @memberof Address6
6243
+ * @instance
6244
+ * @returns {boolean}
6245
+ */
6246
+ isCanonical() {
6247
+ return this.addressMinusSuffix === this.canonicalForm();
6248
+ }
6249
+ /**
6250
+ * Returns true if the address is a link local address, false otherwise
6251
+ * @memberof Address6
6252
+ * @instance
6253
+ * @returns {boolean}
6254
+ */
6255
+ isLinkLocal() {
6256
+ if (this.getBitsBase2(0, 64) === "1111111010000000000000000000000000000000000000000000000000000000") {
6257
+ return true;
6258
+ }
6259
+ return false;
6260
+ }
6261
+ /**
6262
+ * Returns true if the address is a multicast address, false otherwise
6263
+ * @memberof Address6
6264
+ * @instance
6265
+ * @returns {boolean}
6266
+ */
6267
+ isMulticast() {
6268
+ return this.getType() === "Multicast";
6269
+ }
6270
+ /**
6271
+ * Returns true if the address is a v4-in-v6 address, false otherwise
6272
+ * @memberof Address6
6273
+ * @instance
6274
+ * @returns {boolean}
6275
+ */
6276
+ is4() {
6277
+ return this.v4;
6278
+ }
6279
+ /**
6280
+ * Returns true if the address is a Teredo address, false otherwise
6281
+ * @memberof Address6
6282
+ * @instance
6283
+ * @returns {boolean}
6284
+ */
6285
+ isTeredo() {
6286
+ return this.isInSubnet(new _Address6("2001::/32"));
6287
+ }
6288
+ /**
6289
+ * Returns true if the address is a 6to4 address, false otherwise
6290
+ * @memberof Address6
6291
+ * @instance
6292
+ * @returns {boolean}
6293
+ */
6294
+ is6to4() {
6295
+ return this.isInSubnet(new _Address6("2002::/16"));
6296
+ }
6297
+ /**
6298
+ * Returns true if the address is a loopback address, false otherwise
6299
+ * @memberof Address6
6300
+ * @instance
6301
+ * @returns {boolean}
6302
+ */
6303
+ isLoopback() {
6304
+ return this.getType() === "Loopback";
6305
+ }
6306
+ // #endregion
6307
+ // #region HTML
6308
+ /**
6309
+ * @returns {String} the address in link form with a default port of 80
6310
+ */
6311
+ href(optionalPort) {
6312
+ if (optionalPort === void 0) {
6313
+ optionalPort = "";
6314
+ } else {
6315
+ optionalPort = `:${optionalPort}`;
6316
+ }
6317
+ return `http://[${this.correctForm()}]${optionalPort}/`;
6318
+ }
6319
+ /**
6320
+ * @returns {String} a link suitable for conveying the address via a URL hash
6321
+ */
6322
+ link(options) {
6323
+ if (!options) {
6324
+ options = {};
6325
+ }
6326
+ if (options.className === void 0) {
6327
+ options.className = "";
6328
+ }
6329
+ if (options.prefix === void 0) {
6330
+ options.prefix = "/#address=";
6331
+ }
6332
+ if (options.v4 === void 0) {
6333
+ options.v4 = false;
6334
+ }
6335
+ let formFunction = this.correctForm;
6336
+ if (options.v4) {
6337
+ formFunction = this.to4in6;
6338
+ }
6339
+ const form = formFunction.call(this);
6340
+ if (options.className) {
6341
+ return `<a href="${options.prefix}${form}" class="${options.className}">${form}</a>`;
6342
+ }
6343
+ return `<a href="${options.prefix}${form}">${form}</a>`;
6344
+ }
6345
+ /**
6346
+ * Groups an address
6347
+ * @returns {String}
6348
+ */
6349
+ group() {
6350
+ if (this.elidedGroups === 0) {
6351
+ return helpers.simpleGroup(this.address).join(":");
6352
+ }
6353
+ assert(typeof this.elidedGroups === "number");
6354
+ assert(typeof this.elisionBegin === "number");
6355
+ const output = [];
6356
+ const [left, right] = this.address.split("::");
6357
+ if (left.length) {
6358
+ output.push(...helpers.simpleGroup(left));
6359
+ } else {
6360
+ output.push("");
6361
+ }
6362
+ const classes = ["hover-group"];
6363
+ for (let i = this.elisionBegin; i < this.elisionBegin + this.elidedGroups; i++) {
6364
+ classes.push(`group-${i}`);
6365
+ }
6366
+ output.push(`<span class="${classes.join(" ")}"></span>`);
6367
+ if (right.length) {
6368
+ output.push(...helpers.simpleGroup(right, this.elisionEnd));
6369
+ } else {
6370
+ output.push("");
6371
+ }
6372
+ if (this.is4()) {
6373
+ assert(this.address4 instanceof ipv4_1.Address4);
6374
+ output.pop();
6375
+ output.push(this.address4.groupForV6());
6376
+ }
6377
+ return output.join(":");
6378
+ }
6379
+ // #endregion
6380
+ // #region Regular expressions
6381
+ /**
6382
+ * Generate a regular expression string that can be used to find or validate
6383
+ * all variations of this address
6384
+ * @memberof Address6
6385
+ * @instance
6386
+ * @param {boolean} substringSearch
6387
+ * @returns {string}
6388
+ */
6389
+ regularExpressionString(substringSearch = false) {
6390
+ let output = [];
6391
+ const address6 = new _Address6(this.correctForm());
6392
+ if (address6.elidedGroups === 0) {
6393
+ output.push((0, regular_expressions_1.simpleRegularExpression)(address6.parsedAddress));
6394
+ } else if (address6.elidedGroups === constants6.GROUPS) {
6395
+ output.push((0, regular_expressions_1.possibleElisions)(constants6.GROUPS));
6396
+ } else {
6397
+ const halves = address6.address.split("::");
6398
+ if (halves[0].length) {
6399
+ output.push((0, regular_expressions_1.simpleRegularExpression)(halves[0].split(":")));
6400
+ }
6401
+ assert(typeof address6.elidedGroups === "number");
6402
+ output.push((0, regular_expressions_1.possibleElisions)(address6.elidedGroups, halves[0].length !== 0, halves[1].length !== 0));
6403
+ if (halves[1].length) {
6404
+ output.push((0, regular_expressions_1.simpleRegularExpression)(halves[1].split(":")));
6405
+ }
6406
+ output = [output.join(":")];
6407
+ }
6408
+ if (!substringSearch) {
6409
+ output = [
6410
+ "(?=^|",
6411
+ regular_expressions_1.ADDRESS_BOUNDARY,
6412
+ "|[^\\w\\:])(",
6413
+ ...output,
6414
+ ")(?=[^\\w\\:]|",
6415
+ regular_expressions_1.ADDRESS_BOUNDARY,
6416
+ "|$)"
6417
+ ];
6418
+ }
6419
+ return output.join("");
6420
+ }
6421
+ /**
6422
+ * Generate a regular expression that can be used to find or validate all
6423
+ * variations of this address.
6424
+ * @memberof Address6
6425
+ * @instance
6426
+ * @param {boolean} substringSearch
6427
+ * @returns {RegExp}
6428
+ */
6429
+ regularExpression(substringSearch = false) {
6430
+ return new RegExp(this.regularExpressionString(substringSearch), "i");
6431
+ }
6432
+ };
6433
+ exports.Address6 = Address62;
6434
+ }
6435
+ });
6436
+
6437
+ // node_modules/ip-address/dist/ip-address.js
6438
+ var require_ip_address = __commonJS({
6439
+ "node_modules/ip-address/dist/ip-address.js"(exports) {
6440
+ "use strict";
6441
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
6442
+ if (k2 === void 0) k2 = k;
6443
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6444
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6445
+ desc = { enumerable: true, get: function() {
6446
+ return m[k];
6447
+ } };
6448
+ }
6449
+ Object.defineProperty(o, k2, desc);
6450
+ }) : (function(o, m, k, k2) {
6451
+ if (k2 === void 0) k2 = k;
6452
+ o[k2] = m[k];
6453
+ }));
6454
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
6455
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
6456
+ }) : function(o, v) {
6457
+ o["default"] = v;
6458
+ });
6459
+ var __importStar = exports && exports.__importStar || function(mod) {
6460
+ if (mod && mod.__esModule) return mod;
6461
+ var result = {};
6462
+ if (mod != null) {
6463
+ for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
6464
+ }
6465
+ __setModuleDefault(result, mod);
6466
+ return result;
6467
+ };
6468
+ Object.defineProperty(exports, "__esModule", { value: true });
6469
+ exports.v6 = exports.AddressError = exports.Address6 = exports.Address4 = void 0;
6470
+ var ipv4_1 = require_ipv4();
6471
+ Object.defineProperty(exports, "Address4", { enumerable: true, get: function() {
6472
+ return ipv4_1.Address4;
6473
+ } });
6474
+ var ipv6_1 = require_ipv6();
6475
+ Object.defineProperty(exports, "Address6", { enumerable: true, get: function() {
6476
+ return ipv6_1.Address6;
6477
+ } });
6478
+ var address_error_1 = require_address_error();
6479
+ Object.defineProperty(exports, "AddressError", { enumerable: true, get: function() {
6480
+ return address_error_1.AddressError;
6481
+ } });
6482
+ var helpers = __importStar(require_helpers());
6483
+ exports.v6 = { helpers };
6484
+ }
6485
+ });
6486
+
6487
+ // node_modules/express-rate-limit/dist/index.mjs
6488
+ import { isIPv6 } from "node:net";
6489
+ import { isIPv6 as isIPv62 } from "node:net";
6490
+ import { Buffer as Buffer2 } from "node:buffer";
6491
+ import { createHash as createHash3 } from "node:crypto";
6492
+ import { isIP } from "node:net";
6493
+ function ipKeyGenerator(ip, ipv6Subnet = 56) {
6494
+ if (ipv6Subnet && isIPv6(ip)) {
6495
+ return `${new import_ip_address.Address6(`${ip}/${ipv6Subnet}`).startAddress().correctForm()}/${ipv6Subnet}`;
6496
+ }
6497
+ return ip;
6498
+ }
6499
+ var import_ip_address, MemoryStore, SUPPORTED_DRAFT_VERSIONS, getResetSeconds, getPartitionKey, setLegacyHeaders, setDraft6Headers, setDraft7Headers, setDraft8Headers, setRetryAfterHeader, omitUndefinedProperties, ValidationError, ChangeWarning, usedStores, singleCountKeys, validations, getValidations, isLegacyStore, promisifyStore, getOptionsFromConfig, parseOptions, handleAsyncErrors, rateLimit, rate_limit_default;
6500
+ var init_dist5 = __esm({
6501
+ "node_modules/express-rate-limit/dist/index.mjs"() {
6502
+ import_ip_address = __toESM(require_ip_address(), 1);
6503
+ MemoryStore = class {
6504
+ constructor(validations2) {
6505
+ this.validations = validations2;
6506
+ this.previous = /* @__PURE__ */ new Map();
6507
+ this.current = /* @__PURE__ */ new Map();
6508
+ this.localKeys = true;
6509
+ }
6510
+ /**
6511
+ * Method that initializes the store.
6512
+ *
6513
+ * @param options {Options} - The options used to setup the middleware.
6514
+ */
6515
+ init(options) {
6516
+ this.windowMs = options.windowMs;
6517
+ this.validations?.windowMs(this.windowMs);
6518
+ if (this.interval) clearInterval(this.interval);
6519
+ this.interval = setInterval(() => {
6520
+ this.clearExpired();
6521
+ }, this.windowMs);
6522
+ this.interval.unref?.();
6523
+ }
6524
+ /**
6525
+ * Method to fetch a client's hit count and reset time.
6526
+ *
6527
+ * @param key {string} - The identifier for a client.
6528
+ *
6529
+ * @returns {ClientRateLimitInfo | undefined} - The number of hits and reset time for that client.
6530
+ *
6531
+ * @public
6532
+ */
6533
+ async get(key) {
6534
+ return this.current.get(key) ?? this.previous.get(key);
6535
+ }
6536
+ /**
6537
+ * Method to increment a client's hit counter.
6538
+ *
6539
+ * @param key {string} - The identifier for a client.
6540
+ *
6541
+ * @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.
6542
+ *
6543
+ * @public
6544
+ */
6545
+ async increment(key) {
6546
+ const client = this.getClient(key);
6547
+ const now2 = Date.now();
6548
+ if (client.resetTime.getTime() <= now2) {
6549
+ this.resetClient(client, now2);
6550
+ }
6551
+ client.totalHits++;
6552
+ return client;
6553
+ }
6554
+ /**
6555
+ * Method to decrement a client's hit counter.
6556
+ *
6557
+ * @param key {string} - The identifier for a client.
6558
+ *
6559
+ * @public
6560
+ */
6561
+ async decrement(key) {
6562
+ const client = this.getClient(key);
6563
+ if (client.totalHits > 0) client.totalHits--;
6564
+ }
6565
+ /**
6566
+ * Method to reset a client's hit counter.
6567
+ *
6568
+ * @param key {string} - The identifier for a client.
6569
+ *
6570
+ * @public
6571
+ */
6572
+ async resetKey(key) {
6573
+ this.current.delete(key);
6574
+ this.previous.delete(key);
6575
+ }
6576
+ /**
6577
+ * Method to reset everyone's hit counter.
6578
+ *
6579
+ * @public
6580
+ */
6581
+ async resetAll() {
6582
+ this.current.clear();
6583
+ this.previous.clear();
6584
+ }
6585
+ /**
6586
+ * Method to stop the timer (if currently running) and prevent any memory
6587
+ * leaks.
6588
+ *
6589
+ * @public
6590
+ */
6591
+ shutdown() {
6592
+ clearInterval(this.interval);
6593
+ void this.resetAll();
6594
+ }
6595
+ /**
6596
+ * Recycles a client by setting its hit count to zero, and reset time to
6597
+ * `windowMs` milliseconds from now.
6598
+ *
6599
+ * NOT to be confused with `#resetKey()`, which removes a client from both the
6600
+ * `current` and `previous` maps.
6601
+ *
6602
+ * @param client {Client} - The client to recycle.
6603
+ * @param now {number} - The current time, to which the `windowMs` is added to get the `resetTime` for the client.
6604
+ *
6605
+ * @return {Client} - The modified client that was passed in, to allow for chaining.
6606
+ */
6607
+ resetClient(client, now2 = Date.now()) {
6608
+ client.totalHits = 0;
6609
+ client.resetTime.setTime(now2 + this.windowMs);
6610
+ return client;
6611
+ }
6612
+ /**
6613
+ * Retrieves or creates a client, given a key. Also ensures that the client being
6614
+ * returned is in the `current` map.
6615
+ *
6616
+ * @param key {string} - The key under which the client is (or is to be) stored.
6617
+ *
6618
+ * @returns {Client} - The requested client.
6619
+ */
6620
+ getClient(key) {
6621
+ if (this.current.has(key)) return this.current.get(key);
6622
+ let client;
6623
+ if (this.previous.has(key)) {
6624
+ client = this.previous.get(key);
6625
+ this.previous.delete(key);
6626
+ } else {
6627
+ client = { totalHits: 0, resetTime: /* @__PURE__ */ new Date() };
6628
+ this.resetClient(client);
6629
+ }
6630
+ this.current.set(key, client);
6631
+ return client;
6632
+ }
6633
+ /**
6634
+ * Move current clients to previous, create a new map for current.
6635
+ *
6636
+ * This function is called every `windowMs`.
6637
+ */
6638
+ clearExpired() {
6639
+ this.previous = this.current;
6640
+ this.current = /* @__PURE__ */ new Map();
6641
+ }
6642
+ };
6643
+ SUPPORTED_DRAFT_VERSIONS = [
6644
+ "draft-6",
6645
+ "draft-7",
6646
+ "draft-8"
6647
+ ];
6648
+ getResetSeconds = (windowMs, resetTime) => {
6649
+ let resetSeconds;
6650
+ if (resetTime) {
6651
+ const deltaSeconds = Math.ceil((resetTime.getTime() - Date.now()) / 1e3);
6652
+ resetSeconds = Math.max(0, deltaSeconds);
6653
+ } else {
6654
+ resetSeconds = Math.ceil(windowMs / 1e3);
6655
+ }
6656
+ return resetSeconds;
6657
+ };
6658
+ getPartitionKey = (key) => {
6659
+ const hash = createHash3("sha256");
6660
+ hash.update(key);
6661
+ const partitionKey = hash.digest("hex").slice(0, 12);
6662
+ return Buffer2.from(partitionKey).toString("base64");
6663
+ };
6664
+ setLegacyHeaders = (response, info) => {
6665
+ if (response.headersSent) return;
6666
+ response.setHeader("X-RateLimit-Limit", info.limit.toString());
6667
+ response.setHeader("X-RateLimit-Remaining", info.remaining.toString());
6668
+ if (info.resetTime instanceof Date) {
6669
+ response.setHeader("Date", (/* @__PURE__ */ new Date()).toUTCString());
6670
+ response.setHeader(
6671
+ "X-RateLimit-Reset",
6672
+ Math.ceil(info.resetTime.getTime() / 1e3).toString()
6673
+ );
6674
+ }
6675
+ };
6676
+ setDraft6Headers = (response, info, windowMs) => {
6677
+ if (response.headersSent) return;
6678
+ const windowSeconds = Math.ceil(windowMs / 1e3);
6679
+ const resetSeconds = getResetSeconds(windowMs, info.resetTime);
6680
+ response.setHeader("RateLimit-Policy", `${info.limit};w=${windowSeconds}`);
6681
+ response.setHeader("RateLimit-Limit", info.limit.toString());
6682
+ response.setHeader("RateLimit-Remaining", info.remaining.toString());
6683
+ if (typeof resetSeconds === "number")
6684
+ response.setHeader("RateLimit-Reset", resetSeconds.toString());
6685
+ };
6686
+ setDraft7Headers = (response, info, windowMs) => {
6687
+ if (response.headersSent) return;
6688
+ const windowSeconds = Math.ceil(windowMs / 1e3);
6689
+ const resetSeconds = getResetSeconds(windowMs, info.resetTime);
6690
+ response.setHeader("RateLimit-Policy", `${info.limit};w=${windowSeconds}`);
6691
+ response.setHeader(
6692
+ "RateLimit",
6693
+ `limit=${info.limit}, remaining=${info.remaining}, reset=${resetSeconds}`
6694
+ );
6695
+ };
6696
+ setDraft8Headers = (response, info, windowMs, name, key) => {
6697
+ if (response.headersSent) return;
6698
+ const windowSeconds = Math.ceil(windowMs / 1e3);
6699
+ const resetSeconds = getResetSeconds(windowMs, info.resetTime);
6700
+ const partitionKey = getPartitionKey(key);
6701
+ const header = `r=${info.remaining}; t=${resetSeconds}`;
6702
+ const policy = `q=${info.limit}; w=${windowSeconds}; pk=:${partitionKey}:`;
6703
+ response.append("RateLimit", `"${name}"; ${header}`);
6704
+ response.append("RateLimit-Policy", `"${name}"; ${policy}`);
6705
+ };
6706
+ setRetryAfterHeader = (response, info, windowMs) => {
6707
+ if (response.headersSent) return;
6708
+ const resetSeconds = getResetSeconds(windowMs, info.resetTime);
6709
+ response.setHeader("Retry-After", resetSeconds.toString());
6710
+ };
6711
+ omitUndefinedProperties = (passedOptions) => {
6712
+ const omittedOptions = {};
6713
+ for (const k of Object.keys(passedOptions)) {
6714
+ const key = k;
6715
+ if (passedOptions[key] !== void 0) {
6716
+ omittedOptions[key] = passedOptions[key];
6717
+ }
6718
+ }
6719
+ return omittedOptions;
6720
+ };
6721
+ ValidationError = class extends Error {
6722
+ /**
6723
+ * The code must be a string, in snake case and all capital, that starts with
6724
+ * the substring `ERR_ERL_`.
6725
+ *
6726
+ * The message must be a string, starting with an uppercase character,
6727
+ * describing the issue in detail.
6728
+ */
6729
+ constructor(code, message) {
6730
+ const url = `https://express-rate-limit.github.io/${code}/`;
6731
+ super(`${message} See ${url} for more information.`);
6732
+ this.name = this.constructor.name;
6733
+ this.code = code;
6734
+ this.help = url;
6735
+ }
6736
+ };
6737
+ ChangeWarning = class extends ValidationError {
6738
+ };
6739
+ usedStores = /* @__PURE__ */ new Set();
6740
+ singleCountKeys = /* @__PURE__ */ new WeakMap();
6741
+ validations = {
6742
+ enabled: {
6743
+ default: true
6744
+ },
6745
+ // Should be EnabledValidations type, but that's a circular reference
6746
+ disable() {
6747
+ for (const k of Object.keys(this.enabled)) this.enabled[k] = false;
6748
+ },
6749
+ /**
6750
+ * Checks whether the IP address is valid, and that it does not have a port
6751
+ * number in it.
6752
+ *
6753
+ * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_invalid_ip_address.
6754
+ *
6755
+ * @param ip {string | undefined} - The IP address provided by Express as request.ip.
6756
+ *
6757
+ * @returns {void}
6758
+ */
6759
+ ip(ip) {
6760
+ if (ip === void 0) {
6761
+ throw new ValidationError(
6762
+ "ERR_ERL_UNDEFINED_IP_ADDRESS",
6763
+ `An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.`
6764
+ );
6765
+ }
6766
+ if (!isIP(ip)) {
6767
+ throw new ValidationError(
6768
+ "ERR_ERL_INVALID_IP_ADDRESS",
6769
+ `An invalid 'request.ip' (${ip}) was detected. Consider passing a custom 'keyGenerator' function to the rate limiter.`
6770
+ );
6771
+ }
6772
+ },
6773
+ /**
6774
+ * Makes sure the trust proxy setting is not set to `true`.
6775
+ *
6776
+ * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_permissive_trust_proxy.
6777
+ *
6778
+ * @param request {Request} - The Express request object.
6779
+ *
6780
+ * @returns {void}
6781
+ */
6782
+ trustProxy(request) {
6783
+ if (request.app.get("trust proxy") === true) {
6784
+ throw new ValidationError(
6785
+ "ERR_ERL_PERMISSIVE_TRUST_PROXY",
6786
+ `The Express 'trust proxy' setting is true, which allows anyone to trivially bypass IP-based rate limiting.`
6787
+ );
6788
+ }
6789
+ },
6790
+ /**
6791
+ * Makes sure the trust proxy setting is set in case the `X-Forwarded-For`
6792
+ * header is present.
6793
+ *
6794
+ * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_unset_trust_proxy.
6795
+ *
6796
+ * @param request {Request} - The Express request object.
6797
+ *
6798
+ * @returns {void}
6799
+ */
6800
+ xForwardedForHeader(request) {
6801
+ if (request.headers["x-forwarded-for"] && request.app.get("trust proxy") === false) {
6802
+ throw new ValidationError(
6803
+ "ERR_ERL_UNEXPECTED_X_FORWARDED_FOR",
6804
+ `The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.`
6805
+ );
6806
+ }
6807
+ },
6808
+ /**
6809
+ * Alert the user if the Forwarded header is set (standardized version of X-Forwarded-For - not supported by express as of version 5.1.0)
6810
+ *
6811
+ * @param request {Request} - The Express request object.
6812
+ *
6813
+ * @returns {void}
6814
+ */
6815
+ forwardedHeader(request) {
6816
+ if (request.headers.forwarded && request.ip === request.socket?.remoteAddress) {
6817
+ throw new ValidationError(
6818
+ "ERR_ERL_FORWARDED_HEADER",
6819
+ `The 'Forwarded' header (standardized X-Forwarded-For) is set but currently being ignored. Add a custom keyGenerator to use a value from this header.`
6820
+ );
6821
+ }
6822
+ },
6823
+ /**
6824
+ * Ensures totalHits value from store is a positive integer.
6825
+ *
6826
+ * @param hits {any} - The `totalHits` returned by the store.
6827
+ */
6828
+ positiveHits(hits) {
6829
+ if (typeof hits !== "number" || hits < 1 || hits !== Math.round(hits)) {
6830
+ throw new ValidationError(
6831
+ "ERR_ERL_INVALID_HITS",
6832
+ `The totalHits value returned from the store must be a positive integer, got ${hits}`
6833
+ );
6834
+ }
6835
+ },
6836
+ /**
6837
+ * Ensures a single store instance is not used with multiple express-rate-limit instances
6838
+ */
6839
+ unsharedStore(store) {
6840
+ if (usedStores.has(store)) {
6841
+ const maybeUniquePrefix = store?.localKeys ? "" : " (with a unique prefix)";
6842
+ throw new ValidationError(
6843
+ "ERR_ERL_STORE_REUSE",
6844
+ `A Store instance must not be shared across multiple rate limiters. Create a new instance of ${store.constructor.name}${maybeUniquePrefix} for each limiter instead.`
6845
+ );
6846
+ }
6847
+ usedStores.add(store);
6848
+ },
6849
+ /**
6850
+ * Ensures a given key is incremented only once per request.
6851
+ *
6852
+ * @param request {Request} - The Express request object.
6853
+ * @param store {Store} - The store class.
6854
+ * @param key {string} - The key used to store the client's hit count.
6855
+ *
6856
+ * @returns {void}
6857
+ */
6858
+ singleCount(request, store, key) {
6859
+ let storeKeys = singleCountKeys.get(request);
6860
+ if (!storeKeys) {
6861
+ storeKeys = /* @__PURE__ */ new Map();
6862
+ singleCountKeys.set(request, storeKeys);
6863
+ }
6864
+ const storeKey = store.localKeys ? store : store.constructor.name;
6865
+ let keys = storeKeys.get(storeKey);
6866
+ if (!keys) {
6867
+ keys = [];
6868
+ storeKeys.set(storeKey, keys);
6869
+ }
6870
+ const prefixedKey = `${store.prefix ?? ""}${key}`;
6871
+ if (keys.includes(prefixedKey)) {
6872
+ throw new ValidationError(
6873
+ "ERR_ERL_DOUBLE_COUNT",
6874
+ `The hit count for ${key} was incremented more than once for a single request.`
6875
+ );
6876
+ }
6877
+ keys.push(prefixedKey);
6878
+ },
6879
+ /**
6880
+ * Warns the user that the behaviour for `max: 0` / `limit: 0` is
6881
+ * changing in the next major release.
6882
+ *
6883
+ * @param limit {number} - The maximum number of hits per client.
6884
+ *
6885
+ * @returns {void}
6886
+ */
6887
+ limit(limit) {
6888
+ if (limit === 0) {
6889
+ throw new ChangeWarning(
6890
+ "WRN_ERL_MAX_ZERO",
6891
+ "Setting limit or max to 0 disables rate limiting in express-rate-limit v6 and older, but will cause all requests to be blocked in v7"
6892
+ );
6893
+ }
6894
+ },
6895
+ /**
6896
+ * Warns the user that the `draft_polli_ratelimit_headers` option is deprecated
6897
+ * and will be removed in the next major release.
6898
+ *
6899
+ * @param draft_polli_ratelimit_headers {any | undefined} - The now-deprecated setting that was used to enable standard headers.
6900
+ *
6901
+ * @returns {void}
6902
+ */
6903
+ draftPolliHeaders(draft_polli_ratelimit_headers) {
6904
+ if (draft_polli_ratelimit_headers) {
6905
+ throw new ChangeWarning(
6906
+ "WRN_ERL_DEPRECATED_DRAFT_POLLI_HEADERS",
6907
+ `The draft_polli_ratelimit_headers configuration option is deprecated and has been removed in express-rate-limit v7, please set standardHeaders: 'draft-6' instead.`
6908
+ );
6909
+ }
6910
+ },
6911
+ /**
6912
+ * Warns the user that the `onLimitReached` option is deprecated and
6913
+ * will be removed in the next major release.
6914
+ *
6915
+ * @param onLimitReached {any | undefined} - The maximum number of hits per client.
6916
+ *
6917
+ * @returns {void}
6918
+ */
6919
+ onLimitReached(onLimitReached) {
6920
+ if (onLimitReached) {
6921
+ throw new ChangeWarning(
6922
+ "WRN_ERL_DEPRECATED_ON_LIMIT_REACHED",
6923
+ "The onLimitReached configuration option is deprecated and has been removed in express-rate-limit v7."
6924
+ );
6925
+ }
6926
+ },
6927
+ /**
6928
+ * Warns the user when an invalid/unsupported version of the draft spec is passed.
6929
+ *
6930
+ * @param version {any | undefined} - The version passed by the user.
6931
+ *
6932
+ * @returns {void}
6933
+ */
6934
+ headersDraftVersion(version) {
6935
+ if (typeof version !== "string" || // @ts-expect-error This is fine. If version is not in the array, it will just return false.
6936
+ !SUPPORTED_DRAFT_VERSIONS.includes(version)) {
6937
+ const versionString = SUPPORTED_DRAFT_VERSIONS.join(", ");
6938
+ throw new ValidationError(
6939
+ "ERR_ERL_HEADERS_UNSUPPORTED_DRAFT_VERSION",
6940
+ `standardHeaders: only the following versions of the IETF draft specification are supported: ${versionString}.`
6941
+ );
6942
+ }
6943
+ },
6944
+ /**
6945
+ * Warns the user when the selected headers option requires a reset time but
6946
+ * the store does not provide one.
6947
+ *
6948
+ * @param resetTime {Date | undefined} - The timestamp when the client's hit count will be reset.
6949
+ *
6950
+ * @returns {void}
6951
+ */
6952
+ headersResetTime(resetTime) {
6953
+ if (!resetTime) {
6954
+ throw new ValidationError(
6955
+ "ERR_ERL_HEADERS_NO_RESET",
6956
+ `standardHeaders: 'draft-7' requires a 'resetTime', but the store did not provide one. The 'windowMs' value will be used instead, which may cause clients to wait longer than necessary.`
6957
+ );
6958
+ }
6959
+ },
6960
+ knownOptions(passedOptions) {
6961
+ if (!passedOptions) return;
6962
+ const optionsMap = {
6963
+ windowMs: true,
6964
+ limit: true,
6965
+ message: true,
6966
+ statusCode: true,
6967
+ legacyHeaders: true,
6968
+ standardHeaders: true,
6969
+ identifier: true,
6970
+ requestPropertyName: true,
6971
+ skipFailedRequests: true,
6972
+ skipSuccessfulRequests: true,
6973
+ keyGenerator: true,
6974
+ ipv6Subnet: true,
6975
+ handler: true,
6976
+ skip: true,
6977
+ requestWasSuccessful: true,
6978
+ store: true,
6979
+ validate: true,
6980
+ headers: true,
6981
+ max: true,
6982
+ passOnStoreError: true
6983
+ };
6984
+ const validOptions = Object.keys(optionsMap).concat(
6985
+ "draft_polli_ratelimit_headers",
6986
+ // not a valid option anymore, but we have a more specific check for this one, so don't warn for it here
6987
+ // from express-slow-down - https://github.com/express-rate-limit/express-slow-down/blob/main/source/types.ts#L65
6988
+ "delayAfter",
6989
+ "delayMs",
6990
+ "maxDelayMs"
6991
+ );
6992
+ for (const key of Object.keys(passedOptions)) {
6993
+ if (!validOptions.includes(key)) {
6994
+ throw new ValidationError(
6995
+ "ERR_ERL_UNKNOWN_OPTION",
6996
+ `Unexpected configuration option: ${key}`
6997
+ // todo: suggest a valid option with a short levenstein distance?
6998
+ );
6999
+ }
7000
+ }
7001
+ },
7002
+ /**
7003
+ * Checks the options.validate setting to ensure that only recognized
7004
+ * validations are enabled or disabled.
7005
+ *
7006
+ * If any unrecognized values are found, an error is logged that
7007
+ * includes the list of supported validations.
7008
+ */
7009
+ validationsConfig() {
7010
+ const supportedValidations = Object.keys(this).filter(
7011
+ (k) => !["enabled", "disable"].includes(k)
7012
+ );
7013
+ supportedValidations.push("default");
7014
+ for (const key of Object.keys(this.enabled)) {
7015
+ if (!supportedValidations.includes(key)) {
7016
+ throw new ValidationError(
7017
+ "ERR_ERL_UNKNOWN_VALIDATION",
7018
+ `options.validate.${key} is not recognized. Supported validate options are: ${supportedValidations.join(
7019
+ ", "
7020
+ )}.`
7021
+ );
7022
+ }
7023
+ }
7024
+ },
7025
+ /**
7026
+ * Checks to see if the instance was created inside of a request handler,
7027
+ * which would prevent it from working correctly, with the default memory
7028
+ * store (or any other store with localKeys.)
7029
+ */
7030
+ creationStack(store) {
7031
+ const { stack } = new Error(
7032
+ "express-rate-limit validation check (set options.validate.creationStack=false to disable)"
7033
+ );
7034
+ if (stack?.includes("Layer.handle [as handle_request]") || // express v4
7035
+ stack?.includes("Layer.handleRequest")) {
7036
+ if (!store.localKeys) {
7037
+ throw new ValidationError(
7038
+ "ERR_ERL_CREATED_IN_REQUEST_HANDLER",
7039
+ "express-rate-limit instance should *usually* be created at app initialization, not when responding to a request."
7040
+ );
7041
+ }
7042
+ throw new ValidationError(
7043
+ "ERR_ERL_CREATED_IN_REQUEST_HANDLER",
7044
+ "express-rate-limit instance should be created at app initialization, not when responding to a request."
7045
+ );
7046
+ }
7047
+ },
7048
+ ipv6Subnet(ipv6Subnet) {
7049
+ if (ipv6Subnet === false) {
7050
+ return;
7051
+ }
7052
+ if (!Number.isInteger(ipv6Subnet) || ipv6Subnet < 32 || ipv6Subnet > 64) {
7053
+ throw new ValidationError(
7054
+ "ERR_ERL_IPV6_SUBNET",
7055
+ `Unexpected ipv6Subnet value: ${ipv6Subnet}. Expected an integer between 32 and 64 (usually 48-64).`
7056
+ );
7057
+ }
7058
+ },
7059
+ ipv6SubnetOrKeyGenerator(options) {
7060
+ if (options.ipv6Subnet !== void 0 && options.keyGenerator) {
7061
+ throw new ValidationError(
7062
+ "ERR_ERL_IPV6SUBNET_OR_KEYGENERATOR",
7063
+ `Incompatible options: the 'ipv6Subnet' option is ignored when a custom 'keyGenerator' function is also set.`
7064
+ );
7065
+ }
7066
+ },
7067
+ keyGeneratorIpFallback(keyGenerator) {
7068
+ if (!keyGenerator) {
7069
+ return;
7070
+ }
7071
+ const src = keyGenerator.toString();
7072
+ if ((src.includes("req.ip") || src.includes("request.ip")) && !src.includes("ipKeyGenerator")) {
7073
+ throw new ValidationError(
7074
+ "ERR_ERL_KEY_GEN_IPV6",
7075
+ "Custom keyGenerator appears to use request IP without calling the ipKeyGenerator helper function for IPv6 addresses. This could allow IPv6 users to bypass limits."
7076
+ );
7077
+ }
7078
+ },
7079
+ /**
7080
+ * Checks to see if the window duration is greater than 2^32 - 1. This is only
7081
+ * called by the default MemoryStore, since it uses Node's setInterval method.
7082
+ *
7083
+ * See https://nodejs.org/api/timers.html#setintervalcallback-delay-args.
7084
+ */
7085
+ windowMs(windowMs) {
7086
+ const SET_TIMEOUT_MAX = 2 ** 31 - 1;
7087
+ if (typeof windowMs !== "number" || Number.isNaN(windowMs) || windowMs < 1 || windowMs > SET_TIMEOUT_MAX) {
7088
+ throw new ValidationError(
7089
+ "ERR_ERL_WINDOW_MS",
7090
+ `Invalid windowMs value: ${windowMs}${typeof windowMs !== "number" ? ` (${typeof windowMs})` : ""}, must be a number between 1 and ${SET_TIMEOUT_MAX} when using the default MemoryStore`
7091
+ );
7092
+ }
7093
+ }
7094
+ };
7095
+ getValidations = (_enabled) => {
7096
+ let enabled;
7097
+ if (typeof _enabled === "boolean") {
7098
+ enabled = {
7099
+ default: _enabled
7100
+ };
7101
+ } else {
7102
+ enabled = {
7103
+ default: true,
7104
+ ..._enabled
7105
+ };
7106
+ }
7107
+ const wrappedValidations = { enabled };
7108
+ for (const [name, validation] of Object.entries(validations)) {
7109
+ if (typeof validation === "function")
7110
+ wrappedValidations[name] = (...args) => {
7111
+ if (!(enabled[name] ?? enabled.default)) {
7112
+ return;
7113
+ }
7114
+ try {
7115
+ ;
7116
+ validation.apply(
7117
+ wrappedValidations,
7118
+ args
7119
+ );
7120
+ } catch (error) {
7121
+ if (error instanceof ChangeWarning) console.warn(error);
7122
+ else console.error(error);
7123
+ }
7124
+ };
7125
+ }
7126
+ return wrappedValidations;
7127
+ };
7128
+ isLegacyStore = (store) => (
7129
+ // Check that `incr` exists but `increment` does not - store authors might want
7130
+ // to keep both around for backwards compatibility.
7131
+ typeof store.incr === "function" && typeof store.increment !== "function"
7132
+ );
7133
+ promisifyStore = (passedStore) => {
7134
+ if (!isLegacyStore(passedStore)) {
7135
+ return passedStore;
7136
+ }
7137
+ const legacyStore = passedStore;
7138
+ class PromisifiedStore {
7139
+ async increment(key) {
7140
+ return new Promise((resolve24, reject) => {
7141
+ legacyStore.incr(
7142
+ key,
7143
+ (error, totalHits, resetTime) => {
7144
+ if (error) reject(error);
7145
+ resolve24({ totalHits, resetTime });
7146
+ }
7147
+ );
7148
+ });
7149
+ }
7150
+ async decrement(key) {
7151
+ return legacyStore.decrement(key);
7152
+ }
7153
+ async resetKey(key) {
7154
+ return legacyStore.resetKey(key);
7155
+ }
7156
+ /* istanbul ignore next */
7157
+ async resetAll() {
7158
+ if (typeof legacyStore.resetAll === "function")
7159
+ return legacyStore.resetAll();
7160
+ }
7161
+ }
7162
+ return new PromisifiedStore();
7163
+ };
7164
+ getOptionsFromConfig = (config8) => {
7165
+ const { validations: validations2, ...directlyPassableEntries } = config8;
7166
+ return {
7167
+ ...directlyPassableEntries,
7168
+ validate: validations2.enabled
7169
+ };
7170
+ };
7171
+ parseOptions = (passedOptions) => {
7172
+ const notUndefinedOptions = omitUndefinedProperties(passedOptions);
7173
+ const validations2 = getValidations(notUndefinedOptions?.validate ?? true);
7174
+ validations2.validationsConfig();
7175
+ validations2.knownOptions(passedOptions);
7176
+ validations2.draftPolliHeaders(
7177
+ // @ts-expect-error see the note above.
7178
+ notUndefinedOptions.draft_polli_ratelimit_headers
7179
+ );
7180
+ validations2.onLimitReached(notUndefinedOptions.onLimitReached);
7181
+ if (notUndefinedOptions.ipv6Subnet !== void 0 && typeof notUndefinedOptions.ipv6Subnet !== "function") {
7182
+ validations2.ipv6Subnet(notUndefinedOptions.ipv6Subnet);
7183
+ }
7184
+ validations2.keyGeneratorIpFallback(notUndefinedOptions.keyGenerator);
7185
+ validations2.ipv6SubnetOrKeyGenerator(notUndefinedOptions);
7186
+ let standardHeaders = notUndefinedOptions.standardHeaders ?? false;
7187
+ if (standardHeaders === true) standardHeaders = "draft-6";
7188
+ const config8 = {
7189
+ windowMs: 60 * 1e3,
7190
+ limit: passedOptions.max ?? 5,
7191
+ // `max` is deprecated, but support it anyways.
7192
+ message: "Too many requests, please try again later.",
7193
+ statusCode: 429,
7194
+ legacyHeaders: passedOptions.headers ?? true,
7195
+ identifier(request, _response) {
7196
+ let duration = "";
7197
+ const property = config8.requestPropertyName;
7198
+ const { limit } = request[property];
7199
+ const seconds = config8.windowMs / 1e3;
7200
+ const minutes = config8.windowMs / (1e3 * 60);
7201
+ const hours = config8.windowMs / (1e3 * 60 * 60);
7202
+ const days = config8.windowMs / (1e3 * 60 * 60 * 24);
7203
+ if (seconds < 60) duration = `${seconds}sec`;
7204
+ else if (minutes < 60) duration = `${minutes}min`;
7205
+ else if (hours < 24) duration = `${hours}hr${hours > 1 ? "s" : ""}`;
7206
+ else duration = `${days}day${days > 1 ? "s" : ""}`;
7207
+ return `${limit}-in-${duration}`;
7208
+ },
7209
+ requestPropertyName: "rateLimit",
7210
+ skipFailedRequests: false,
7211
+ skipSuccessfulRequests: false,
7212
+ requestWasSuccessful: (_request, response) => response.statusCode < 400,
7213
+ skip: (_request, _response) => false,
7214
+ async keyGenerator(request, response) {
7215
+ validations2.ip(request.ip);
7216
+ validations2.trustProxy(request);
7217
+ validations2.xForwardedForHeader(request);
7218
+ validations2.forwardedHeader(request);
7219
+ const ip = request.ip;
7220
+ let subnet = 56;
7221
+ if (isIPv62(ip)) {
7222
+ subnet = typeof config8.ipv6Subnet === "function" ? await config8.ipv6Subnet(request, response) : config8.ipv6Subnet;
7223
+ if (typeof config8.ipv6Subnet === "function")
7224
+ validations2.ipv6Subnet(subnet);
7225
+ }
7226
+ return ipKeyGenerator(ip, subnet);
7227
+ },
7228
+ ipv6Subnet: 56,
7229
+ async handler(request, response, _next, _optionsUsed) {
7230
+ response.status(config8.statusCode);
7231
+ const message = typeof config8.message === "function" ? await config8.message(
7232
+ request,
7233
+ response
7234
+ ) : config8.message;
7235
+ if (!response.writableEnded) response.send(message);
7236
+ },
7237
+ passOnStoreError: false,
7238
+ // Allow the default options to be overridden by the passed options.
7239
+ ...notUndefinedOptions,
7240
+ // `standardHeaders` is resolved into a draft version above, use that.
7241
+ standardHeaders,
7242
+ // Note that this field is declared after the user's options are spread in,
7243
+ // so that this field doesn't get overridden with an un-promisified store!
7244
+ store: promisifyStore(
7245
+ notUndefinedOptions.store ?? new MemoryStore(validations2)
7246
+ ),
7247
+ // Print an error to the console if a few known misconfigurations are detected.
7248
+ validations: validations2
7249
+ };
7250
+ if (typeof config8.store.increment !== "function" || typeof config8.store.decrement !== "function" || typeof config8.store.resetKey !== "function" || config8.store.resetAll !== void 0 && typeof config8.store.resetAll !== "function" || config8.store.init !== void 0 && typeof config8.store.init !== "function") {
7251
+ throw new TypeError(
7252
+ "An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface."
7253
+ );
7254
+ }
7255
+ return config8;
7256
+ };
7257
+ handleAsyncErrors = (fn) => async (request, response, next) => {
7258
+ try {
7259
+ await Promise.resolve(fn(request, response, next)).catch(next);
7260
+ } catch (error) {
7261
+ next(error);
7262
+ }
7263
+ };
7264
+ rateLimit = (passedOptions) => {
7265
+ const config8 = parseOptions(passedOptions ?? {});
7266
+ const options = getOptionsFromConfig(config8);
7267
+ config8.validations.creationStack(config8.store);
7268
+ config8.validations.unsharedStore(config8.store);
7269
+ if (typeof config8.store.init === "function") config8.store.init(options);
7270
+ const middleware = handleAsyncErrors(
7271
+ async (request, response, next) => {
7272
+ const skip = await config8.skip(request, response);
7273
+ if (skip) {
7274
+ next();
7275
+ return;
7276
+ }
7277
+ const augmentedRequest = request;
7278
+ const key = await config8.keyGenerator(request, response);
7279
+ let totalHits = 0;
7280
+ let resetTime;
7281
+ try {
7282
+ const incrementResult = await config8.store.increment(key);
7283
+ totalHits = incrementResult.totalHits;
7284
+ resetTime = incrementResult.resetTime;
7285
+ } catch (error) {
7286
+ if (config8.passOnStoreError) {
7287
+ console.error(
7288
+ "express-rate-limit: error from store, allowing request without rate-limiting.",
7289
+ error
7290
+ );
7291
+ next();
7292
+ return;
7293
+ }
7294
+ throw error;
7295
+ }
7296
+ config8.validations.positiveHits(totalHits);
7297
+ config8.validations.singleCount(request, config8.store, key);
7298
+ const retrieveLimit = typeof config8.limit === "function" ? config8.limit(request, response) : config8.limit;
7299
+ const limit = await retrieveLimit;
7300
+ config8.validations.limit(limit);
7301
+ const info = {
7302
+ limit,
7303
+ used: totalHits,
7304
+ remaining: Math.max(limit - totalHits, 0),
7305
+ resetTime,
7306
+ key
7307
+ };
7308
+ Object.defineProperty(info, "current", {
7309
+ configurable: false,
7310
+ enumerable: false,
7311
+ value: totalHits
7312
+ });
7313
+ augmentedRequest[config8.requestPropertyName] = info;
7314
+ if (config8.legacyHeaders && !response.headersSent) {
7315
+ setLegacyHeaders(response, info);
7316
+ }
7317
+ if (config8.standardHeaders && !response.headersSent) {
7318
+ switch (config8.standardHeaders) {
7319
+ case "draft-6": {
7320
+ setDraft6Headers(response, info, config8.windowMs);
7321
+ break;
7322
+ }
7323
+ case "draft-7": {
7324
+ config8.validations.headersResetTime(info.resetTime);
7325
+ setDraft7Headers(response, info, config8.windowMs);
7326
+ break;
7327
+ }
7328
+ case "draft-8": {
7329
+ const retrieveName = typeof config8.identifier === "function" ? config8.identifier(request, response) : config8.identifier;
7330
+ const name = await retrieveName;
7331
+ config8.validations.headersResetTime(info.resetTime);
7332
+ setDraft8Headers(response, info, config8.windowMs, name, key);
7333
+ break;
7334
+ }
7335
+ default: {
7336
+ config8.validations.headersDraftVersion(config8.standardHeaders);
7337
+ break;
7338
+ }
7339
+ }
7340
+ }
7341
+ if (config8.skipFailedRequests || config8.skipSuccessfulRequests) {
7342
+ let decremented = false;
7343
+ const decrementKey = async () => {
7344
+ if (!decremented) {
7345
+ await config8.store.decrement(key);
7346
+ decremented = true;
7347
+ }
7348
+ };
7349
+ if (config8.skipFailedRequests) {
7350
+ response.on("finish", async () => {
7351
+ if (!await config8.requestWasSuccessful(request, response))
7352
+ await decrementKey();
7353
+ });
7354
+ response.on("close", async () => {
7355
+ if (!response.writableEnded) await decrementKey();
7356
+ });
7357
+ response.on("error", async () => {
7358
+ await decrementKey();
7359
+ });
7360
+ }
7361
+ if (config8.skipSuccessfulRequests) {
7362
+ response.on("finish", async () => {
7363
+ if (await config8.requestWasSuccessful(request, response))
7364
+ await decrementKey();
7365
+ });
7366
+ }
7367
+ }
7368
+ config8.validations.disable();
7369
+ if (totalHits > limit) {
7370
+ if (config8.legacyHeaders || config8.standardHeaders) {
7371
+ setRetryAfterHeader(response, info, config8.windowMs);
7372
+ }
7373
+ config8.handler(request, response, next, options);
7374
+ return;
7375
+ }
7376
+ next();
7377
+ }
7378
+ );
7379
+ const getThrowFn = () => {
7380
+ throw new Error("The current store does not support the get/getKey method");
7381
+ };
7382
+ middleware.resetKey = config8.store.resetKey.bind(config8.store);
7383
+ middleware.getKey = typeof config8.store.get === "function" ? config8.store.get.bind(config8.store) : getThrowFn;
7384
+ return middleware;
7385
+ };
7386
+ rate_limit_default = rateLimit;
7387
+ }
7388
+ });
7389
+
7390
+ // packages/server/dist/routes/entities.js
7391
+ import { Router as Router2 } from "express";
7392
+ function createEntityRoutes(bundle) {
7393
+ const router = Router2();
7394
+ const { store } = bundle;
7395
+ router.get("/", async (req, res) => {
7396
+ try {
7397
+ const { type, project, search, limit: rawLimit = "50", offset: rawOffset = "0", status = "active" } = req.query;
7398
+ const parsedLimit = Math.max(1, Math.min(Number(rawLimit) || 50, 500));
7399
+ const parsedOffset = Math.max(0, Number(rawOffset) || 0);
7400
+ if (search && typeof search === "string") {
7401
+ const results = await store.searchEntities(search, parsedLimit);
7402
+ res.json({ success: true, data: results, meta: { total: results.length, limit: parsedLimit, offset: 0 } });
7403
+ return;
7404
+ }
7405
+ const entities = await store.findEntities({
7406
+ type,
7407
+ projectId: project,
7408
+ status,
7409
+ limit: parsedLimit,
7410
+ offset: parsedOffset
7411
+ });
7412
+ res.json({ success: true, data: entities, meta: { limit: parsedLimit, offset: parsedOffset } });
7413
+ } catch (err) {
7414
+ logger26.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
7415
+ res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
7416
+ }
7417
+ });
7418
+ router.get("/:id", async (req, res) => {
7419
+ try {
7420
+ const entity = await store.getEntity(req.params.id);
7421
+ if (!entity) {
7422
+ res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "Entity not found" } });
7423
+ return;
7424
+ }
7425
+ res.json({ success: true, data: entity });
7426
+ } catch (err) {
7427
+ logger26.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
7428
+ res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
7429
+ }
7430
+ });
7431
+ router.get("/:id/relationships", async (req, res) => {
7432
+ try {
7433
+ const { direction = "both" } = req.query;
7434
+ const relationships = await store.getRelationshipsForEntity(req.params.id, direction);
7435
+ res.json({ success: true, data: relationships });
7436
+ } catch (err) {
7437
+ logger26.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
7438
+ res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
7439
+ }
7440
+ });
7441
+ return router;
7442
+ }
7443
+ var logger26;
7444
+ var init_entities = __esm({
7445
+ "packages/server/dist/routes/entities.js"() {
7446
+ "use strict";
7447
+ init_dist();
7448
+ logger26 = createLogger("server:entities");
7449
+ }
7450
+ });
7451
+
7452
+ // packages/server/dist/routes/relationships.js
7453
+ import { Router as Router3 } from "express";
7454
+ function createRelationshipRoutes(bundle) {
7455
+ const router = Router3();
7456
+ const { store } = bundle;
7457
+ router.get("/", async (req, res) => {
7458
+ try {
7459
+ const { type, sourceId, targetId, limit: rawLimit = "100" } = req.query;
7460
+ const parsedLimit = Math.max(1, Math.min(Number(rawLimit) || 100, 500));
7461
+ if (sourceId && typeof sourceId === "string") {
7462
+ const rels = await store.getRelationshipsForEntity(sourceId, "out");
7463
+ const filtered = type ? rels.filter((r) => r.type === type) : rels;
7464
+ res.json({ success: true, data: filtered.slice(0, parsedLimit) });
7465
+ return;
7466
+ }
7467
+ if (targetId && typeof targetId === "string") {
7468
+ const rels = await store.getRelationshipsForEntity(targetId, "in");
7469
+ const filtered = type ? rels.filter((r) => r.type === type) : rels;
7470
+ res.json({ success: true, data: filtered.slice(0, parsedLimit) });
7471
+ return;
7472
+ }
7473
+ res.json({
7474
+ success: true,
7475
+ data: [],
7476
+ meta: { message: "Provide sourceId or targetId to query relationships" }
7477
+ });
7478
+ } catch (err) {
7479
+ logger27.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
7480
+ res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
7481
+ }
7482
+ });
7483
+ router.get("/:id", async (req, res) => {
7484
+ try {
7485
+ const rel = await store.getRelationship(req.params.id);
7486
+ if (!rel) {
7487
+ res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "Relationship not found" } });
7488
+ return;
7489
+ }
7490
+ res.json({ success: true, data: rel });
7491
+ } catch (err) {
7492
+ logger27.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
7493
+ res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
7494
+ }
7495
+ });
7496
+ return router;
7497
+ }
7498
+ var logger27;
7499
+ var init_relationships = __esm({
7500
+ "packages/server/dist/routes/relationships.js"() {
7501
+ "use strict";
7502
+ init_dist();
7503
+ logger27 = createLogger("server:relationships");
7504
+ }
7505
+ });
7506
+
7507
+ // packages/server/dist/routes/projects.js
7508
+ import { Router as Router4 } from "express";
7509
+ function createProjectRoutes(bundle) {
7510
+ const router = Router4();
7511
+ const { store } = bundle;
7512
+ router.get("/", async (_req, res) => {
7513
+ try {
7514
+ const projects = await store.listProjects();
7515
+ res.json({ success: true, data: projects });
7516
+ } catch (err) {
7517
+ logger28.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
7518
+ res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
7519
+ }
7520
+ });
7521
+ router.get("/:id", async (req, res) => {
7522
+ try {
7523
+ const project = await store.getProject(req.params.id);
7524
+ if (!project) {
7525
+ res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "Project not found" } });
7526
+ return;
7527
+ }
7528
+ res.json({ success: true, data: project });
7529
+ } catch (err) {
7530
+ logger28.error("Request failed", { error: err instanceof Error ? err.message : String(err) });
7531
+ res.status(500).json({ success: false, error: { code: "SERVER_ERROR", message: "Internal server error" } });
7532
+ }
7533
+ });
7534
+ return router;
7535
+ }
7536
+ var logger28;
7537
+ var init_projects = __esm({
7538
+ "packages/server/dist/routes/projects.js"() {
7539
+ "use strict";
7540
+ init_dist();
7541
+ logger28 = createLogger("server:projects");
7542
+ }
7543
+ });
7544
+
7545
+ // packages/server/dist/routes/query.js
7546
+ import { Router as Router5 } from "express";
7547
+ function createQueryRoutes(bundle) {
7548
+ const router = Router5();
7549
+ const { store, queryEngine, router: llmRouter } = bundle;
7550
+ router.post("/", async (req, res) => {
7551
+ try {
7552
+ const { query, projectId, stream = false } = req.body;
7553
+ if (!query || typeof query !== "string") {
7554
+ res.status(400).json({ success: false, error: { code: "BAD_REQUEST", message: "query is required" } });
7555
+ return;
7556
+ }
7557
+ if (projectId && typeof projectId === "string") {
7558
+ const project = await store.getProject(projectId);
7559
+ if (!project) {
7560
+ res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "Project not found" } });
7561
+ return;
7562
+ }
7563
+ }
7564
+ const context = await queryEngine.assembleContext(query, void 0, projectId);
7565
+ if (stream) {
7566
+ res.setHeader("Content-Type", "text/event-stream");
7567
+ res.setHeader("Cache-Control", "no-cache");
7568
+ res.setHeader("Connection", "keep-alive");
7569
+ const systemPrompt8 = buildQuerySystemPrompt(context);
7570
+ const gen = llmRouter.stream({
7571
+ systemPrompt: systemPrompt8,
7572
+ userPrompt: query,
7573
+ promptId: "conversational_query",
7574
+ promptVersion: "1.0",
7575
+ task: LLMTask.CONVERSATIONAL_QUERY,
7576
+ modelPreference: "primary",
7577
+ temperature: 0.7
7578
+ });
7579
+ for await (const chunk of gen) {
7580
+ res.write(`data: ${JSON.stringify({ type: "chunk", content: chunk })}
7581
+
7582
+ `);
7583
+ }
7584
+ res.write(`data: ${JSON.stringify({ type: "sources", entities: context.entities.slice(0, 10) })}
7585
+
7586
+ `);
7587
+ res.write(`data: ${JSON.stringify({ type: "complete" })}
7588
+
7589
+ `);
7590
+ res.end();
7591
+ return;
7592
+ }
7593
+ const systemPrompt7 = buildQuerySystemPrompt(context);
7594
+ const result = await llmRouter.complete({
7595
+ systemPrompt: systemPrompt7,
7596
+ userPrompt: query,
7597
+ promptId: "conversational_query",
7598
+ promptVersion: "1.0",
7599
+ task: LLMTask.CONVERSATIONAL_QUERY,
7600
+ modelPreference: "primary",
7601
+ temperature: 0.7
7602
+ });
7603
+ res.json({
7604
+ success: true,
7605
+ data: {
7606
+ answer: result.content,
7607
+ sources: context.entities.slice(0, 10),
7608
+ relationships: context.relationships,
7609
+ model: result.model,
7610
+ tokens: { input: result.inputTokens, output: result.outputTokens }
7611
+ }
7612
+ });
7613
+ } catch (err) {
7614
+ logger29.error("Query failed", { error: err instanceof Error ? err.message : String(err) });
7615
+ res.status(500).json({ success: false, error: { code: "QUERY_FAILED", message: "Query processing failed" } });
7616
+ }
7617
+ });
7618
+ return router;
7619
+ }
7620
+ function buildQuerySystemPrompt(context) {
7621
+ const entityContext = context.entities.map((e, i) => `[${i + 1}] ${e.type}: ${e.name}
7622
+ ${e.summary ?? e.content}`).join("\n\n");
7623
+ return `You are Cortex, a knowledge graph assistant. Answer questions using ONLY the context below. Cite sources as [N].
7624
+
7625
+ ## Knowledge Context
7626
+ ${entityContext || "No relevant entities found."}
7627
+
7628
+ ## Instructions
7629
+ - Answer concisely and accurately based on the context
7630
+ - Cite sources using [N] notation
7631
+ - If the context doesn't contain enough information, say so
7632
+ - Suggest follow-up questions the user might ask`;
5177
7633
  }
5178
7634
  var logger29;
5179
7635
  var init_query = __esm({
@@ -5601,7 +8057,8 @@ async function startServer(options) {
5601
8057
  if (options.webDistPath) {
5602
8058
  const webDist = resolve20(options.webDistPath);
5603
8059
  app.use(express.static(webDist));
5604
- app.get("*", (_req, res) => {
8060
+ const spaLimiter = rate_limit_default({ windowMs: 6e4, max: 60 });
8061
+ app.get("*", spaLimiter, (_req, res) => {
5605
8062
  res.sendFile(resolve20(webDist, "index.html"));
5606
8063
  });
5607
8064
  logger34.info("Serving web dashboard", { path: webDist });
@@ -5675,9 +8132,10 @@ async function startServer(options) {
5675
8132
  process.on("SIGTERM", shutdown);
5676
8133
  }
5677
8134
  var logger34;
5678
- var init_dist5 = __esm({
8135
+ var init_dist6 = __esm({
5679
8136
  "packages/server/dist/index.js"() {
5680
8137
  "use strict";
8138
+ init_dist5();
5681
8139
  init_dist();
5682
8140
  init_dist2();
5683
8141
  init_dist3();
@@ -6426,6 +8884,9 @@ import { resolve as resolve7 } from "node:path";
6426
8884
  import { statSync as statSync3 } from "node:fs";
6427
8885
  import chalk5 from "chalk";
6428
8886
  var logger15 = createLogger("cli:status");
8887
+ function sanitizeConfigValue(val) {
8888
+ return [...val].map((c) => c).join("");
8889
+ }
6429
8890
  function sanitizeUrl(url) {
6430
8891
  try {
6431
8892
  const parsed = new URL(url);
@@ -6473,10 +8934,17 @@ async function runStatus(globals) {
6473
8934
  vectorSizeBytes = vectorStat.size;
6474
8935
  } catch {
6475
8936
  }
8937
+ const cloudProvider = sanitizeConfigValue(config8.llm.cloud.provider);
8938
+ const cloudPrimary = sanitizeConfigValue(config8.llm.cloud.models.primary);
8939
+ const cloudFast = sanitizeConfigValue(config8.llm.cloud.models.fast);
8940
+ const localModel = sanitizeConfigValue(config8.llm.local.model);
8941
+ const localHost = sanitizeUrl(config8.llm.local.host);
8942
+ const localNumCtx = Number(config8.llm.local.numCtx) || 8192;
8943
+ const localNumGpu = Number(config8.llm.local.numGpu) ?? -1;
6476
8944
  const apiKeySource = config8.llm.cloud.apiKeySource;
6477
8945
  const apiKeyEnvVar = apiKeySource.startsWith("env:") ? apiKeySource.slice(4) : void 0;
6478
- const hasApiKey = apiKeyEnvVar ? Boolean(process.env[apiKeyEnvVar]) : false;
6479
- const mode = config8.llm.mode;
8946
+ const hasApiKey = apiKeyEnvVar ? Object.hasOwn(process.env, apiKeyEnvVar) : false;
8947
+ const mode = sanitizeConfigValue(config8.llm.mode);
6480
8948
  const ollamaAvailable = mode !== "cloud-first" ? await checkOllamaAvailable(config8.llm.local.host) : false;
6481
8949
  if (globals.json)
6482
8950
  setGlobalLogLevel("error");
@@ -6505,15 +8973,15 @@ async function runStatus(globals) {
6505
8973
  llm: {
6506
8974
  mode,
6507
8975
  cloud: {
6508
- provider: config8.llm.cloud.provider,
8976
+ provider: cloudProvider,
6509
8977
  available: hasApiKey
6510
8978
  },
6511
8979
  local: {
6512
8980
  provider: "ollama",
6513
8981
  available: ollamaAvailable,
6514
- host: sanitizeUrl(config8.llm.local.host),
6515
- model: config8.llm.local.model,
6516
- numCtx: localProvider?.getNumCtx() ?? config8.llm.local.numCtx
8982
+ host: localHost,
8983
+ model: localModel,
8984
+ numCtx: localProvider?.getNumCtx() ?? localNumCtx
6517
8985
  }
6518
8986
  },
6519
8987
  budget: {
@@ -6536,11 +9004,11 @@ async function runStatus(globals) {
6536
9004
  console.log(chalk5.white("Files: ") + `${stats.fileCount} tracked`);
6537
9005
  console.log(chalk5.white("Storage: ") + `${formatBytes(stats.dbSizeBytes)} (SQLite) | ${formatBytes(vectorSizeBytes)} (vectors)`);
6538
9006
  console.log("");
6539
- const numCtx = localProvider?.getNumCtx() ?? config8.llm.local.numCtx;
6540
- const numGpu = localProvider?.getNumGpu() ?? config8.llm.local.numGpu;
9007
+ const numCtx = localProvider?.getNumCtx() ?? localNumCtx;
9008
+ const numGpu = localProvider?.getNumGpu() ?? localNumGpu;
6541
9009
  console.log(chalk5.white("LLM Mode: ") + mode);
6542
- const cloudLabel = `${config8.llm.cloud.models.primary} / ${config8.llm.cloud.models.fast} (${config8.llm.cloud.provider})`;
6543
- const localLabel = `${config8.llm.local.model} @ ${sanitizeUrl(config8.llm.local.host)}`;
9010
+ const cloudLabel = `${cloudPrimary} / ${cloudFast} (${cloudProvider})`;
9011
+ const localLabel = `${localModel} @ ${localHost}`;
6544
9012
  const localDetail = `${numCtx.toLocaleString()} ctx | GPU: ${numGpu === -1 ? "auto" : numGpu} layers | ~30 tok/s est.`;
6545
9013
  if (mode === "cloud-first") {
6546
9014
  const llmStatus = hasApiKey ? chalk5.green("\u2713") : chalk5.red("\u2717");
@@ -6829,9 +9297,15 @@ function setNestedValue(obj, path, value) {
6829
9297
  current = current[part];
6830
9298
  }
6831
9299
  const lastKey = parts[parts.length - 1];
6832
- if (DANGEROUS_KEYS.has(lastKey))
9300
+ if (lastKey === "__proto__" || lastKey === "constructor" || lastKey === "prototype") {
6833
9301
  throw new Error(`Invalid config key: ${lastKey}`);
6834
- current[lastKey] = value;
9302
+ }
9303
+ Object.defineProperty(current, lastKey, {
9304
+ value,
9305
+ writable: true,
9306
+ enumerable: true,
9307
+ configurable: true
9308
+ });
6835
9309
  }
6836
9310
  function parseValue(value) {
6837
9311
  try {
@@ -8283,7 +10757,7 @@ async function runServe(opts, globals) {
8283
10757
  }
8284
10758
  } catch {
8285
10759
  }
8286
- const { startServer: startServer2 } = await Promise.resolve().then(() => (init_dist5(), dist_exports2));
10760
+ const { startServer: startServer2 } = await Promise.resolve().then(() => (init_dist6(), dist_exports2));
8287
10761
  const pidDir = resolve21(homedir7(), ".cortex");
8288
10762
  mkdirSync6(pidDir, { recursive: true });
8289
10763
  writeFileSync5(resolve21(pidDir, "cortex.pid"), String(process.pid));