@hasna/instructions 0.4.3 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -4486,7 +4486,7 @@ var init_package_manager_guard = __esm(() => {
4486
4486
  ];
4487
4487
  });
4488
4488
 
4489
- // node_modules/.pnpm/@hasna+events@0.1.13/node_modules/@hasna/events/dist/commander.js
4489
+ // node_modules/@hasna/events/dist/commander.js
4490
4490
  import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
4491
4491
  import { existsSync } from "fs";
4492
4492
  import { homedir } from "os";
@@ -4503,83 +4503,29 @@ function getPathValue(input, path) {
4503
4503
  return;
4504
4504
  }, input);
4505
4505
  }
4506
- function getFieldValues(input, path) {
4507
- const values = [];
4508
- const push = (value) => {
4509
- if (!values.some((item) => Object.is(item, value)))
4510
- values.push(value);
4511
- };
4512
- if (path.includes(".") && path in input)
4513
- push(input[path]);
4514
- const nestedValue = getPathValue(input, path);
4515
- if (nestedValue !== undefined || !path.includes("."))
4516
- push(nestedValue);
4517
- return values;
4518
- }
4519
- function wildcardToRegExp(pattern, options = {}) {
4520
- let body = "";
4521
- for (let index = 0;index < pattern.length; index += 1) {
4522
- const char = pattern[index];
4523
- if (char === "*") {
4524
- if (pattern[index + 1] === "*") {
4525
- body += ".*";
4526
- index += 1;
4527
- } else {
4528
- body += options.segmentSafe ? "[^/]*" : ".*";
4529
- }
4530
- } else {
4531
- body += char.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
4532
- }
4533
- }
4534
- return new RegExp(`^${body}$`);
4506
+ function wildcardToRegExp(pattern) {
4507
+ const escaped = pattern.replace(/[|\\{}()[\]^$+?.]/g, "\\$&").replace(/\*/g, ".*");
4508
+ return new RegExp(`^${escaped}$`);
4535
4509
  }
4536
- function matchString(value, matcher, options = {}) {
4510
+ function matchString(value, matcher) {
4537
4511
  if (matcher === undefined)
4538
4512
  return true;
4539
4513
  if (value === undefined)
4540
4514
  return false;
4541
4515
  const matchers = Array.isArray(matcher) ? matcher : [matcher];
4542
- return matchers.some((item) => wildcardToRegExp(item, options).test(value));
4516
+ return matchers.some((item) => wildcardToRegExp(item).test(value));
4543
4517
  }
4544
4518
  function matchRecord(input, matcher) {
4545
4519
  if (!matcher)
4546
4520
  return true;
4547
4521
  return Object.entries(matcher).every(([path, expected]) => {
4548
- const actualValues = getFieldValues(input, path);
4549
- return matchField(actualValues, expected, path);
4522
+ const actual = getPathValue(input, path);
4523
+ if (typeof expected === "string" || Array.isArray(expected)) {
4524
+ return matchString(actual === undefined ? undefined : String(actual), expected);
4525
+ }
4526
+ return actual === expected;
4550
4527
  });
4551
4528
  }
4552
- function matchField(actualValues, expected, path) {
4553
- if (isNegativeMatcher(expected)) {
4554
- return !actualValues.some((actual) => matchPositiveField(actual, expected.not, path));
4555
- }
4556
- return actualValues.some((actual) => matchPositiveField(actual, expected, path));
4557
- }
4558
- function matchPositiveField(actual, expected, path) {
4559
- if (typeof expected === "string" || Array.isArray(expected)) {
4560
- return stringCandidates(actual).some((candidate) => matchString(candidate, expected, {
4561
- segmentSafe: path.endsWith("_path") || path.endsWith(".path")
4562
- }));
4563
- }
4564
- if (Array.isArray(actual)) {
4565
- return actual.some((item) => item === expected);
4566
- }
4567
- return actual === expected;
4568
- }
4569
- function stringCandidates(actual) {
4570
- if (actual === undefined)
4571
- return [];
4572
- if (Array.isArray(actual)) {
4573
- return actual.flatMap((item) => isPrimitiveFieldValue(item) ? [String(item)] : []);
4574
- }
4575
- return [String(actual)];
4576
- }
4577
- function isPrimitiveFieldValue(value) {
4578
- return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
4579
- }
4580
- function isNegativeMatcher(value) {
4581
- return Boolean(value && typeof value === "object" && !Array.isArray(value) && "not" in value);
4582
- }
4583
4529
  function eventMatchesFilter(event, filter) {
4584
4530
  return matchString(event.source, filter.source) && matchString(event.type, filter.type) && matchString(event.subject, filter.subject) && matchString(event.severity, filter.severity) && matchRecord(event.data, filter.data) && matchRecord(event.metadata, filter.metadata);
4585
4531
  }
@@ -4595,14 +4541,6 @@ var HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME";
4595
4541
  function getEventsDataDir(override) {
4596
4542
  return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join(homedir(), ".hasna", "events");
4597
4543
  }
4598
- function getActiveEventsDirEnv() {
4599
- if (process.env[HASNA_EVENTS_DIR_ENV])
4600
- return HASNA_EVENTS_DIR_ENV;
4601
- if (process.env[HASNA_EVENTS_HOME_ENV])
4602
- return HASNA_EVENTS_HOME_ENV;
4603
- return null;
4604
- }
4605
-
4606
4544
  class JsonEventsStore {
4607
4545
  dataDir;
4608
4546
  channelsPath;
@@ -4714,52 +4652,6 @@ class JsonEventsStore {
4714
4652
  });
4715
4653
  }
4716
4654
  }
4717
- async function getEventsStatus(dataDir) {
4718
- const store = new JsonEventsStore(dataDir);
4719
- await store.init();
4720
- const [channels, events, deliveries] = await Promise.all([
4721
- store.listChannels(),
4722
- store.listEvents(),
4723
- store.listDeliveries()
4724
- ]);
4725
- const transports = channels.reduce((counts, channel) => {
4726
- counts[channel.transport] = (counts[channel.transport] ?? 0) + 1;
4727
- return counts;
4728
- }, {});
4729
- return {
4730
- service: "events",
4731
- schemaVersion: "1.0",
4732
- dataDir: store.dataDir,
4733
- env: {
4734
- primary: HASNA_EVENTS_DIR_ENV,
4735
- fallback: HASNA_EVENTS_HOME_ENV,
4736
- active: getActiveEventsDirEnv()
4737
- },
4738
- files: {
4739
- channels: statusFile(store.dataDir, "channels.json", channels.length),
4740
- events: statusFile(store.dataDir, "events.json", events.length),
4741
- deliveries: statusFile(store.dataDir, "deliveries.json", deliveries.length)
4742
- },
4743
- counts: {
4744
- channels: channels.length,
4745
- enabledChannels: channels.filter((channel) => channel.enabled).length,
4746
- disabledChannels: channels.filter((channel) => !channel.enabled).length,
4747
- events: events.length,
4748
- deliveries: deliveries.length
4749
- },
4750
- transports,
4751
- safety: {
4752
- includesEventPayloads: false,
4753
- includesWebhookSecrets: false,
4754
- listOutputsRedactSecrets: true,
4755
- statusOutputIsMetadataOnly: true
4756
- }
4757
- };
4758
- }
4759
- function statusFile(dataDir, fileName, records) {
4760
- const path = join(dataDir, fileName);
4761
- return { path, exists: existsSync(path), records };
4762
- }
4763
4655
  var DEFAULT_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
4764
4656
  function buildSignatureBase(timestamp, body) {
4765
4657
  return `${timestamp}.${body}`;
@@ -4985,7 +4877,7 @@ class EventsClient {
4985
4877
  }
4986
4878
  return deliveries;
4987
4879
  }
4988
- async matchChannel(id, input = {}) {
4880
+ async testChannel(id, input = {}) {
4989
4881
  const channel = await this.store.getChannel(id);
4990
4882
  if (!channel)
4991
4883
  throw new Error(`Channel not found: ${id}`);
@@ -5002,34 +4894,6 @@ class EventsClient {
5002
4894
  time: input.time,
5003
4895
  id: input.id
5004
4896
  });
5005
- const matched = channelMatchesEvent(channel, event);
5006
- return {
5007
- channelId: channel.id,
5008
- matched,
5009
- event,
5010
- filters: channel.filters,
5011
- reason: matched ? undefined : channel.enabled ? "event did not match channel filters" : "channel is disabled"
5012
- };
5013
- }
5014
- async testChannel(id, input = {}, options = {}) {
5015
- const channel = await this.store.getChannel(id);
5016
- if (!channel)
5017
- throw new Error(`Channel not found: ${id}`);
5018
- const match = await this.matchChannel(id, input);
5019
- const event = match.event;
5020
- if (options.honorFilters && !match.matched) {
5021
- const timestamp = new Date().toISOString();
5022
- const result2 = createDeliveryResult(event, channel, [{
5023
- attempt: 1,
5024
- status: "skipped",
5025
- startedAt: timestamp,
5026
- completedAt: timestamp,
5027
- error: match.reason
5028
- }]);
5029
- result2.metadata = { reason: "filter_mismatch" };
5030
- await this.store.appendDelivery(result2);
5031
- return result2;
5032
- }
5033
4897
  const eventForChannel = await this.applyRedaction(event, channel);
5034
4898
  const result = await this.deliverWithRetry(eventForChannel, channel);
5035
4899
  await this.store.appendDelivery(result);
@@ -5140,76 +5004,6 @@ function normalizeRetryPolicy(policy) {
5140
5004
  multiplier: Math.max(1, policy?.multiplier ?? 2)
5141
5005
  };
5142
5006
  }
5143
- function parseFieldMatchers(values, label, typed = false) {
5144
- if (!values?.length)
5145
- return;
5146
- const result = {};
5147
- for (const value of values) {
5148
- const parsed = parseMatcherExpression(value, label);
5149
- const path = parsed.path;
5150
- if (path in result)
5151
- throw new Error(`Duplicate ${label} filter path: ${path}`);
5152
- const matcherValue = typed ? parseTypedMatcherValue(parsed.rawValue, label) : parsed.rawValue;
5153
- result[path] = parsed.negated ? { not: matcherValue } : matcherValue;
5154
- }
5155
- return result;
5156
- }
5157
- function parseFilterOptions(options) {
5158
- const filter2 = {};
5159
- if (options.source)
5160
- filter2.source = options.source;
5161
- if (options.type)
5162
- filter2.type = options.type;
5163
- if (options.subject)
5164
- filter2.subject = options.subject;
5165
- if (options.severity)
5166
- filter2.severity = options.severity;
5167
- const data = mergeMatchers(parseFieldMatchers(options.data, "data"), parseFieldMatchers(options.dataJson, "data-json", true));
5168
- const metadata = mergeMatchers(parseFieldMatchers(options.metadata, "metadata"), parseFieldMatchers(options.metadataJson, "metadata-json", true));
5169
- if (Object.keys(data).length > 0)
5170
- filter2.data = data;
5171
- if (Object.keys(metadata).length > 0)
5172
- filter2.metadata = metadata;
5173
- return Object.keys(filter2).length > 0 ? [filter2] : undefined;
5174
- }
5175
- function mergeMatchers(...records) {
5176
- const result = {};
5177
- for (const record of records) {
5178
- if (!record)
5179
- continue;
5180
- for (const [path, value] of Object.entries(record)) {
5181
- if (path in result)
5182
- throw new Error(`Duplicate filter path: ${path}`);
5183
- result[path] = value;
5184
- }
5185
- }
5186
- return result;
5187
- }
5188
- function parseTypedMatcherValue(value, label) {
5189
- const parsed = JSON.parse(value);
5190
- if (parsed === null || typeof parsed === "string" || typeof parsed === "number" || typeof parsed === "boolean" || Array.isArray(parsed) && parsed.every((item) => typeof item === "string")) {
5191
- return parsed;
5192
- }
5193
- throw new Error(`${label} filter JSON values must be string, string[], number, boolean, or null`);
5194
- }
5195
- function parseMatcherExpression(value, label) {
5196
- const negativeSeparator = value.indexOf("!=");
5197
- if (negativeSeparator > 0) {
5198
- return {
5199
- path: value.slice(0, negativeSeparator),
5200
- rawValue: value.slice(negativeSeparator + 2),
5201
- negated: true
5202
- };
5203
- }
5204
- const separator = value.indexOf("=");
5205
- if (separator <= 0)
5206
- throw new Error(`Invalid ${label} filter, expected path=value or path!=value: ${value}`);
5207
- return {
5208
- path: value.slice(0, separator),
5209
- rawValue: value.slice(separator + 1),
5210
- negated: false
5211
- };
5212
- }
5213
5007
  function parseJsonObject(value, fallback) {
5214
5008
  if (!value)
5215
5009
  return fallback;
@@ -5231,6 +5025,18 @@ function parseHeaders(values) {
5231
5025
  }
5232
5026
  return headers;
5233
5027
  }
5028
+ function parseFilter(options) {
5029
+ const filter2 = {};
5030
+ if (options.source)
5031
+ filter2.source = options.source;
5032
+ if (options.type)
5033
+ filter2.type = options.type;
5034
+ if (options.subject)
5035
+ filter2.subject = options.subject;
5036
+ if (options.severity)
5037
+ filter2.severity = options.severity;
5038
+ return Object.keys(filter2).length > 0 ? [filter2] : undefined;
5039
+ }
5234
5040
  function createClient(options) {
5235
5041
  if (options.createClient)
5236
5042
  return options.createClient();
@@ -5248,16 +5054,16 @@ function hasJsonOption(options) {
5248
5054
  function wantsJson(actionOptions, command) {
5249
5055
  return hasJsonOption(actionOptions) || hasJsonOption(command);
5250
5056
  }
5251
- function registerChannelCommands(program, options) {
5252
- const channels = program.command(options.channelsCommandName ?? "channels").description("Manage Hasna event channels");
5253
- channels.command("add").description("Add or replace a channel").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--data <path=value...>", "Event data field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard", collectValues, []).option("--metadata <path=value...>", "Event metadata field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard", collectValues, []).option("--data-json <path=json...>", "Event data field filter with typed JSON value; path!=json negatives supported", collectValues, []).option("--metadata-json <path=json...>", "Event metadata field filter with typed JSON value; path!=json negatives supported", collectValues, []).option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions, command) => {
5057
+ function registerWebhookCommands(program, options) {
5058
+ const webhooks = program.command(options.webhooksCommandName ?? "webhooks").description("Manage Hasna event webhook subscriptions");
5059
+ webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions, command) => {
5254
5060
  const timestamp = new Date().toISOString();
5255
5061
  const channel = {
5256
5062
  id: actionOptions.id,
5257
5063
  name: actionOptions.name,
5258
5064
  enabled: !actionOptions.disabled,
5259
5065
  transport: actionOptions.transport,
5260
- filters: parseFilterOptions(actionOptions),
5066
+ filters: parseFilter(actionOptions),
5261
5067
  retry: actionOptions.retryAttempts || actionOptions.retryBackoffMs ? { maxAttempts: actionOptions.retryAttempts, backoffMs: actionOptions.retryBackoffMs } : undefined,
5262
5068
  redact: actionOptions.redact?.length ? { paths: actionOptions.redact } : undefined,
5263
5069
  createdAt: timestamp,
@@ -5273,51 +5079,35 @@ function registerChannelCommands(program, options) {
5273
5079
  const saved = await createClient(options).addChannel(channel);
5274
5080
  print(sanitizeChannelForOutput(saved), wantsJson(actionOptions, command), `Added ${saved.transport} channel ${saved.id}`);
5275
5081
  });
5276
- channels.command("list").description("List configured channels").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
5277
- const channels2 = await createClient(options).listChannels();
5082
+ webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
5083
+ const channels = await createClient(options).listChannels();
5278
5084
  if (wantsJson(actionOptions, command)) {
5279
- console.log(JSON.stringify(sanitizeChannelsForOutput(channels2), null, 2));
5085
+ console.log(JSON.stringify(sanitizeChannelsForOutput(channels), null, 2));
5280
5086
  return;
5281
5087
  }
5282
- if (!channels2.length) {
5088
+ if (!channels.length) {
5283
5089
  console.log("No channels configured.");
5284
5090
  return;
5285
5091
  }
5286
- for (const channel of channels2) {
5092
+ for (const channel of channels) {
5287
5093
  console.log(`${channel.id} ${channel.enabled ? "enabled" : "disabled"} ${channel.transport} ${channel.webhook?.url ?? channel.command?.command ?? channel.transport}`);
5288
5094
  }
5289
5095
  });
5290
- channels.command("status").description("Show events channel storage status").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
5291
- const status = await getEventsStatus(options.dataDir);
5292
- print(status, wantsJson(actionOptions, command), `events dataDir: ${status.dataDir}`);
5293
- });
5294
- channels.command("remove").description("Remove a channel").argument("<id>", "Channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
5096
+ webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
5295
5097
  const removed = await createClient(options).removeChannel(id);
5296
5098
  print({ removed }, wantsJson(actionOptions, command), removed ? `Removed ${id}` : `Channel not found: ${id}`);
5297
5099
  });
5298
- channels.command("test").description("Send a test event to one channel").argument("<id>", "Channel identifier").option("--source <source>", "Event source override").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--honor-filters", "Skip delivery when the sample event does not match channel filters", false).option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
5100
+ webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
5299
5101
  const result = await createClient(options).testChannel(id, {
5300
- source: actionOptions.source ?? options.source,
5301
- type: actionOptions.type,
5302
- subject: actionOptions.subject ?? id,
5303
- message: actionOptions.message,
5304
- data: parseJsonObject(actionOptions.data, { test: true }),
5305
- metadata: parseJsonObject(actionOptions.metadata, {})
5306
- }, { honorFilters: actionOptions.honorFilters });
5307
- print(result, wantsJson(actionOptions, command), `${result.status}: ${result.channelId}`);
5308
- });
5309
- channels.command("match").description("Check whether a sample event matches one channel without delivering").argument("<id>", "Channel identifier").option("--source <source>", "Event source override").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events match preview").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
5310
- const result = await createClient(options).matchChannel(id, {
5311
- source: actionOptions.source ?? options.source,
5102
+ source: options.source,
5312
5103
  type: actionOptions.type,
5313
5104
  subject: actionOptions.subject ?? id,
5314
5105
  message: actionOptions.message,
5315
- data: parseJsonObject(actionOptions.data, { test: true }),
5316
- metadata: parseJsonObject(actionOptions.metadata, {})
5106
+ data: parseJsonObject(actionOptions.data, { test: true })
5317
5107
  });
5318
- print(result, wantsJson(actionOptions, command), `${result.matched ? "matched" : "skipped"}: ${result.channelId}`);
5108
+ print(result, wantsJson(actionOptions, command), `${result.status}: ${result.channelId}`);
5319
5109
  });
5320
- return channels;
5110
+ return webhooks;
5321
5111
  }
5322
5112
  function registerEventCommands(program, options) {
5323
5113
  const events = program.command(options.eventsCommandName ?? "events").description("Emit, list, and replay Hasna events");
@@ -5365,7 +5155,7 @@ function registerEventCommands(program, options) {
5365
5155
  return events;
5366
5156
  }
5367
5157
  function registerEventsCommands(program, options) {
5368
- registerChannelCommands(program, options);
5158
+ registerWebhookCommands(program, options);
5369
5159
  registerEventCommands(program, options);
5370
5160
  }
5371
5161
  function parseNumber(value) {
package/dist/mcp/index.js CHANGED
@@ -2040,7 +2040,7 @@ var init_sync_dir = __esm(() => {
2040
2040
  var require_package = __commonJS((exports, module) => {
2041
2041
  module.exports = {
2042
2042
  name: "@hasna/instructions",
2043
- version: "0.4.3",
2043
+ version: "0.4.4",
2044
2044
  description: "AI coding agent instruction & configuration manager \u2014 store, version, apply, and share all your AI coding configs. CLI + MCP + HTTP API (instructions-serve) + generated SDK + Dashboard.",
2045
2045
  type: "module",
2046
2046
  main: "dist/index.js",
@@ -2,7 +2,7 @@
2
2
  // @bun
3
3
  var __require = import.meta.require;
4
4
 
5
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/compose.js
5
+ // node_modules/hono/dist/compose.js
6
6
  var compose = (middleware, onError, onNotFound) => {
7
7
  return (context, next) => {
8
8
  let index = -1;
@@ -46,39 +46,21 @@ var compose = (middleware, onError, onNotFound) => {
46
46
  };
47
47
  };
48
48
 
49
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/request/constants.js
49
+ // node_modules/hono/dist/request/constants.js
50
50
  var GET_MATCH_RESULT = /* @__PURE__ */ Symbol();
51
51
 
52
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/utils/buffer.js
53
- var bufferToFormData = (arrayBuffer, contentType) => {
54
- const response = new Response(arrayBuffer, {
55
- headers: {
56
- "Content-Type": contentType.replace(/^[^;]+/, (mediaType) => mediaType.toLowerCase())
57
- }
58
- });
59
- return response.formData();
60
- };
61
-
62
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/utils/body.js
63
- var isRawRequest = (request) => ("headers" in request);
52
+ // node_modules/hono/dist/utils/body.js
64
53
  var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
65
54
  const { all = false, dot = false } = options;
66
- const headers = isRawRequest(request) ? request.headers : request.raw.headers;
55
+ const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
67
56
  const contentType = headers.get("Content-Type");
68
- const mediaType = contentType?.split(";")[0].trim().toLowerCase();
69
- if (mediaType === "multipart/form-data" || mediaType === "application/x-www-form-urlencoded") {
57
+ if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) {
70
58
  return parseFormData(request, { all, dot });
71
59
  }
72
60
  return {};
73
61
  };
74
62
  async function parseFormData(request, options) {
75
- const headers = isRawRequest(request) ? request.headers : request.raw.headers;
76
- const arrayBuffer = await request.arrayBuffer();
77
- const formDataPromise = bufferToFormData(arrayBuffer, headers.get("Content-Type") || "");
78
- if (!isRawRequest(request)) {
79
- request.bodyCache.formData = formDataPromise;
80
- }
81
- const formData = await formDataPromise;
63
+ const formData = await request.formData();
82
64
  if (formData) {
83
65
  return convertFormDataToBodyData(formData, options);
84
66
  }
@@ -138,7 +120,7 @@ var handleParsingNestedValues = (form, key, value) => {
138
120
  });
139
121
  };
140
122
 
141
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/utils/url.js
123
+ // node_modules/hono/dist/utils/url.js
142
124
  var splitPath = (path) => {
143
125
  const paths = path.split("/");
144
126
  if (paths[0] === "") {
@@ -338,7 +320,7 @@ var getQueryParams = (url, key) => {
338
320
  };
339
321
  var decodeURIComponent_ = decodeURIComponent;
340
322
 
341
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/request.js
323
+ // node_modules/hono/dist/request.js
342
324
  var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
343
325
  var HonoRequest = class {
344
326
  raw;
@@ -420,9 +402,6 @@ var HonoRequest = class {
420
402
  arrayBuffer() {
421
403
  return this.#cachedBody("arrayBuffer");
422
404
  }
423
- bytes() {
424
- return this.#cachedBody("arrayBuffer").then((buffer) => new Uint8Array(buffer));
425
- }
426
405
  blob() {
427
406
  return this.#cachedBody("blob");
428
407
  }
@@ -452,7 +431,7 @@ var HonoRequest = class {
452
431
  }
453
432
  };
454
433
 
455
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/utils/html.js
434
+ // node_modules/hono/dist/utils/html.js
456
435
  var HtmlEscapedCallbackPhase = {
457
436
  Stringify: 1,
458
437
  BeforeStream: 2,
@@ -490,7 +469,7 @@ var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) =>
490
469
  }
491
470
  };
492
471
 
493
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/context.js
472
+ // node_modules/hono/dist/context.js
494
473
  var TEXT_PLAIN = "text/plain; charset=UTF-8";
495
474
  var setDefaultContentType = (contentType, headers) => {
496
475
  return {
@@ -657,7 +636,7 @@ var Context = class {
657
636
  };
658
637
  };
659
638
 
660
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/router.js
639
+ // node_modules/hono/dist/router.js
661
640
  var METHOD_NAME_ALL = "ALL";
662
641
  var METHOD_NAME_ALL_LOWERCASE = "all";
663
642
  var METHODS = ["get", "post", "put", "delete", "options", "patch"];
@@ -665,10 +644,10 @@ var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is
665
644
  var UnsupportedPathError = class extends Error {
666
645
  };
667
646
 
668
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/utils/constants.js
647
+ // node_modules/hono/dist/utils/constants.js
669
648
  var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
670
649
 
671
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/hono-base.js
650
+ // node_modules/hono/dist/hono-base.js
672
651
  var notFoundHandler = (c) => {
673
652
  return c.text("404 Not Found", 404);
674
653
  };
@@ -759,7 +738,7 @@ var Hono = class _Hono {
759
738
  handler = async (c, next) => (await compose([], app.errorHandler)(c, () => r.handler(c, next))).res;
760
739
  handler[COMPOSED_HANDLER] = r.handler;
761
740
  }
762
- subApp.#addRoute(r.method, r.path, handler, r.basePath);
741
+ subApp.#addRoute(r.method, r.path, handler);
763
742
  });
764
743
  return this;
765
744
  }
@@ -806,7 +785,7 @@ var Hono = class _Hono {
806
785
  const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
807
786
  return (request) => {
808
787
  const url = new URL(request.url);
809
- url.pathname = this.getPath(request).slice(pathPrefixLength) || "/";
788
+ url.pathname = url.pathname.slice(pathPrefixLength) || "/";
810
789
  return new Request(url, request);
811
790
  };
812
791
  })();
@@ -820,15 +799,10 @@ var Hono = class _Hono {
820
799
  this.#addRoute(METHOD_NAME_ALL, mergePath(path, "*"), handler);
821
800
  return this;
822
801
  }
823
- #addRoute(method, path, handler, baseRoutePath) {
802
+ #addRoute(method, path, handler) {
824
803
  method = method.toUpperCase();
825
804
  path = mergePath(this._basePath, path);
826
- const r = {
827
- basePath: baseRoutePath !== undefined ? mergePath(this._basePath, baseRoutePath) : this._basePath,
828
- path,
829
- method,
830
- handler
831
- };
805
+ const r = { basePath: this._basePath, path, method, handler };
832
806
  this.router.add(method, path, [handler, r]);
833
807
  this.routes.push(r);
834
808
  }
@@ -892,7 +866,7 @@ var Hono = class _Hono {
892
866
  };
893
867
  };
894
868
 
895
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/router/reg-exp-router/matcher.js
869
+ // node_modules/hono/dist/router/reg-exp-router/matcher.js
896
870
  var emptyParam = [];
897
871
  function match(method, path) {
898
872
  const matchers = this.buildAllMatchers();
@@ -913,7 +887,7 @@ function match(method, path) {
913
887
  return match2(method, path);
914
888
  }
915
889
 
916
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/router/reg-exp-router/node.js
890
+ // node_modules/hono/dist/router/reg-exp-router/node.js
917
891
  var LABEL_REG_EXP_STR = "[^/]+";
918
892
  var ONLY_WILDCARD_REG_EXP_STR = ".*";
919
893
  var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
@@ -1017,7 +991,7 @@ var Node = class _Node {
1017
991
  }
1018
992
  };
1019
993
 
1020
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/router/reg-exp-router/trie.js
994
+ // node_modules/hono/dist/router/reg-exp-router/trie.js
1021
995
  var Trie = class {
1022
996
  #context = { varIndex: 0 };
1023
997
  #root = new Node;
@@ -1073,7 +1047,7 @@ var Trie = class {
1073
1047
  }
1074
1048
  };
1075
1049
 
1076
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/router/reg-exp-router/router.js
1050
+ // node_modules/hono/dist/router/reg-exp-router/router.js
1077
1051
  var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
1078
1052
  var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
1079
1053
  function buildWildcardRegExp(path) {
@@ -1238,7 +1212,7 @@ var RegExpRouter = class {
1238
1212
  }
1239
1213
  };
1240
1214
 
1241
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/router/reg-exp-router/prepared-router.js
1215
+ // node_modules/hono/dist/router/reg-exp-router/prepared-router.js
1242
1216
  var PreparedRegExpRouter = class {
1243
1217
  name = "PreparedRegExpRouter";
1244
1218
  #matchers;
@@ -1310,7 +1284,7 @@ var PreparedRegExpRouter = class {
1310
1284
  match = match;
1311
1285
  };
1312
1286
 
1313
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/router/smart-router/router.js
1287
+ // node_modules/hono/dist/router/smart-router/router.js
1314
1288
  var SmartRouter = class {
1315
1289
  name = "SmartRouter";
1316
1290
  #routers = [];
@@ -1365,7 +1339,7 @@ var SmartRouter = class {
1365
1339
  }
1366
1340
  };
1367
1341
 
1368
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/router/trie-router/node.js
1342
+ // node_modules/hono/dist/router/trie-router/node.js
1369
1343
  var emptyParams = /* @__PURE__ */ Object.create(null);
1370
1344
  var hasChildren = (children) => {
1371
1345
  for (const _ in children) {
@@ -1534,7 +1508,7 @@ var Node2 = class _Node2 {
1534
1508
  }
1535
1509
  };
1536
1510
 
1537
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/router/trie-router/router.js
1511
+ // node_modules/hono/dist/router/trie-router/router.js
1538
1512
  var TrieRouter = class {
1539
1513
  name = "TrieRouter";
1540
1514
  #node;
@@ -1556,7 +1530,7 @@ var TrieRouter = class {
1556
1530
  }
1557
1531
  };
1558
1532
 
1559
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/hono.js
1533
+ // node_modules/hono/dist/hono.js
1560
1534
  var Hono2 = class extends Hono {
1561
1535
  constructor(options = {}) {
1562
1536
  super(options);
@@ -1566,18 +1540,24 @@ var Hono2 = class extends Hono {
1566
1540
  }
1567
1541
  };
1568
1542
 
1569
- // node_modules/.pnpm/hono@4.12.28/node_modules/hono/dist/middleware/cors/index.js
1543
+ // node_modules/hono/dist/middleware/cors/index.js
1570
1544
  var cors = (options) => {
1571
- const opts = {
1545
+ const defaults = {
1572
1546
  origin: "*",
1573
1547
  allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
1574
1548
  allowHeaders: [],
1575
- exposeHeaders: [],
1549
+ exposeHeaders: []
1550
+ };
1551
+ const opts = {
1552
+ ...defaults,
1576
1553
  ...options
1577
1554
  };
1578
1555
  const findAllowOrigin = ((optsOrigin) => {
1579
1556
  if (typeof optsOrigin === "string") {
1580
1557
  if (optsOrigin === "*") {
1558
+ if (opts.credentials) {
1559
+ return (origin) => origin || null;
1560
+ }
1581
1561
  return () => optsOrigin;
1582
1562
  } else {
1583
1563
  return (origin) => optsOrigin === origin ? origin : null;
@@ -1612,7 +1592,7 @@ var cors = (options) => {
1612
1592
  set("Access-Control-Expose-Headers", opts.exposeHeaders.join(","));
1613
1593
  }
1614
1594
  if (c.req.method === "OPTIONS") {
1615
- if (opts.origin !== "*") {
1595
+ if (opts.origin !== "*" || opts.credentials) {
1616
1596
  set("Vary", "Origin");
1617
1597
  }
1618
1598
  if (opts.maxAge != null) {
@@ -1642,7 +1622,7 @@ var cors = (options) => {
1642
1622
  });
1643
1623
  }
1644
1624
  await next();
1645
- if (opts.origin !== "*") {
1625
+ if (opts.origin !== "*" || opts.credentials) {
1646
1626
  c.header("Vary", "Origin", { append: true });
1647
1627
  }
1648
1628
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/instructions",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "AI coding agent instruction & configuration manager — store, version, apply, and share all your AI coding configs. CLI + MCP + HTTP API (instructions-serve) + generated SDK + Dashboard.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",