@fulmenhq/tsfulmen 0.2.2 → 0.2.3

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.
@@ -1,6 +1,7 @@
1
1
  import { access, readFile, mkdir, writeFile } from 'fs/promises';
2
2
  import { dirname, extname, join, relative } from 'path';
3
3
  import { parse, stringify } from 'yaml';
4
+ import addFormats from 'ajv-formats';
4
5
  import { spawn } from 'child_process';
5
6
  import { fileURLToPath } from 'url';
6
7
  import glob from 'fast-glob';
@@ -13,7 +14,6 @@ import Ajv from 'ajv';
13
14
  import Ajv2019 from 'ajv/dist/2019';
14
15
  import Ajv2020 from 'ajv/dist/2020';
15
16
  import AjvDraft04 from 'ajv-draft-04';
16
- import addFormats from 'ajv-formats';
17
17
 
18
18
  var __defProp = Object.defineProperty;
19
19
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -729,6 +729,27 @@ var init_types = __esm({
729
729
  "src/telemetry/types.ts"() {
730
730
  }
731
731
  });
732
+ function applyFulmenAjvFormats(ajv, options = {}) {
733
+ const mode = options.mode ?? "fast";
734
+ const formats = options.formats ?? DEFAULT_FORMATS;
735
+ addFormats(ajv, { mode, formats });
736
+ return ajv;
737
+ }
738
+ var DEFAULT_FORMATS;
739
+ var init_ajv_formats = __esm({
740
+ "src/schema/ajv-formats.ts"() {
741
+ DEFAULT_FORMATS = [
742
+ "date-time",
743
+ "email",
744
+ "hostname",
745
+ "ipv4",
746
+ "ipv6",
747
+ "uri",
748
+ "uri-reference",
749
+ "uuid"
750
+ ];
751
+ }
752
+ });
732
753
 
733
754
  // src/schema/errors.ts
734
755
  var errors_exports = {};
@@ -3294,7 +3315,9 @@ __export(foundry_exports, {
3294
3315
  clearMimeTypeCache: () => clearMimeTypeCache,
3295
3316
  clearPatternCache: () => clearPatternCache,
3296
3317
  createBearerTokenAuth: () => createBearerTokenAuth,
3318
+ createConfigReloadEndpoint: () => createConfigReloadEndpoint,
3297
3319
  createConfigReloadHandler: () => createConfigReloadHandler,
3320
+ createControlDiscoveryEndpoint: () => createControlDiscoveryEndpoint,
3298
3321
  createDoubleTapTracker: () => createDoubleTapTracker,
3299
3322
  createSignalEndpoint: () => createSignalEndpoint,
3300
3323
  createSignalManager: () => createSignalManager,
@@ -4350,6 +4373,7 @@ var init_cli = __esm({
4350
4373
  // src/schema/index.ts
4351
4374
  var init_schema = __esm({
4352
4375
  "src/schema/index.ts"() {
4376
+ init_ajv_formats();
4353
4377
  init_cli();
4354
4378
  init_errors();
4355
4379
  init_export();
@@ -4516,10 +4540,7 @@ function createAjv(dialect) {
4516
4540
  // Enable async schema loading for YAML references
4517
4541
  loadSchema: loadReferencedSchema
4518
4542
  });
4519
- addFormats(ajv, {
4520
- mode: "fast",
4521
- formats: ["date-time", "email", "hostname", "ipv4", "ipv6", "uri", "uri-reference"]
4522
- });
4543
+ applyFulmenAjvFormats(ajv);
4523
4544
  return ajv;
4524
4545
  }
4525
4546
  async function getAjv(dialect) {
@@ -4765,6 +4786,7 @@ var ajvInstances, metaschemaReady, schemaCache;
4765
4786
  var init_validator = __esm({
4766
4787
  "src/schema/validator.ts"() {
4767
4788
  init_telemetry();
4789
+ init_ajv_formats();
4768
4790
  init_errors();
4769
4791
  init_registry2();
4770
4792
  init_utils();
@@ -4989,6 +5011,224 @@ var init_capabilities2 = __esm({
4989
5011
  }
4990
5012
  });
4991
5013
 
5014
+ // src/foundry/signals/config-reload-endpoint.ts
5015
+ function createConfigReloadEndpoint(options) {
5016
+ const { loader, validator, onReload: onReload2, auth, rateLimit, logger, telemetry } = options;
5017
+ return async (payload, req) => {
5018
+ const correlationId = payload.correlation_id ?? generateCorrelationId2();
5019
+ const authResult = await auth(req);
5020
+ if (!authResult.authenticated) {
5021
+ if (logger) {
5022
+ logger.warn("Config reload endpoint: authentication failed", {
5023
+ correlation_id: correlationId,
5024
+ reason: authResult.reason
5025
+ });
5026
+ }
5027
+ if (telemetry) {
5028
+ telemetry.emit("fulmen.config.http_endpoint.auth_failed", {
5029
+ correlation_id: correlationId
5030
+ });
5031
+ }
5032
+ return {
5033
+ status: "error",
5034
+ error: "authentication_failed",
5035
+ message: authResult.reason || "Authentication required",
5036
+ statusCode: 401
5037
+ };
5038
+ }
5039
+ const identity = authResult.identity || "unknown";
5040
+ if (rateLimit) {
5041
+ const rateLimitResult = await rateLimit(identity);
5042
+ if (!rateLimitResult.allowed) {
5043
+ if (logger) {
5044
+ logger.warn("Config reload endpoint: rate limit exceeded", {
5045
+ correlation_id: correlationId,
5046
+ identity
5047
+ });
5048
+ }
5049
+ if (telemetry) {
5050
+ telemetry.emit("fulmen.config.http_endpoint.rate_limited", {
5051
+ correlation_id: correlationId
5052
+ });
5053
+ }
5054
+ return {
5055
+ status: "error",
5056
+ error: "rate_limit_exceeded",
5057
+ message: "Rate limit exceeded. Please try again later.",
5058
+ statusCode: 429
5059
+ };
5060
+ }
5061
+ }
5062
+ if (telemetry) {
5063
+ telemetry.emit("fulmen.config.http_endpoint.reload_requested", {
5064
+ correlation_id: correlationId
5065
+ });
5066
+ }
5067
+ try {
5068
+ const config = await loader();
5069
+ if (validator) {
5070
+ const validation = await validator(config);
5071
+ if (!validation.valid) {
5072
+ if (logger) {
5073
+ logger.warn("Config reload endpoint: validation failed", {
5074
+ correlation_id: correlationId,
5075
+ error_count: validation.errors?.length ?? 0
5076
+ });
5077
+ }
5078
+ if (telemetry) {
5079
+ telemetry.emit("fulmen.config.http_endpoint.reload_rejected", {
5080
+ correlation_id: correlationId,
5081
+ reason: "validation_failed"
5082
+ });
5083
+ }
5084
+ return {
5085
+ status: "error",
5086
+ error: "validation_failed",
5087
+ message: "Configuration validation failed",
5088
+ validation_errors: validation.errors,
5089
+ statusCode: 422
5090
+ };
5091
+ }
5092
+ }
5093
+ if (onReload2) {
5094
+ await onReload2(config);
5095
+ }
5096
+ if (telemetry) {
5097
+ telemetry.emit("fulmen.config.http_endpoint.reload_accepted", {
5098
+ correlation_id: correlationId
5099
+ });
5100
+ }
5101
+ if (logger) {
5102
+ logger.info("Config reload endpoint: reload accepted", {
5103
+ correlation_id: correlationId,
5104
+ reason: payload.reason
5105
+ });
5106
+ }
5107
+ return {
5108
+ status: "reloaded",
5109
+ correlation_id: correlationId,
5110
+ message: "Configuration reloaded",
5111
+ statusCode: 200
5112
+ };
5113
+ } catch (error) {
5114
+ if (logger) {
5115
+ logger.warn("Config reload endpoint: reload failed", {
5116
+ correlation_id: correlationId,
5117
+ error: error instanceof Error ? error.message : String(error)
5118
+ });
5119
+ }
5120
+ if (telemetry) {
5121
+ telemetry.emit("fulmen.config.http_endpoint.reload_error", {
5122
+ correlation_id: correlationId,
5123
+ error_type: error instanceof Error ? error.constructor.name : "unknown"
5124
+ });
5125
+ }
5126
+ return {
5127
+ status: "error",
5128
+ error: "reload_failed",
5129
+ message: error instanceof Error ? error.message : String(error),
5130
+ statusCode: 500
5131
+ };
5132
+ }
5133
+ };
5134
+ }
5135
+ function generateCorrelationId2() {
5136
+ return `cfg-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
5137
+ }
5138
+ var init_config_reload_endpoint = __esm({
5139
+ "src/foundry/signals/config-reload-endpoint.ts"() {
5140
+ }
5141
+ });
5142
+
5143
+ // src/appidentity/runtime.ts
5144
+ function detectRuntime() {
5145
+ const versions = process.versions;
5146
+ if (typeof versions.bun === "string" && versions.bun.length > 0) {
5147
+ return { name: "bun", version: versions.bun };
5148
+ }
5149
+ if (typeof versions.node === "string" && versions.node.length > 0) {
5150
+ return { name: "node", version: versions.node };
5151
+ }
5152
+ return { name: "unknown" };
5153
+ }
5154
+ function buildRuntimeInfo(options = {}) {
5155
+ const runtime = detectRuntime();
5156
+ const serviceName = options.serviceName ?? options.identity?.app.binary_name ?? "unknown-service";
5157
+ const vendor = options.vendor ?? options.identity?.app.vendor;
5158
+ return {
5159
+ service: {
5160
+ name: serviceName,
5161
+ vendor,
5162
+ version: options.version
5163
+ },
5164
+ runtime,
5165
+ platform: {
5166
+ os: process.platform,
5167
+ arch: process.arch
5168
+ }
5169
+ };
5170
+ }
5171
+ var init_runtime = __esm({
5172
+ "src/appidentity/runtime.ts"() {
5173
+ }
5174
+ });
5175
+
5176
+ // src/foundry/signals/control-discovery-endpoint.ts
5177
+ function createControlDiscoveryEndpoint(options) {
5178
+ const { identity, version, endpoints, auth, authSummary, logger, telemetry } = options;
5179
+ return async (req) => {
5180
+ if (auth) {
5181
+ const authResult = await auth(req);
5182
+ if (!authResult.authenticated) {
5183
+ if (logger) {
5184
+ logger.warn("Control discovery endpoint: authentication failed", {
5185
+ reason: authResult.reason
5186
+ });
5187
+ }
5188
+ if (telemetry) {
5189
+ telemetry.emit("fulmen.control.discovery.auth_failed", {
5190
+ service: identity.app.binary_name
5191
+ });
5192
+ }
5193
+ return {
5194
+ status: "error",
5195
+ error: "authentication_failed",
5196
+ message: authResult.reason || "Authentication required",
5197
+ statusCode: 401
5198
+ };
5199
+ }
5200
+ }
5201
+ if (telemetry) {
5202
+ telemetry.emit("fulmen.control.discovery.served", {
5203
+ service: identity.app.binary_name
5204
+ });
5205
+ }
5206
+ const runtime = buildRuntimeInfo({ identity, version });
5207
+ return {
5208
+ status: "ok",
5209
+ service: {
5210
+ name: identity.app.binary_name,
5211
+ vendor: identity.app.vendor,
5212
+ version
5213
+ },
5214
+ runtime: {
5215
+ name: runtime.runtime.name,
5216
+ version: runtime.runtime.version,
5217
+ platform: runtime.platform.os,
5218
+ arch: runtime.platform.arch
5219
+ },
5220
+ auth_summary: authSummary,
5221
+ endpoints,
5222
+ statusCode: 200
5223
+ };
5224
+ };
5225
+ }
5226
+ var init_control_discovery_endpoint = __esm({
5227
+ "src/foundry/signals/control-discovery-endpoint.ts"() {
5228
+ init_runtime();
5229
+ }
5230
+ });
5231
+
4992
5232
  // src/foundry/signals/convenience.ts
4993
5233
  async function onShutdown(manager, handler, options = {}) {
4994
5234
  await manager.register("SIGTERM", handler, options);
@@ -5248,7 +5488,7 @@ var init_guards = __esm({
5248
5488
  function createSignalEndpoint(options) {
5249
5489
  const { manager, auth, rateLimit, logger, telemetry, allowedSignals } = options;
5250
5490
  return async (payload, req) => {
5251
- const correlationId = payload.correlation_id ?? generateCorrelationId2();
5491
+ const correlationId = payload.correlation_id ?? generateCorrelationId3();
5252
5492
  const authResult = await auth(req);
5253
5493
  if (!authResult.authenticated) {
5254
5494
  if (logger) {
@@ -5371,7 +5611,7 @@ function normalizeSignalName(signal) {
5371
5611
  }
5372
5612
  return `SIG${upper}`;
5373
5613
  }
5374
- function generateCorrelationId2() {
5614
+ function generateCorrelationId3() {
5375
5615
  return `sig-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
5376
5616
  }
5377
5617
  function createBearerTokenAuth(expectedToken) {
@@ -5838,6 +6078,8 @@ var init_signals = __esm({
5838
6078
  "src/foundry/signals/index.ts"() {
5839
6079
  init_capabilities2();
5840
6080
  init_catalog();
6081
+ init_config_reload_endpoint();
6082
+ init_control_discovery_endpoint();
5841
6083
  init_convenience();
5842
6084
  init_double_tap();
5843
6085
  init_guards();
@@ -5851,6 +6093,6 @@ var init_signals = __esm({
5851
6093
  // src/signals/index.ts
5852
6094
  init_signals();
5853
6095
 
5854
- export { ConfigReloadTracker, SignalManager, createBearerTokenAuth, createConfigReloadHandler, createDoubleTapTracker, createSignalEndpoint, createSignalManager, createSimpleRateLimiter, ensurePOSIX, ensureSignalExitCodesSupported, ensureSupported, ensureWindows, getBehavior, getFallbackMetadata, getHttpFallbackGuidance, getPlatform2 as getPlatform, getPlatformCapabilities2 as getPlatformCapabilities, getSignal, getSignalCatalog, getSignalNumber, getSignalsVersion, getWindowTimeRemaining, getWindowsEvent, handleDoubleTap, handleWindowsFallback, isPOSIX2 as isPOSIX, isWindows2 as isWindows, isWithinWindow, listBehaviors, listSignals, onAnyShutdown, onEmergencyQuit, onReload, onShutdown, onUSR1, onUSR2, requiresFallback, resetDoubleTap, supportsSignal, supportsSignalExitCodes2 as supportsSignalExitCodes };
6096
+ export { ConfigReloadTracker, SignalManager, createBearerTokenAuth, createConfigReloadEndpoint, createConfigReloadHandler, createControlDiscoveryEndpoint, createDoubleTapTracker, createSignalEndpoint, createSignalManager, createSimpleRateLimiter, ensurePOSIX, ensureSignalExitCodesSupported, ensureSupported, ensureWindows, getBehavior, getFallbackMetadata, getHttpFallbackGuidance, getPlatform2 as getPlatform, getPlatformCapabilities2 as getPlatformCapabilities, getSignal, getSignalCatalog, getSignalNumber, getSignalsVersion, getWindowTimeRemaining, getWindowsEvent, handleDoubleTap, handleWindowsFallback, isPOSIX2 as isPOSIX, isWindows2 as isWindows, isWithinWindow, listBehaviors, listSignals, onAnyShutdown, onEmergencyQuit, onReload, onShutdown, onUSR1, onUSR2, requiresFallback, resetDoubleTap, supportsSignal, supportsSignalExitCodes2 as supportsSignalExitCodes };
5855
6097
  //# sourceMappingURL=index.js.map
5856
6098
  //# sourceMappingURL=index.js.map