@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.
- package/CHANGELOG.md +28 -0
- package/README.md +9 -8
- package/dist/appidentity/index.d.ts +30 -108
- package/dist/appidentity/index.js +251 -8
- package/dist/appidentity/index.js.map +1 -1
- package/dist/config/index.d.ts +46 -1
- package/dist/config/index.js +309 -10
- package/dist/config/index.js.map +1 -1
- package/dist/crucible/index.js +249 -7
- package/dist/crucible/index.js.map +1 -1
- package/dist/errors/index.js +249 -7
- package/dist/errors/index.js.map +1 -1
- package/dist/foundry/index.d.ts +2 -1
- package/dist/foundry/index.js +250 -8
- package/dist/foundry/index.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +252 -9
- package/dist/index.js.map +1 -1
- package/dist/pathfinder/index.js +249 -7
- package/dist/pathfinder/index.js.map +1 -1
- package/dist/reports/license-inventory.csv +29 -23
- package/dist/schema/index.d.ts +14 -1
- package/dist/schema/index.js +250 -8
- package/dist/schema/index.js.map +1 -1
- package/dist/signals/index.d.ts +483 -395
- package/dist/signals/index.js +250 -8
- package/dist/signals/index.js.map +1 -1
- package/dist/telemetry/http/index.js +250 -7
- package/dist/telemetry/http/index.js.map +1 -1
- package/dist/telemetry/index.js +249 -7
- package/dist/telemetry/index.js.map +1 -1
- package/dist/telemetry/prometheus/index.js +251 -7
- package/dist/telemetry/prometheus/index.js.map +1 -1
- package/dist/types-Dv5TERCM.d.ts +108 -0
- package/package.json +8 -8
package/dist/telemetry/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile, access, 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';
|
|
@@ -8,7 +9,6 @@ import Ajv from 'ajv';
|
|
|
8
9
|
import Ajv2019 from 'ajv/dist/2019';
|
|
9
10
|
import Ajv2020 from 'ajv/dist/2020';
|
|
10
11
|
import AjvDraft04 from 'ajv-draft-04';
|
|
11
|
-
import addFormats from 'ajv-formats';
|
|
12
12
|
import { Readable } from 'stream';
|
|
13
13
|
import picomatch from 'picomatch';
|
|
14
14
|
import { suggest as suggest$1, substringSimilarity, score as score$1, normalize as normalize$1, jaro_winkler, damerau_levenshtein, osa_distance, levenshtein } from '@3leaps/string-metrics-wasm';
|
|
@@ -801,6 +801,27 @@ var init_types = __esm({
|
|
|
801
801
|
"src/telemetry/types.ts"() {
|
|
802
802
|
}
|
|
803
803
|
});
|
|
804
|
+
function applyFulmenAjvFormats(ajv, options = {}) {
|
|
805
|
+
const mode = options.mode ?? "fast";
|
|
806
|
+
const formats = options.formats ?? DEFAULT_FORMATS;
|
|
807
|
+
addFormats(ajv, { mode, formats });
|
|
808
|
+
return ajv;
|
|
809
|
+
}
|
|
810
|
+
var DEFAULT_FORMATS;
|
|
811
|
+
var init_ajv_formats = __esm({
|
|
812
|
+
"src/schema/ajv-formats.ts"() {
|
|
813
|
+
DEFAULT_FORMATS = [
|
|
814
|
+
"date-time",
|
|
815
|
+
"email",
|
|
816
|
+
"hostname",
|
|
817
|
+
"ipv4",
|
|
818
|
+
"ipv6",
|
|
819
|
+
"uri",
|
|
820
|
+
"uri-reference",
|
|
821
|
+
"uuid"
|
|
822
|
+
];
|
|
823
|
+
}
|
|
824
|
+
});
|
|
804
825
|
|
|
805
826
|
// src/schema/errors.ts
|
|
806
827
|
var errors_exports = {};
|
|
@@ -1628,10 +1649,7 @@ function createAjv(dialect) {
|
|
|
1628
1649
|
// Enable async schema loading for YAML references
|
|
1629
1650
|
loadSchema: loadReferencedSchema
|
|
1630
1651
|
});
|
|
1631
|
-
|
|
1632
|
-
mode: "fast",
|
|
1633
|
-
formats: ["date-time", "email", "hostname", "ipv4", "ipv6", "uri", "uri-reference"]
|
|
1634
|
-
});
|
|
1652
|
+
applyFulmenAjvFormats(ajv);
|
|
1635
1653
|
return ajv;
|
|
1636
1654
|
}
|
|
1637
1655
|
async function getAjv(dialect) {
|
|
@@ -1877,6 +1895,7 @@ var ajvInstances, metaschemaReady, schemaCache;
|
|
|
1877
1895
|
var init_validator = __esm({
|
|
1878
1896
|
"src/schema/validator.ts"() {
|
|
1879
1897
|
init_telemetry();
|
|
1898
|
+
init_ajv_formats();
|
|
1880
1899
|
init_errors();
|
|
1881
1900
|
init_registry2();
|
|
1882
1901
|
init_utils();
|
|
@@ -3836,6 +3855,224 @@ var init_capabilities2 = __esm({
|
|
|
3836
3855
|
}
|
|
3837
3856
|
});
|
|
3838
3857
|
|
|
3858
|
+
// src/foundry/signals/config-reload-endpoint.ts
|
|
3859
|
+
function createConfigReloadEndpoint(options) {
|
|
3860
|
+
const { loader, validator, onReload: onReload2, auth, rateLimit, logger, telemetry } = options;
|
|
3861
|
+
return async (payload, req) => {
|
|
3862
|
+
const correlationId = payload.correlation_id ?? generateCorrelationId();
|
|
3863
|
+
const authResult = await auth(req);
|
|
3864
|
+
if (!authResult.authenticated) {
|
|
3865
|
+
if (logger) {
|
|
3866
|
+
logger.warn("Config reload endpoint: authentication failed", {
|
|
3867
|
+
correlation_id: correlationId,
|
|
3868
|
+
reason: authResult.reason
|
|
3869
|
+
});
|
|
3870
|
+
}
|
|
3871
|
+
if (telemetry) {
|
|
3872
|
+
telemetry.emit("fulmen.config.http_endpoint.auth_failed", {
|
|
3873
|
+
correlation_id: correlationId
|
|
3874
|
+
});
|
|
3875
|
+
}
|
|
3876
|
+
return {
|
|
3877
|
+
status: "error",
|
|
3878
|
+
error: "authentication_failed",
|
|
3879
|
+
message: authResult.reason || "Authentication required",
|
|
3880
|
+
statusCode: 401
|
|
3881
|
+
};
|
|
3882
|
+
}
|
|
3883
|
+
const identity = authResult.identity || "unknown";
|
|
3884
|
+
if (rateLimit) {
|
|
3885
|
+
const rateLimitResult = await rateLimit(identity);
|
|
3886
|
+
if (!rateLimitResult.allowed) {
|
|
3887
|
+
if (logger) {
|
|
3888
|
+
logger.warn("Config reload endpoint: rate limit exceeded", {
|
|
3889
|
+
correlation_id: correlationId,
|
|
3890
|
+
identity
|
|
3891
|
+
});
|
|
3892
|
+
}
|
|
3893
|
+
if (telemetry) {
|
|
3894
|
+
telemetry.emit("fulmen.config.http_endpoint.rate_limited", {
|
|
3895
|
+
correlation_id: correlationId
|
|
3896
|
+
});
|
|
3897
|
+
}
|
|
3898
|
+
return {
|
|
3899
|
+
status: "error",
|
|
3900
|
+
error: "rate_limit_exceeded",
|
|
3901
|
+
message: "Rate limit exceeded. Please try again later.",
|
|
3902
|
+
statusCode: 429
|
|
3903
|
+
};
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3906
|
+
if (telemetry) {
|
|
3907
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_requested", {
|
|
3908
|
+
correlation_id: correlationId
|
|
3909
|
+
});
|
|
3910
|
+
}
|
|
3911
|
+
try {
|
|
3912
|
+
const config = await loader();
|
|
3913
|
+
if (validator) {
|
|
3914
|
+
const validation = await validator(config);
|
|
3915
|
+
if (!validation.valid) {
|
|
3916
|
+
if (logger) {
|
|
3917
|
+
logger.warn("Config reload endpoint: validation failed", {
|
|
3918
|
+
correlation_id: correlationId,
|
|
3919
|
+
error_count: validation.errors?.length ?? 0
|
|
3920
|
+
});
|
|
3921
|
+
}
|
|
3922
|
+
if (telemetry) {
|
|
3923
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_rejected", {
|
|
3924
|
+
correlation_id: correlationId,
|
|
3925
|
+
reason: "validation_failed"
|
|
3926
|
+
});
|
|
3927
|
+
}
|
|
3928
|
+
return {
|
|
3929
|
+
status: "error",
|
|
3930
|
+
error: "validation_failed",
|
|
3931
|
+
message: "Configuration validation failed",
|
|
3932
|
+
validation_errors: validation.errors,
|
|
3933
|
+
statusCode: 422
|
|
3934
|
+
};
|
|
3935
|
+
}
|
|
3936
|
+
}
|
|
3937
|
+
if (onReload2) {
|
|
3938
|
+
await onReload2(config);
|
|
3939
|
+
}
|
|
3940
|
+
if (telemetry) {
|
|
3941
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_accepted", {
|
|
3942
|
+
correlation_id: correlationId
|
|
3943
|
+
});
|
|
3944
|
+
}
|
|
3945
|
+
if (logger) {
|
|
3946
|
+
logger.info("Config reload endpoint: reload accepted", {
|
|
3947
|
+
correlation_id: correlationId,
|
|
3948
|
+
reason: payload.reason
|
|
3949
|
+
});
|
|
3950
|
+
}
|
|
3951
|
+
return {
|
|
3952
|
+
status: "reloaded",
|
|
3953
|
+
correlation_id: correlationId,
|
|
3954
|
+
message: "Configuration reloaded",
|
|
3955
|
+
statusCode: 200
|
|
3956
|
+
};
|
|
3957
|
+
} catch (error) {
|
|
3958
|
+
if (logger) {
|
|
3959
|
+
logger.warn("Config reload endpoint: reload failed", {
|
|
3960
|
+
correlation_id: correlationId,
|
|
3961
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3962
|
+
});
|
|
3963
|
+
}
|
|
3964
|
+
if (telemetry) {
|
|
3965
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_error", {
|
|
3966
|
+
correlation_id: correlationId,
|
|
3967
|
+
error_type: error instanceof Error ? error.constructor.name : "unknown"
|
|
3968
|
+
});
|
|
3969
|
+
}
|
|
3970
|
+
return {
|
|
3971
|
+
status: "error",
|
|
3972
|
+
error: "reload_failed",
|
|
3973
|
+
message: error instanceof Error ? error.message : String(error),
|
|
3974
|
+
statusCode: 500
|
|
3975
|
+
};
|
|
3976
|
+
}
|
|
3977
|
+
};
|
|
3978
|
+
}
|
|
3979
|
+
function generateCorrelationId() {
|
|
3980
|
+
return `cfg-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
3981
|
+
}
|
|
3982
|
+
var init_config_reload_endpoint = __esm({
|
|
3983
|
+
"src/foundry/signals/config-reload-endpoint.ts"() {
|
|
3984
|
+
}
|
|
3985
|
+
});
|
|
3986
|
+
|
|
3987
|
+
// src/appidentity/runtime.ts
|
|
3988
|
+
function detectRuntime() {
|
|
3989
|
+
const versions = process.versions;
|
|
3990
|
+
if (typeof versions.bun === "string" && versions.bun.length > 0) {
|
|
3991
|
+
return { name: "bun", version: versions.bun };
|
|
3992
|
+
}
|
|
3993
|
+
if (typeof versions.node === "string" && versions.node.length > 0) {
|
|
3994
|
+
return { name: "node", version: versions.node };
|
|
3995
|
+
}
|
|
3996
|
+
return { name: "unknown" };
|
|
3997
|
+
}
|
|
3998
|
+
function buildRuntimeInfo(options = {}) {
|
|
3999
|
+
const runtime = detectRuntime();
|
|
4000
|
+
const serviceName = options.serviceName ?? options.identity?.app.binary_name ?? "unknown-service";
|
|
4001
|
+
const vendor = options.vendor ?? options.identity?.app.vendor;
|
|
4002
|
+
return {
|
|
4003
|
+
service: {
|
|
4004
|
+
name: serviceName,
|
|
4005
|
+
vendor,
|
|
4006
|
+
version: options.version
|
|
4007
|
+
},
|
|
4008
|
+
runtime,
|
|
4009
|
+
platform: {
|
|
4010
|
+
os: process.platform,
|
|
4011
|
+
arch: process.arch
|
|
4012
|
+
}
|
|
4013
|
+
};
|
|
4014
|
+
}
|
|
4015
|
+
var init_runtime = __esm({
|
|
4016
|
+
"src/appidentity/runtime.ts"() {
|
|
4017
|
+
}
|
|
4018
|
+
});
|
|
4019
|
+
|
|
4020
|
+
// src/foundry/signals/control-discovery-endpoint.ts
|
|
4021
|
+
function createControlDiscoveryEndpoint(options) {
|
|
4022
|
+
const { identity, version, endpoints, auth, authSummary, logger, telemetry } = options;
|
|
4023
|
+
return async (req) => {
|
|
4024
|
+
if (auth) {
|
|
4025
|
+
const authResult = await auth(req);
|
|
4026
|
+
if (!authResult.authenticated) {
|
|
4027
|
+
if (logger) {
|
|
4028
|
+
logger.warn("Control discovery endpoint: authentication failed", {
|
|
4029
|
+
reason: authResult.reason
|
|
4030
|
+
});
|
|
4031
|
+
}
|
|
4032
|
+
if (telemetry) {
|
|
4033
|
+
telemetry.emit("fulmen.control.discovery.auth_failed", {
|
|
4034
|
+
service: identity.app.binary_name
|
|
4035
|
+
});
|
|
4036
|
+
}
|
|
4037
|
+
return {
|
|
4038
|
+
status: "error",
|
|
4039
|
+
error: "authentication_failed",
|
|
4040
|
+
message: authResult.reason || "Authentication required",
|
|
4041
|
+
statusCode: 401
|
|
4042
|
+
};
|
|
4043
|
+
}
|
|
4044
|
+
}
|
|
4045
|
+
if (telemetry) {
|
|
4046
|
+
telemetry.emit("fulmen.control.discovery.served", {
|
|
4047
|
+
service: identity.app.binary_name
|
|
4048
|
+
});
|
|
4049
|
+
}
|
|
4050
|
+
const runtime = buildRuntimeInfo({ identity, version });
|
|
4051
|
+
return {
|
|
4052
|
+
status: "ok",
|
|
4053
|
+
service: {
|
|
4054
|
+
name: identity.app.binary_name,
|
|
4055
|
+
vendor: identity.app.vendor,
|
|
4056
|
+
version
|
|
4057
|
+
},
|
|
4058
|
+
runtime: {
|
|
4059
|
+
name: runtime.runtime.name,
|
|
4060
|
+
version: runtime.runtime.version,
|
|
4061
|
+
platform: runtime.platform.os,
|
|
4062
|
+
arch: runtime.platform.arch
|
|
4063
|
+
},
|
|
4064
|
+
auth_summary: authSummary,
|
|
4065
|
+
endpoints,
|
|
4066
|
+
statusCode: 200
|
|
4067
|
+
};
|
|
4068
|
+
};
|
|
4069
|
+
}
|
|
4070
|
+
var init_control_discovery_endpoint = __esm({
|
|
4071
|
+
"src/foundry/signals/control-discovery-endpoint.ts"() {
|
|
4072
|
+
init_runtime();
|
|
4073
|
+
}
|
|
4074
|
+
});
|
|
4075
|
+
|
|
3839
4076
|
// src/foundry/signals/convenience.ts
|
|
3840
4077
|
async function onShutdown(manager, handler, options = {}) {
|
|
3841
4078
|
await manager.register("SIGTERM", handler, options);
|
|
@@ -4095,7 +4332,7 @@ var init_guards = __esm({
|
|
|
4095
4332
|
function createSignalEndpoint(options) {
|
|
4096
4333
|
const { manager, auth, rateLimit, logger, telemetry, allowedSignals } = options;
|
|
4097
4334
|
return async (payload, req) => {
|
|
4098
|
-
const correlationId = payload.correlation_id ??
|
|
4335
|
+
const correlationId = payload.correlation_id ?? generateCorrelationId2();
|
|
4099
4336
|
const authResult = await auth(req);
|
|
4100
4337
|
if (!authResult.authenticated) {
|
|
4101
4338
|
if (logger) {
|
|
@@ -4218,7 +4455,7 @@ function normalizeSignalName(signal) {
|
|
|
4218
4455
|
}
|
|
4219
4456
|
return `SIG${upper}`;
|
|
4220
4457
|
}
|
|
4221
|
-
function
|
|
4458
|
+
function generateCorrelationId2() {
|
|
4222
4459
|
return `sig-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
4223
4460
|
}
|
|
4224
4461
|
function createBearerTokenAuth(expectedToken) {
|
|
@@ -4685,6 +4922,8 @@ var init_signals = __esm({
|
|
|
4685
4922
|
"src/foundry/signals/index.ts"() {
|
|
4686
4923
|
init_capabilities2();
|
|
4687
4924
|
init_catalog();
|
|
4925
|
+
init_config_reload_endpoint();
|
|
4926
|
+
init_control_discovery_endpoint();
|
|
4688
4927
|
init_convenience();
|
|
4689
4928
|
init_double_tap();
|
|
4690
4929
|
init_guards();
|
|
@@ -4830,7 +5069,9 @@ __export(foundry_exports, {
|
|
|
4830
5069
|
clearMimeTypeCache: () => clearMimeTypeCache,
|
|
4831
5070
|
clearPatternCache: () => clearPatternCache,
|
|
4832
5071
|
createBearerTokenAuth: () => createBearerTokenAuth,
|
|
5072
|
+
createConfigReloadEndpoint: () => createConfigReloadEndpoint,
|
|
4833
5073
|
createConfigReloadHandler: () => createConfigReloadHandler,
|
|
5074
|
+
createControlDiscoveryEndpoint: () => createControlDiscoveryEndpoint,
|
|
4834
5075
|
createDoubleTapTracker: () => createDoubleTapTracker,
|
|
4835
5076
|
createSignalEndpoint: () => createSignalEndpoint,
|
|
4836
5077
|
createSignalManager: () => createSignalManager,
|
|
@@ -5886,6 +6127,7 @@ var init_cli = __esm({
|
|
|
5886
6127
|
// src/schema/index.ts
|
|
5887
6128
|
var init_schema = __esm({
|
|
5888
6129
|
"src/schema/index.ts"() {
|
|
6130
|
+
init_ajv_formats();
|
|
5889
6131
|
init_cli();
|
|
5890
6132
|
init_errors();
|
|
5891
6133
|
init_export();
|