everything-dev 1.45.0 → 1.46.0
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/build.cjs +328 -0
- package/dist/build.cjs.map +1 -0
- package/dist/build.mjs +320 -0
- package/dist/build.mjs.map +1 -0
- package/dist/cli/init.cjs +1 -1
- package/dist/cli/init.mjs +1 -1
- package/dist/cli/sync.cjs +1 -1
- package/dist/cli/sync.mjs +1 -1
- package/dist/cli/upgrade.cjs +2 -2
- package/dist/cli/upgrade.mjs +2 -2
- package/dist/cli.cjs +2 -2
- package/dist/cli.mjs +2 -2
- package/dist/code-artifacts.cjs +25 -0
- package/dist/code-artifacts.cjs.map +1 -0
- package/dist/code-artifacts.mjs +24 -0
- package/dist/code-artifacts.mjs.map +1 -0
- package/dist/contract.cjs.map +1 -1
- package/dist/contract.d.cts +22 -21
- package/dist/contract.d.cts.map +1 -1
- package/dist/contract.d.mts +22 -21
- package/dist/contract.d.mts.map +1 -1
- package/dist/contract.mjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/integrity.cjs +18 -55
- package/dist/integrity.cjs.map +1 -1
- package/dist/integrity.d.cts +3 -7
- package/dist/integrity.d.cts.map +1 -1
- package/dist/integrity.d.mts +3 -7
- package/dist/integrity.d.mts.map +1 -1
- package/dist/integrity.mjs +18 -53
- package/dist/integrity.mjs.map +1 -1
- package/dist/plugin.cjs +37 -571
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +9 -16
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.mts +9 -16
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +23 -556
- package/dist/plugin.mjs.map +1 -1
- package/dist/publish.cjs +220 -0
- package/dist/publish.cjs.map +1 -0
- package/dist/publish.mjs +217 -0
- package/dist/publish.mjs.map +1 -0
- package/dist/types.d.cts +2 -2
- package/dist/types.d.mts +2 -2
- package/dist/utils/run.cjs +21 -3
- package/dist/utils/run.cjs.map +1 -1
- package/dist/utils/run.mjs +21 -3
- package/dist/utils/run.mjs.map +1 -1
- package/dist/utils/string.cjs +9 -0
- package/dist/utils/string.cjs.map +1 -0
- package/dist/utils/string.mjs +8 -0
- package/dist/utils/string.mjs.map +1 -0
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ApiPluginConfig, ApiPluginConfigSchema, BosConfig, BosConfigInput, BosConfigInputAppEntry, BosConfigInputSchema, BosConfigSchema, BosPluginRef, BosPluginRefSchema, BosStaging, BosStagingSchema, CiConfig, CiConfigSchema, ClientRuntimeConfig, ClientRuntimeConfigSchema, ClientRuntimeInfo, ClientRuntimeInfoSchema, ComposableAppEntry, ComposableAppEntrySchema, Extends, ExtendsConfig, ExtendsSchema, FederationEntry, FederationEntrySchema, HostConfig, HostConfigSchema, JsonObject, JsonObjectSchema, JsonPrimitive, JsonValue, JsonValueSchema, PluginEntries, PluginEntryValue, PluginRuntimeUi, PluginUiConfig, PluginUiConfigSchema, RailwayCi, RailwayCiSchema, RuntimeConfig, RuntimeConfigSchema, RuntimeLineage, RuntimeLineageSchema, RuntimePluginConfig, RuntimePluginConfigSchema, SharedConfig, SharedConfigSchema, SharedDepConfig, SharedDepConfigSchema, SharedDepMapSchema, SourceMode, SourceModeSchema, UiConfig, UiConfigSchema } from "./types.cjs";
|
|
2
|
-
import { BosConfigResult, BuildOptions, BuildOptionsSchema, BuildResultSchema, ConfigOptionsSchema, ConfigResultSchema, DbStudioOptions, DbStudioOptionsSchema, DbStudioResult, DbStudioResultSchema, DeployOptions, DeployOptionsSchema, DeployResult, DeployResultSchema, DevOptions, DevOptionsSchema, DevResult, DevResultSchema, InitOptions, InitOptionsSchema, InitResult, InitResultSchema, KeyPublishOptions, KeyPublishOptionsSchema, KeyPublishResult, KeyPublishResultSchema, OverrideSection, OverrideSectionSchema, PhaseTiming, PhaseTimingSchema, PluginAddOptions, PluginAddOptionsSchema, PluginAddResult, PluginAddResultSchema, PluginListResult, PluginListResultSchema, PluginPublishOptions, PluginPublishOptionsSchema, PluginPublishResult, PluginPublishResultSchema, PluginRemoveOptions, PluginRemoveOptionsSchema, PluginRemoveResult, PluginRemoveResultSchema, PublishOptions, PublishOptionsSchema, PublishResultSchema, RuntimeOverrideTarget, RuntimeOverrideTargetBaseSchema, RuntimeOverrideTargetSchema, StartOptions, StartOptionsSchema, StartResult, StartResultSchema, StatusResult, StatusResultSchema, SyncOptions, SyncOptionsSchema, SyncResult, SyncResultSchema, TypesGenOptions, TypesGenOptionsSchema, TypesGenResult, TypesGenResultSchema, UpgradeOptions, UpgradeOptionsSchema, UpgradeResult, UpgradeResultSchema, WorkspaceDeployResult, WorkspaceDeployResultSchema, bosContract } from "./contract.cjs";
|
|
2
|
+
import { BosConfigResult, BuildOptions, BuildOptionsSchema, BuildResultSchema, ConfigOptionsSchema, ConfigResultSchema, DbStudioOptions, DbStudioOptionsSchema, DbStudioResult, DbStudioResultSchema, DeployOptions, DeployOptionsSchema, DeployResult, DeployResultSchema, DevOptions, DevOptionsSchema, DevResult, DevResultSchema, InitOptions, InitOptionsSchema, InitResult, InitResultSchema, KeyPublishOptions, KeyPublishOptionsSchema, KeyPublishResult, KeyPublishResultSchema, OverrideSection, OverrideSectionSchema, PhaseTiming, PhaseTimingSchema, PluginAddOptions, PluginAddOptionsSchema, PluginAddResult, PluginAddResultSchema, PluginListResult, PluginListResultSchema, PluginPublishOptions, PluginPublishOptionsSchema, PluginPublishResult, PluginPublishResultSchema, PluginRemoveOptions, PluginRemoveOptionsSchema, PluginRemoveResult, PluginRemoveResultSchema, PublishOptions, PublishOptionsSchema, PublishResult, PublishResultSchema, RuntimeOverrideTarget, RuntimeOverrideTargetBaseSchema, RuntimeOverrideTargetSchema, StartOptions, StartOptionsSchema, StartResult, StartResultSchema, StatusResult, StatusResultSchema, SyncOptions, SyncOptionsSchema, SyncResult, SyncResultSchema, TypesGenOptions, TypesGenOptionsSchema, TypesGenResult, TypesGenResultSchema, UpgradeOptions, UpgradeOptionsSchema, UpgradeResult, UpgradeResultSchema, WorkspaceDeployResult, WorkspaceDeployResultSchema, bosContract } from "./contract.cjs";
|
|
3
3
|
import { BOS_CONFIG_ORDER, mergeBosConfigWithExtends, rebuildOrderedConfig, resolveExtendsRef } from "./merge.cjs";
|
|
4
4
|
import { BuildRuntimeConfigOptions, ConfigResult, LocalConfigResult, RemoteConfigResult, ResolvedComposableReference, buildRuntimeConfig, buildRuntimePluginsForConfig, clearConfigCache, drainConfigWarnings, findConfigPath, getConfig, getHostDevelopmentPort, getProjectRoot, getResolvedConfigPath, isLocalDevelopmentTarget, isRuntimeOverrideAllowed, loadBosConfig, loadGeneratedResolvedConfig, loadLocalConfig, loadRemoteConfig, loadResolvedConfig, parsePort, parseRuntimeOverrideTargets, readBosConfigForBuild, resolveBosConfigPath, resolveComposableReference, resolveConfigComposableEntries, resolveDevelopmentHostUrl, resolveLocalDevelopmentPath, resolvePluginRuntimeName, resumeWarnings, suppressWarnings, writeResolvedConfig } from "./config.cjs";
|
|
5
5
|
import { CliCommandMeta, cliCommandMeta } from "./contract.meta.cjs";
|
|
6
6
|
import { NetworkId, PluginManifest, buildRegistryConfigUrl, buildRegistryConfigUrlForNetwork, fetchBosConfigFromFastKv, fetchRemotePluginManifest, getFastKvBaseUrlForNetwork, getRegistryNamespaceForAccount, getRegistryNamespaceForNetwork, parseBosUrl } from "./fastkv.cjs";
|
|
7
7
|
import { AnyContractRouter, AnySchema, Context, Effect, Layer, LoadedPluginWithBinding, Plugin, PluginRuntime, Scope, createPlugin, createPluginRuntime, oc, z } from "./sdk.cjs";
|
|
8
|
-
export { AnyContractRouter, AnySchema, ApiPluginConfig, ApiPluginConfigSchema, BOS_CONFIG_ORDER, BosConfig, BosConfigInput, BosConfigInputAppEntry, BosConfigInputSchema, BosConfigResult, BosConfigSchema, BosPluginRef, BosPluginRefSchema, BosStaging, BosStagingSchema, BuildOptions, BuildOptionsSchema, BuildResultSchema, BuildRuntimeConfigOptions, CiConfig, CiConfigSchema, CliCommandMeta, ClientRuntimeConfig, ClientRuntimeConfigSchema, ClientRuntimeInfo, ClientRuntimeInfoSchema, ComposableAppEntry, ComposableAppEntrySchema, ConfigOptionsSchema, ConfigResult, ConfigResultSchema, Context, DbStudioOptions, DbStudioOptionsSchema, DbStudioResult, DbStudioResultSchema, DeployOptions, DeployOptionsSchema, DeployResult, DeployResultSchema, DevOptions, DevOptionsSchema, DevResult, DevResultSchema, Effect, Extends, ExtendsConfig, ExtendsSchema, FederationEntry, FederationEntrySchema, HostConfig, HostConfigSchema, InitOptions, InitOptionsSchema, InitResult, InitResultSchema, JsonObject, JsonObjectSchema, JsonPrimitive, JsonValue, JsonValueSchema, KeyPublishOptions, KeyPublishOptionsSchema, KeyPublishResult, KeyPublishResultSchema, Layer, LoadedPluginWithBinding, LocalConfigResult, NetworkId, OverrideSection, OverrideSectionSchema, PhaseTiming, PhaseTimingSchema, Plugin, PluginAddOptions, PluginAddOptionsSchema, PluginAddResult, PluginAddResultSchema, PluginEntries, PluginEntryValue, PluginListResult, PluginListResultSchema, PluginManifest, PluginPublishOptions, PluginPublishOptionsSchema, PluginPublishResult, PluginPublishResultSchema, PluginRemoveOptions, PluginRemoveOptionsSchema, PluginRemoveResult, PluginRemoveResultSchema, PluginRuntime, PluginRuntimeUi, PluginUiConfig, PluginUiConfigSchema, PublishOptions, PublishOptionsSchema, PublishResultSchema, RailwayCi, RailwayCiSchema, RemoteConfigResult, ResolvedComposableReference, RuntimeConfig, RuntimeConfigSchema, RuntimeLineage, RuntimeLineageSchema, RuntimeOverrideTarget, RuntimeOverrideTargetBaseSchema, RuntimeOverrideTargetSchema, RuntimePluginConfig, RuntimePluginConfigSchema, Scope, SharedConfig, SharedConfigSchema, SharedDepConfig, SharedDepConfigSchema, SharedDepMapSchema, SourceMode, SourceModeSchema, StartOptions, StartOptionsSchema, StartResult, StartResultSchema, StatusResult, StatusResultSchema, SyncOptions, SyncOptionsSchema, SyncResult, SyncResultSchema, TypesGenOptions, TypesGenOptionsSchema, TypesGenResult, TypesGenResultSchema, UiConfig, UiConfigSchema, UpgradeOptions, UpgradeOptionsSchema, UpgradeResult, UpgradeResultSchema, WorkspaceDeployResult, WorkspaceDeployResultSchema, bosContract, buildRegistryConfigUrl, buildRegistryConfigUrlForNetwork, buildRuntimeConfig, buildRuntimePluginsForConfig, clearConfigCache, cliCommandMeta, createPlugin, createPluginRuntime, drainConfigWarnings, fetchBosConfigFromFastKv, fetchRemotePluginManifest, findConfigPath, getConfig, getFastKvBaseUrlForNetwork, getHostDevelopmentPort, getProjectRoot, getRegistryNamespaceForAccount, getRegistryNamespaceForNetwork, getResolvedConfigPath, isLocalDevelopmentTarget, isRuntimeOverrideAllowed, loadBosConfig, loadGeneratedResolvedConfig, loadLocalConfig, loadRemoteConfig, loadResolvedConfig, mergeBosConfigWithExtends, oc, parseBosUrl, parsePort, parseRuntimeOverrideTargets, readBosConfigForBuild, rebuildOrderedConfig, resolveBosConfigPath, resolveComposableReference, resolveConfigComposableEntries, resolveDevelopmentHostUrl, resolveExtendsRef, resolveLocalDevelopmentPath, resolvePluginRuntimeName, resumeWarnings, suppressWarnings, writeResolvedConfig, z };
|
|
8
|
+
export { AnyContractRouter, AnySchema, ApiPluginConfig, ApiPluginConfigSchema, BOS_CONFIG_ORDER, BosConfig, BosConfigInput, BosConfigInputAppEntry, BosConfigInputSchema, BosConfigResult, BosConfigSchema, BosPluginRef, BosPluginRefSchema, BosStaging, BosStagingSchema, BuildOptions, BuildOptionsSchema, BuildResultSchema, BuildRuntimeConfigOptions, CiConfig, CiConfigSchema, CliCommandMeta, ClientRuntimeConfig, ClientRuntimeConfigSchema, ClientRuntimeInfo, ClientRuntimeInfoSchema, ComposableAppEntry, ComposableAppEntrySchema, ConfigOptionsSchema, ConfigResult, ConfigResultSchema, Context, DbStudioOptions, DbStudioOptionsSchema, DbStudioResult, DbStudioResultSchema, DeployOptions, DeployOptionsSchema, DeployResult, DeployResultSchema, DevOptions, DevOptionsSchema, DevResult, DevResultSchema, Effect, Extends, ExtendsConfig, ExtendsSchema, FederationEntry, FederationEntrySchema, HostConfig, HostConfigSchema, InitOptions, InitOptionsSchema, InitResult, InitResultSchema, JsonObject, JsonObjectSchema, JsonPrimitive, JsonValue, JsonValueSchema, KeyPublishOptions, KeyPublishOptionsSchema, KeyPublishResult, KeyPublishResultSchema, Layer, LoadedPluginWithBinding, LocalConfigResult, NetworkId, OverrideSection, OverrideSectionSchema, PhaseTiming, PhaseTimingSchema, Plugin, PluginAddOptions, PluginAddOptionsSchema, PluginAddResult, PluginAddResultSchema, PluginEntries, PluginEntryValue, PluginListResult, PluginListResultSchema, PluginManifest, PluginPublishOptions, PluginPublishOptionsSchema, PluginPublishResult, PluginPublishResultSchema, PluginRemoveOptions, PluginRemoveOptionsSchema, PluginRemoveResult, PluginRemoveResultSchema, PluginRuntime, PluginRuntimeUi, PluginUiConfig, PluginUiConfigSchema, PublishOptions, PublishOptionsSchema, PublishResult, PublishResultSchema, RailwayCi, RailwayCiSchema, RemoteConfigResult, ResolvedComposableReference, RuntimeConfig, RuntimeConfigSchema, RuntimeLineage, RuntimeLineageSchema, RuntimeOverrideTarget, RuntimeOverrideTargetBaseSchema, RuntimeOverrideTargetSchema, RuntimePluginConfig, RuntimePluginConfigSchema, Scope, SharedConfig, SharedConfigSchema, SharedDepConfig, SharedDepConfigSchema, SharedDepMapSchema, SourceMode, SourceModeSchema, StartOptions, StartOptionsSchema, StartResult, StartResultSchema, StatusResult, StatusResultSchema, SyncOptions, SyncOptionsSchema, SyncResult, SyncResultSchema, TypesGenOptions, TypesGenOptionsSchema, TypesGenResult, TypesGenResultSchema, UiConfig, UiConfigSchema, UpgradeOptions, UpgradeOptionsSchema, UpgradeResult, UpgradeResultSchema, WorkspaceDeployResult, WorkspaceDeployResultSchema, bosContract, buildRegistryConfigUrl, buildRegistryConfigUrlForNetwork, buildRuntimeConfig, buildRuntimePluginsForConfig, clearConfigCache, cliCommandMeta, createPlugin, createPluginRuntime, drainConfigWarnings, fetchBosConfigFromFastKv, fetchRemotePluginManifest, findConfigPath, getConfig, getFastKvBaseUrlForNetwork, getHostDevelopmentPort, getProjectRoot, getRegistryNamespaceForAccount, getRegistryNamespaceForNetwork, getResolvedConfigPath, isLocalDevelopmentTarget, isRuntimeOverrideAllowed, loadBosConfig, loadGeneratedResolvedConfig, loadLocalConfig, loadRemoteConfig, loadResolvedConfig, mergeBosConfigWithExtends, oc, parseBosUrl, parsePort, parseRuntimeOverrideTargets, readBosConfigForBuild, rebuildOrderedConfig, resolveBosConfigPath, resolveComposableReference, resolveConfigComposableEntries, resolveDevelopmentHostUrl, resolveExtendsRef, resolveLocalDevelopmentPath, resolvePluginRuntimeName, resumeWarnings, suppressWarnings, writeResolvedConfig, z };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ApiPluginConfig, ApiPluginConfigSchema, BosConfig, BosConfigInput, BosConfigInputAppEntry, BosConfigInputSchema, BosConfigSchema, BosPluginRef, BosPluginRefSchema, BosStaging, BosStagingSchema, CiConfig, CiConfigSchema, ClientRuntimeConfig, ClientRuntimeConfigSchema, ClientRuntimeInfo, ClientRuntimeInfoSchema, ComposableAppEntry, ComposableAppEntrySchema, Extends, ExtendsConfig, ExtendsSchema, FederationEntry, FederationEntrySchema, HostConfig, HostConfigSchema, JsonObject, JsonObjectSchema, JsonPrimitive, JsonValue, JsonValueSchema, PluginEntries, PluginEntryValue, PluginRuntimeUi, PluginUiConfig, PluginUiConfigSchema, RailwayCi, RailwayCiSchema, RuntimeConfig, RuntimeConfigSchema, RuntimeLineage, RuntimeLineageSchema, RuntimePluginConfig, RuntimePluginConfigSchema, SharedConfig, SharedConfigSchema, SharedDepConfig, SharedDepConfigSchema, SharedDepMapSchema, SourceMode, SourceModeSchema, UiConfig, UiConfigSchema } from "./types.mjs";
|
|
2
|
-
import { BosConfigResult, BuildOptions, BuildOptionsSchema, BuildResultSchema, ConfigOptionsSchema, ConfigResultSchema, DbStudioOptions, DbStudioOptionsSchema, DbStudioResult, DbStudioResultSchema, DeployOptions, DeployOptionsSchema, DeployResult, DeployResultSchema, DevOptions, DevOptionsSchema, DevResult, DevResultSchema, InitOptions, InitOptionsSchema, InitResult, InitResultSchema, KeyPublishOptions, KeyPublishOptionsSchema, KeyPublishResult, KeyPublishResultSchema, OverrideSection, OverrideSectionSchema, PhaseTiming, PhaseTimingSchema, PluginAddOptions, PluginAddOptionsSchema, PluginAddResult, PluginAddResultSchema, PluginListResult, PluginListResultSchema, PluginPublishOptions, PluginPublishOptionsSchema, PluginPublishResult, PluginPublishResultSchema, PluginRemoveOptions, PluginRemoveOptionsSchema, PluginRemoveResult, PluginRemoveResultSchema, PublishOptions, PublishOptionsSchema, PublishResultSchema, RuntimeOverrideTarget, RuntimeOverrideTargetBaseSchema, RuntimeOverrideTargetSchema, StartOptions, StartOptionsSchema, StartResult, StartResultSchema, StatusResult, StatusResultSchema, SyncOptions, SyncOptionsSchema, SyncResult, SyncResultSchema, TypesGenOptions, TypesGenOptionsSchema, TypesGenResult, TypesGenResultSchema, UpgradeOptions, UpgradeOptionsSchema, UpgradeResult, UpgradeResultSchema, WorkspaceDeployResult, WorkspaceDeployResultSchema, bosContract } from "./contract.mjs";
|
|
2
|
+
import { BosConfigResult, BuildOptions, BuildOptionsSchema, BuildResultSchema, ConfigOptionsSchema, ConfigResultSchema, DbStudioOptions, DbStudioOptionsSchema, DbStudioResult, DbStudioResultSchema, DeployOptions, DeployOptionsSchema, DeployResult, DeployResultSchema, DevOptions, DevOptionsSchema, DevResult, DevResultSchema, InitOptions, InitOptionsSchema, InitResult, InitResultSchema, KeyPublishOptions, KeyPublishOptionsSchema, KeyPublishResult, KeyPublishResultSchema, OverrideSection, OverrideSectionSchema, PhaseTiming, PhaseTimingSchema, PluginAddOptions, PluginAddOptionsSchema, PluginAddResult, PluginAddResultSchema, PluginListResult, PluginListResultSchema, PluginPublishOptions, PluginPublishOptionsSchema, PluginPublishResult, PluginPublishResultSchema, PluginRemoveOptions, PluginRemoveOptionsSchema, PluginRemoveResult, PluginRemoveResultSchema, PublishOptions, PublishOptionsSchema, PublishResult, PublishResultSchema, RuntimeOverrideTarget, RuntimeOverrideTargetBaseSchema, RuntimeOverrideTargetSchema, StartOptions, StartOptionsSchema, StartResult, StartResultSchema, StatusResult, StatusResultSchema, SyncOptions, SyncOptionsSchema, SyncResult, SyncResultSchema, TypesGenOptions, TypesGenOptionsSchema, TypesGenResult, TypesGenResultSchema, UpgradeOptions, UpgradeOptionsSchema, UpgradeResult, UpgradeResultSchema, WorkspaceDeployResult, WorkspaceDeployResultSchema, bosContract } from "./contract.mjs";
|
|
3
3
|
import { BOS_CONFIG_ORDER, mergeBosConfigWithExtends, rebuildOrderedConfig, resolveExtendsRef } from "./merge.mjs";
|
|
4
4
|
import { BuildRuntimeConfigOptions, ConfigResult, LocalConfigResult, RemoteConfigResult, ResolvedComposableReference, buildRuntimeConfig, buildRuntimePluginsForConfig, clearConfigCache, drainConfigWarnings, findConfigPath, getConfig, getHostDevelopmentPort, getProjectRoot, getResolvedConfigPath, isLocalDevelopmentTarget, isRuntimeOverrideAllowed, loadBosConfig, loadGeneratedResolvedConfig, loadLocalConfig, loadRemoteConfig, loadResolvedConfig, parsePort, parseRuntimeOverrideTargets, readBosConfigForBuild, resolveBosConfigPath, resolveComposableReference, resolveConfigComposableEntries, resolveDevelopmentHostUrl, resolveLocalDevelopmentPath, resolvePluginRuntimeName, resumeWarnings, suppressWarnings, writeResolvedConfig } from "./config.mjs";
|
|
5
5
|
import { CliCommandMeta, cliCommandMeta } from "./contract.meta.mjs";
|
|
6
6
|
import { NetworkId, PluginManifest, buildRegistryConfigUrl, buildRegistryConfigUrlForNetwork, fetchBosConfigFromFastKv, fetchRemotePluginManifest, getFastKvBaseUrlForNetwork, getRegistryNamespaceForAccount, getRegistryNamespaceForNetwork, parseBosUrl } from "./fastkv.mjs";
|
|
7
7
|
import { AnyContractRouter, AnySchema, Context, Effect, Layer, LoadedPluginWithBinding, Plugin, PluginRuntime, Scope, createPlugin, createPluginRuntime, oc, z } from "./sdk.mjs";
|
|
8
|
-
export { AnyContractRouter, AnySchema, ApiPluginConfig, ApiPluginConfigSchema, BOS_CONFIG_ORDER, BosConfig, BosConfigInput, BosConfigInputAppEntry, BosConfigInputSchema, BosConfigResult, BosConfigSchema, BosPluginRef, BosPluginRefSchema, BosStaging, BosStagingSchema, BuildOptions, BuildOptionsSchema, BuildResultSchema, BuildRuntimeConfigOptions, CiConfig, CiConfigSchema, CliCommandMeta, ClientRuntimeConfig, ClientRuntimeConfigSchema, ClientRuntimeInfo, ClientRuntimeInfoSchema, ComposableAppEntry, ComposableAppEntrySchema, ConfigOptionsSchema, ConfigResult, ConfigResultSchema, Context, DbStudioOptions, DbStudioOptionsSchema, DbStudioResult, DbStudioResultSchema, DeployOptions, DeployOptionsSchema, DeployResult, DeployResultSchema, DevOptions, DevOptionsSchema, DevResult, DevResultSchema, Effect, Extends, ExtendsConfig, ExtendsSchema, FederationEntry, FederationEntrySchema, HostConfig, HostConfigSchema, InitOptions, InitOptionsSchema, InitResult, InitResultSchema, JsonObject, JsonObjectSchema, JsonPrimitive, JsonValue, JsonValueSchema, KeyPublishOptions, KeyPublishOptionsSchema, KeyPublishResult, KeyPublishResultSchema, Layer, LoadedPluginWithBinding, LocalConfigResult, NetworkId, OverrideSection, OverrideSectionSchema, PhaseTiming, PhaseTimingSchema, Plugin, PluginAddOptions, PluginAddOptionsSchema, PluginAddResult, PluginAddResultSchema, PluginEntries, PluginEntryValue, PluginListResult, PluginListResultSchema, PluginManifest, PluginPublishOptions, PluginPublishOptionsSchema, PluginPublishResult, PluginPublishResultSchema, PluginRemoveOptions, PluginRemoveOptionsSchema, PluginRemoveResult, PluginRemoveResultSchema, PluginRuntime, PluginRuntimeUi, PluginUiConfig, PluginUiConfigSchema, PublishOptions, PublishOptionsSchema, PublishResultSchema, RailwayCi, RailwayCiSchema, RemoteConfigResult, ResolvedComposableReference, RuntimeConfig, RuntimeConfigSchema, RuntimeLineage, RuntimeLineageSchema, RuntimeOverrideTarget, RuntimeOverrideTargetBaseSchema, RuntimeOverrideTargetSchema, RuntimePluginConfig, RuntimePluginConfigSchema, Scope, SharedConfig, SharedConfigSchema, SharedDepConfig, SharedDepConfigSchema, SharedDepMapSchema, SourceMode, SourceModeSchema, StartOptions, StartOptionsSchema, StartResult, StartResultSchema, StatusResult, StatusResultSchema, SyncOptions, SyncOptionsSchema, SyncResult, SyncResultSchema, TypesGenOptions, TypesGenOptionsSchema, TypesGenResult, TypesGenResultSchema, UiConfig, UiConfigSchema, UpgradeOptions, UpgradeOptionsSchema, UpgradeResult, UpgradeResultSchema, WorkspaceDeployResult, WorkspaceDeployResultSchema, bosContract, buildRegistryConfigUrl, buildRegistryConfigUrlForNetwork, buildRuntimeConfig, buildRuntimePluginsForConfig, clearConfigCache, cliCommandMeta, createPlugin, createPluginRuntime, drainConfigWarnings, fetchBosConfigFromFastKv, fetchRemotePluginManifest, findConfigPath, getConfig, getFastKvBaseUrlForNetwork, getHostDevelopmentPort, getProjectRoot, getRegistryNamespaceForAccount, getRegistryNamespaceForNetwork, getResolvedConfigPath, isLocalDevelopmentTarget, isRuntimeOverrideAllowed, loadBosConfig, loadGeneratedResolvedConfig, loadLocalConfig, loadRemoteConfig, loadResolvedConfig, mergeBosConfigWithExtends, oc, parseBosUrl, parsePort, parseRuntimeOverrideTargets, readBosConfigForBuild, rebuildOrderedConfig, resolveBosConfigPath, resolveComposableReference, resolveConfigComposableEntries, resolveDevelopmentHostUrl, resolveExtendsRef, resolveLocalDevelopmentPath, resolvePluginRuntimeName, resumeWarnings, suppressWarnings, writeResolvedConfig, z };
|
|
8
|
+
export { AnyContractRouter, AnySchema, ApiPluginConfig, ApiPluginConfigSchema, BOS_CONFIG_ORDER, BosConfig, BosConfigInput, BosConfigInputAppEntry, BosConfigInputSchema, BosConfigResult, BosConfigSchema, BosPluginRef, BosPluginRefSchema, BosStaging, BosStagingSchema, BuildOptions, BuildOptionsSchema, BuildResultSchema, BuildRuntimeConfigOptions, CiConfig, CiConfigSchema, CliCommandMeta, ClientRuntimeConfig, ClientRuntimeConfigSchema, ClientRuntimeInfo, ClientRuntimeInfoSchema, ComposableAppEntry, ComposableAppEntrySchema, ConfigOptionsSchema, ConfigResult, ConfigResultSchema, Context, DbStudioOptions, DbStudioOptionsSchema, DbStudioResult, DbStudioResultSchema, DeployOptions, DeployOptionsSchema, DeployResult, DeployResultSchema, DevOptions, DevOptionsSchema, DevResult, DevResultSchema, Effect, Extends, ExtendsConfig, ExtendsSchema, FederationEntry, FederationEntrySchema, HostConfig, HostConfigSchema, InitOptions, InitOptionsSchema, InitResult, InitResultSchema, JsonObject, JsonObjectSchema, JsonPrimitive, JsonValue, JsonValueSchema, KeyPublishOptions, KeyPublishOptionsSchema, KeyPublishResult, KeyPublishResultSchema, Layer, LoadedPluginWithBinding, LocalConfigResult, NetworkId, OverrideSection, OverrideSectionSchema, PhaseTiming, PhaseTimingSchema, Plugin, PluginAddOptions, PluginAddOptionsSchema, PluginAddResult, PluginAddResultSchema, PluginEntries, PluginEntryValue, PluginListResult, PluginListResultSchema, PluginManifest, PluginPublishOptions, PluginPublishOptionsSchema, PluginPublishResult, PluginPublishResultSchema, PluginRemoveOptions, PluginRemoveOptionsSchema, PluginRemoveResult, PluginRemoveResultSchema, PluginRuntime, PluginRuntimeUi, PluginUiConfig, PluginUiConfigSchema, PublishOptions, PublishOptionsSchema, PublishResult, PublishResultSchema, RailwayCi, RailwayCiSchema, RemoteConfigResult, ResolvedComposableReference, RuntimeConfig, RuntimeConfigSchema, RuntimeLineage, RuntimeLineageSchema, RuntimeOverrideTarget, RuntimeOverrideTargetBaseSchema, RuntimeOverrideTargetSchema, RuntimePluginConfig, RuntimePluginConfigSchema, Scope, SharedConfig, SharedConfigSchema, SharedDepConfig, SharedDepConfigSchema, SharedDepMapSchema, SourceMode, SourceModeSchema, StartOptions, StartOptionsSchema, StartResult, StartResultSchema, StatusResult, StatusResultSchema, SyncOptions, SyncOptionsSchema, SyncResult, SyncResultSchema, TypesGenOptions, TypesGenOptionsSchema, TypesGenResult, TypesGenResultSchema, UiConfig, UiConfigSchema, UpgradeOptions, UpgradeOptionsSchema, UpgradeResult, UpgradeResultSchema, WorkspaceDeployResult, WorkspaceDeployResultSchema, bosContract, buildRegistryConfigUrl, buildRegistryConfigUrlForNetwork, buildRuntimeConfig, buildRuntimePluginsForConfig, clearConfigCache, cliCommandMeta, createPlugin, createPluginRuntime, drainConfigWarnings, fetchBosConfigFromFastKv, fetchRemotePluginManifest, findConfigPath, getConfig, getFastKvBaseUrlForNetwork, getHostDevelopmentPort, getProjectRoot, getRegistryNamespaceForAccount, getRegistryNamespaceForNetwork, getResolvedConfigPath, isLocalDevelopmentTarget, isRuntimeOverrideAllowed, loadBosConfig, loadGeneratedResolvedConfig, loadLocalConfig, loadRemoteConfig, loadResolvedConfig, mergeBosConfigWithExtends, oc, parseBosUrl, parsePort, parseRuntimeOverrideTargets, readBosConfigForBuild, rebuildOrderedConfig, resolveBosConfigPath, resolveComposableReference, resolveConfigComposableEntries, resolveDevelopmentHostUrl, resolveExtendsRef, resolveLocalDevelopmentPath, resolvePluginRuntimeName, resumeWarnings, suppressWarnings, writeResolvedConfig, z };
|
package/dist/integrity.cjs
CHANGED
|
@@ -146,24 +146,8 @@ function deleteNestedPath(obj, dottedPath) {
|
|
|
146
146
|
}
|
|
147
147
|
delete current[keys[keys.length - 1]];
|
|
148
148
|
}
|
|
149
|
-
function
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
function writeDeployResult(opts) {
|
|
153
|
-
const resultDir = process.env.BOS_DEPLOY_RESULT_DIR;
|
|
154
|
-
if (resultDir) {
|
|
155
|
-
(0, node_fs.mkdirSync)(resultDir, { recursive: true });
|
|
156
|
-
const entry = {
|
|
157
|
-
label: opts.label,
|
|
158
|
-
url: opts.url,
|
|
159
|
-
integrity: opts.integrity ?? void 0,
|
|
160
|
-
urlField: opts.urlField,
|
|
161
|
-
integrityField: opts.integrityField
|
|
162
|
-
};
|
|
163
|
-
(0, node_fs.writeFileSync)((0, node_path.join)(resultDir, `${sanitizeFilename(opts.label)}.json`), JSON.stringify(entry, null, 2));
|
|
164
|
-
console.log(` ✅ Deploy result: ${opts.urlField}`);
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
149
|
+
function reportDeployResult(opts) {
|
|
150
|
+
console.log(`[BOS_DEPLOY] url=${opts.url} urlField=${opts.urlField} integrityField=${opts.integrityField ?? ""} integrity=${opts.integrity ?? ""}`);
|
|
167
151
|
try {
|
|
168
152
|
const config = JSON.parse((0, node_fs.readFileSync)(opts.bosConfigPath, "utf8"));
|
|
169
153
|
setNestedPath(config, opts.urlField, opts.url);
|
|
@@ -176,33 +160,21 @@ function writeDeployResult(opts) {
|
|
|
176
160
|
console.error(" ❌ Failed to update bos.config.json:", err.message);
|
|
177
161
|
}
|
|
178
162
|
}
|
|
179
|
-
function
|
|
180
|
-
if (!(0, node_fs.existsSync)(resultDir)) return [];
|
|
163
|
+
function parseDeployLines(output) {
|
|
181
164
|
const results = [];
|
|
182
|
-
for (const
|
|
183
|
-
if (!
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const subdirPath = (0, node_path.join)(baseDir, subdir);
|
|
196
|
-
try {
|
|
197
|
-
const stat = (0, node_fs.readdirSync)(subdirPath);
|
|
198
|
-
for (const file of stat) {
|
|
199
|
-
if (!file.endsWith(".json")) continue;
|
|
200
|
-
try {
|
|
201
|
-
const content = JSON.parse((0, node_fs.readFileSync)((0, node_path.join)(subdirPath, file), "utf8"));
|
|
202
|
-
results.push(content);
|
|
203
|
-
} catch {}
|
|
204
|
-
}
|
|
205
|
-
} catch {}
|
|
165
|
+
for (const line of output.split("\n")) {
|
|
166
|
+
if (!line.includes("[BOS_DEPLOY]")) continue;
|
|
167
|
+
const urlMatch = line.match(/url=(\S+)/);
|
|
168
|
+
const urlFieldMatch = line.match(/urlField=(\S+)/);
|
|
169
|
+
if (!urlMatch || !urlFieldMatch) continue;
|
|
170
|
+
const integrityFieldMatch = line.match(/integrityField=(\S+)/);
|
|
171
|
+
const integrityMatch = line.match(/integrity=(\S+)/);
|
|
172
|
+
results.push({
|
|
173
|
+
url: urlMatch[1],
|
|
174
|
+
urlField: urlFieldMatch[1],
|
|
175
|
+
integrityField: integrityFieldMatch?.[1] || void 0,
|
|
176
|
+
integrity: integrityMatch?.[1] || void 0
|
|
177
|
+
});
|
|
206
178
|
}
|
|
207
179
|
return results;
|
|
208
180
|
}
|
|
@@ -215,13 +187,6 @@ function applyDeployResults(config, results) {
|
|
|
215
187
|
}
|
|
216
188
|
return merged;
|
|
217
189
|
}
|
|
218
|
-
function cleanDeployResultDir(baseDir) {
|
|
219
|
-
if ((0, node_fs.existsSync)(baseDir)) (0, node_fs.rmSync)(baseDir, {
|
|
220
|
-
recursive: true,
|
|
221
|
-
force: true
|
|
222
|
-
});
|
|
223
|
-
(0, node_fs.mkdirSync)(baseDir, { recursive: true });
|
|
224
|
-
}
|
|
225
190
|
function findPluginKey(bosConfigPath, pluginDir) {
|
|
226
191
|
const plugins = JSON.parse((0, node_fs.readFileSync)(bosConfigPath, "utf8")).plugins;
|
|
227
192
|
if (!plugins) return null;
|
|
@@ -238,14 +203,12 @@ function findPluginKey(bosConfigPath, pluginDir) {
|
|
|
238
203
|
//#endregion
|
|
239
204
|
exports.IntegrityRegistry = IntegrityRegistry;
|
|
240
205
|
exports.applyDeployResults = applyDeployResults;
|
|
241
|
-
exports.cleanDeployResultDir = cleanDeployResultDir;
|
|
242
206
|
exports.computeSriHash = computeSriHash;
|
|
243
207
|
exports.computeSriHashForUrl = computeSriHashForUrl;
|
|
244
208
|
exports.findPluginKey = findPluginKey;
|
|
245
|
-
exports.
|
|
246
|
-
exports.
|
|
209
|
+
exports.parseDeployLines = parseDeployLines;
|
|
210
|
+
exports.reportDeployResult = reportDeployResult;
|
|
247
211
|
exports.resolveEntryUrl = resolveEntryUrl;
|
|
248
212
|
exports.verifyConfigAgainstChain = verifyConfigAgainstChain;
|
|
249
213
|
exports.verifySriForUrl = verifySriForUrl;
|
|
250
|
-
exports.writeDeployResult = writeDeployResult;
|
|
251
214
|
//# sourceMappingURL=integrity.cjs.map
|
package/dist/integrity.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrity.cjs","names":["fetchResponse","fetchBosConfigFromFastKv"],"sources":["../src/integrity.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { fetchBosConfigFromFastKv } from \"./fastkv\";\nimport { fetchResponse } from \"./http-client\";\n\nconst DEFAULT_MAX_SRI_RESPONSE_BYTES = 20 * 1024 * 1024;\n\ninterface SriUrlOptions {\n resolveEntryUrl?: boolean;\n maxBytes?: number;\n}\n\nexport function computeSriHash(content: string | Buffer): string {\n return `sha384-${createHash(\"sha384\").update(content).digest(\"base64\")}`;\n}\n\nfunction resolveSriTargetUrl(url: string, options?: SriUrlOptions): string {\n return options?.resolveEntryUrl === false ? url : resolveEntryUrl(url);\n}\n\nfunction getMaxSriResponseBytes(options?: SriUrlOptions): number {\n return options?.maxBytes ?? DEFAULT_MAX_SRI_RESPONSE_BYTES;\n}\n\nasync function computeSriHashFromResponse(\n response: Response,\n url: string,\n options?: SriUrlOptions,\n): Promise<string> {\n const maxBytes = getMaxSriResponseBytes(options);\n const contentLengthHeader = response.headers.get(\"content-length\");\n\n if (contentLengthHeader) {\n const contentLength = Number(contentLengthHeader);\n if (Number.isFinite(contentLength) && contentLength > maxBytes) {\n throw new Error(\n `[SRI] Response for ${url} exceeds max size of ${maxBytes} bytes (${contentLength})`,\n );\n }\n }\n\n if (!response.body) {\n throw new Error(`[SRI] Missing response body for ${url}`);\n }\n\n const hash = createHash(\"sha384\");\n const reader = response.body.getReader();\n let totalBytes = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n await reader.cancel();\n throw new Error(\n `[SRI] Response for ${url} exceeds max size of ${maxBytes} bytes (${totalBytes})`,\n );\n }\n\n hash.update(value);\n }\n\n return `sha384-${hash.digest(\"base64\")}`;\n}\n\nexport async function computeSriHashForUrl(\n url: string,\n options?: SriUrlOptions,\n): Promise<string | null> {\n try {\n const entryUrl = resolveSriTargetUrl(url, options);\n\n const response = await fetchResponse(entryUrl, { timeout: \"30 seconds\" });\n if (!response.ok) {\n console.warn(`[SRI] Failed to fetch ${entryUrl}: ${response.status} ${response.statusText}`);\n return null;\n }\n return await computeSriHashFromResponse(response, entryUrl, options);\n } catch (error) {\n console.warn(\n `[SRI] Error computing integrity for ${url}:`,\n error instanceof Error ? error.message : error,\n );\n return null;\n }\n}\n\nexport function resolveEntryUrl(url: string): string {\n if (url.endsWith(\"/remoteEntry.js\")) return url;\n if (url.endsWith(\"/mf-manifest.json\"))\n return `${url.replace(/\\/mf-manifest\\.json$/, \"\")}/remoteEntry.js`;\n return `${url.replace(/\\/$/, \"\")}/remoteEntry.js`;\n}\n\nexport async function verifySriForUrl(\n url: string,\n expectedIntegrity: string,\n options?: SriUrlOptions,\n): Promise<void> {\n const entryUrl = resolveSriTargetUrl(url, options);\n\n const response = await fetchResponse(entryUrl, { timeout: \"30 seconds\" });\n if (!response.ok) {\n console.warn(`[SRI] Failed to fetch ${entryUrl} for verification: ${response.status}`);\n return;\n }\n\n const computed = await computeSriHashFromResponse(response, entryUrl, options);\n\n if (computed !== expectedIntegrity) {\n throw new Error(\n `[SRI] Integrity check failed for ${entryUrl}\\n Expected: ${expectedIntegrity}\\n Computed: ${computed}`,\n );\n }\n}\n\nexport class IntegrityRegistry {\n private hashes = new Map<string, string>();\n\n register(url: string, integrity: string): void {\n this.hashes.set(url, integrity);\n }\n\n registerEntry(baseUrl: string, integrity: string): void {\n this.hashes.set(resolveEntryUrl(baseUrl), integrity);\n }\n\n get(url: string): string | undefined {\n return this.hashes.get(url);\n }\n\n has(url: string): boolean {\n return this.hashes.has(url);\n }\n\n entries(): IterableIterator<[string, string]> {\n return this.hashes.entries();\n }\n}\n\nfunction extractIntegrityHashes(config: Record<string, unknown>): Map<string, string> {\n const hashes = new Map<string, string>();\n const app = config.app as Record<string, Record<string, unknown>> | undefined;\n const plugins = config.plugins as Record<string, Record<string, unknown>> | undefined;\n\n if (app) {\n for (const [, entry] of Object.entries(app)) {\n if (entry?.integrity && entry?.production) {\n hashes.set(resolveEntryUrl(entry.production as string), entry.integrity as string);\n }\n }\n }\n\n if (plugins) {\n for (const [, entry] of Object.entries(plugins)) {\n if (entry?.integrity && entry?.production) {\n hashes.set(resolveEntryUrl(entry.production as string), entry.integrity as string);\n }\n }\n }\n\n return hashes;\n}\n\nexport async function verifyConfigAgainstChain(\n localConfig: Record<string, unknown>,\n bosUrl: string,\n): Promise<{ verified: boolean; mismatches: string[] }> {\n const mismatches: string[] = [];\n\n let chainConfig: Record<string, unknown>;\n try {\n chainConfig = await fetchBosConfigFromFastKv<Record<string, unknown>>(bosUrl);\n } catch (error) {\n console.warn(\n `[Attestation] Failed to fetch on-chain config: ${error instanceof Error ? error.message : String(error)}`,\n );\n return { verified: false, mismatches: [\"chain-fetch-failed\"] };\n }\n\n const localHashes = extractIntegrityHashes(localConfig);\n const chainHashes = extractIntegrityHashes(chainConfig);\n\n for (const [url, chainHash] of chainHashes) {\n const localHash = localHashes.get(url);\n if (localHash && localHash !== chainHash) {\n mismatches.push(url);\n console.error(\n `[Attestation] Integrity mismatch for ${url}\\n Local: ${localHash}\\n Chain: ${chainHash}`,\n );\n }\n }\n\n if (mismatches.length === 0 && localHashes.size > 0) {\n console.log(\n `[Attestation] Local config verified against on-chain anchor (${localHashes.size} entries checked)`,\n );\n }\n\n return { verified: mismatches.length === 0, mismatches };\n}\n\nexport interface DeployResultEntry {\n label: string;\n url: string;\n integrity?: string;\n urlField: string;\n integrityField?: string;\n}\n\nfunction setNestedPath(obj: Record<string, unknown>, dottedPath: string, value: unknown): void {\n const keys = dottedPath.split(\".\");\n let current = obj;\n for (let i = 0; i < keys.length - 1; i += 1) {\n const key = keys[i]!;\n if (current[key] === undefined || current[key] === null || typeof current[key] !== \"object\") {\n current[key] = {};\n }\n current = current[key] as Record<string, unknown>;\n }\n current[keys[keys.length - 1]!] = value;\n}\n\nfunction deleteNestedPath(obj: Record<string, unknown>, dottedPath: string): void {\n const keys = dottedPath.split(\".\");\n let current = obj;\n for (let i = 0; i < keys.length - 1; i += 1) {\n const key = keys[i]!;\n if (current[key] === undefined || typeof current[key] !== \"object\") return;\n current = current[key] as Record<string, unknown>;\n }\n delete current[keys[keys.length - 1]!];\n}\n\nfunction sanitizeFilename(name: string): string {\n return name.replace(/[^A-Za-z0-9_-]/g, \"-\");\n}\n\nexport function writeDeployResult(opts: {\n url: string;\n integrity?: string | null;\n bosConfigPath: string;\n urlField: string;\n integrityField?: string;\n label: string;\n}): void {\n const resultDir = process.env.BOS_DEPLOY_RESULT_DIR;\n\n if (resultDir) {\n mkdirSync(resultDir, { recursive: true });\n const entry: DeployResultEntry = {\n label: opts.label,\n url: opts.url,\n integrity: opts.integrity ?? undefined,\n urlField: opts.urlField,\n integrityField: opts.integrityField,\n };\n const resultFile = join(resultDir, `${sanitizeFilename(opts.label)}.json`);\n writeFileSync(resultFile, JSON.stringify(entry, null, 2));\n console.log(` ✅ Deploy result: ${opts.urlField}`);\n return;\n }\n\n try {\n const config = JSON.parse(readFileSync(opts.bosConfigPath, \"utf8\")) as Record<string, unknown>;\n setNestedPath(config, opts.urlField, opts.url);\n if (opts.integrityField) {\n if (opts.integrity) {\n setNestedPath(config, opts.integrityField, opts.integrity);\n } else {\n deleteNestedPath(config, opts.integrityField);\n }\n }\n writeFileSync(opts.bosConfigPath, `${JSON.stringify(config, null, 2)}\\n`);\n console.log(` ✅ Updated bos.config.json: ${opts.urlField}`);\n if (opts.integrityField && opts.integrity) {\n console.log(` ✅ Updated bos.config.json: ${opts.integrityField}`);\n }\n } catch (err) {\n console.error(\" ❌ Failed to update bos.config.json:\", (err as Error).message);\n }\n}\n\nexport function readDeployResults(resultDir: string): DeployResultEntry[] {\n if (!existsSync(resultDir)) return [];\n const results: DeployResultEntry[] = [];\n for (const file of readdirSync(resultDir)) {\n if (!file.endsWith(\".json\")) continue;\n try {\n const content = JSON.parse(readFileSync(join(resultDir, file), \"utf8\")) as DeployResultEntry;\n results.push(content);\n } catch {\n // skip malformed files\n }\n }\n return results;\n}\n\nexport function readAllDeployResults(baseDir: string): DeployResultEntry[] {\n if (!existsSync(baseDir)) return [];\n const results: DeployResultEntry[] = [];\n for (const subdir of readdirSync(baseDir)) {\n const subdirPath = join(baseDir, subdir);\n try {\n const stat = readdirSync(subdirPath);\n for (const file of stat) {\n if (!file.endsWith(\".json\")) continue;\n try {\n const content = JSON.parse(\n readFileSync(join(subdirPath, file), \"utf8\"),\n ) as DeployResultEntry;\n results.push(content);\n } catch {\n // skip malformed files\n }\n }\n } catch {\n // not a directory, skip\n }\n }\n return results;\n}\n\nexport function applyDeployResults(\n config: Record<string, unknown>,\n results: DeployResultEntry[],\n): Record<string, unknown> {\n const merged = structuredClone(config);\n for (const result of results) {\n setNestedPath(merged, result.urlField, result.url);\n if (result.integrityField) {\n if (result.integrity) {\n setNestedPath(merged, result.integrityField, result.integrity);\n } else {\n deleteNestedPath(merged, result.integrityField);\n }\n }\n }\n return merged;\n}\n\nexport function cleanDeployResultDir(baseDir: string): void {\n if (existsSync(baseDir)) {\n rmSync(baseDir, { recursive: true, force: true });\n }\n mkdirSync(baseDir, { recursive: true });\n}\n\nexport function findPluginKey(bosConfigPath: string, pluginDir: string): string | null {\n const config = JSON.parse(readFileSync(bosConfigPath, \"utf8\")) as Record<string, unknown>;\n const plugins = config.plugins as Record<string, Record<string, unknown>> | undefined;\n if (!plugins) return null;\n const configRoot = join(bosConfigPath, \"..\");\n const normalizedPluginDir = pluginDir.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n for (const [key, plugin] of Object.entries(plugins)) {\n const dev = plugin?.development;\n if (typeof dev !== \"string\" || !dev.startsWith(\"local:\")) continue;\n const resolved = join(configRoot, dev.slice(\"local:\".length))\n .replace(/\\\\/g, \"/\")\n .replace(/\\/+$/, \"\");\n if (resolved === normalizedPluginDir) return key;\n }\n return null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"integrity.cjs","names":["fetchResponse","fetchBosConfigFromFastKv"],"sources":["../src/integrity.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { fetchBosConfigFromFastKv } from \"./fastkv\";\nimport { fetchResponse } from \"./http-client\";\n\nconst DEFAULT_MAX_SRI_RESPONSE_BYTES = 20 * 1024 * 1024;\n\ninterface SriUrlOptions {\n resolveEntryUrl?: boolean;\n maxBytes?: number;\n}\n\nexport function computeSriHash(content: string | Buffer): string {\n return `sha384-${createHash(\"sha384\").update(content).digest(\"base64\")}`;\n}\n\nfunction resolveSriTargetUrl(url: string, options?: SriUrlOptions): string {\n return options?.resolveEntryUrl === false ? url : resolveEntryUrl(url);\n}\n\nfunction getMaxSriResponseBytes(options?: SriUrlOptions): number {\n return options?.maxBytes ?? DEFAULT_MAX_SRI_RESPONSE_BYTES;\n}\n\nasync function computeSriHashFromResponse(\n response: Response,\n url: string,\n options?: SriUrlOptions,\n): Promise<string> {\n const maxBytes = getMaxSriResponseBytes(options);\n const contentLengthHeader = response.headers.get(\"content-length\");\n\n if (contentLengthHeader) {\n const contentLength = Number(contentLengthHeader);\n if (Number.isFinite(contentLength) && contentLength > maxBytes) {\n throw new Error(\n `[SRI] Response for ${url} exceeds max size of ${maxBytes} bytes (${contentLength})`,\n );\n }\n }\n\n if (!response.body) {\n throw new Error(`[SRI] Missing response body for ${url}`);\n }\n\n const hash = createHash(\"sha384\");\n const reader = response.body.getReader();\n let totalBytes = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n await reader.cancel();\n throw new Error(\n `[SRI] Response for ${url} exceeds max size of ${maxBytes} bytes (${totalBytes})`,\n );\n }\n\n hash.update(value);\n }\n\n return `sha384-${hash.digest(\"base64\")}`;\n}\n\nexport async function computeSriHashForUrl(\n url: string,\n options?: SriUrlOptions,\n): Promise<string | null> {\n try {\n const entryUrl = resolveSriTargetUrl(url, options);\n\n const response = await fetchResponse(entryUrl, { timeout: \"30 seconds\" });\n if (!response.ok) {\n console.warn(`[SRI] Failed to fetch ${entryUrl}: ${response.status} ${response.statusText}`);\n return null;\n }\n return await computeSriHashFromResponse(response, entryUrl, options);\n } catch (error) {\n console.warn(\n `[SRI] Error computing integrity for ${url}:`,\n error instanceof Error ? error.message : error,\n );\n return null;\n }\n}\n\nexport function resolveEntryUrl(url: string): string {\n if (url.endsWith(\"/remoteEntry.js\")) return url;\n if (url.endsWith(\"/mf-manifest.json\"))\n return `${url.replace(/\\/mf-manifest\\.json$/, \"\")}/remoteEntry.js`;\n return `${url.replace(/\\/$/, \"\")}/remoteEntry.js`;\n}\n\nexport async function verifySriForUrl(\n url: string,\n expectedIntegrity: string,\n options?: SriUrlOptions,\n): Promise<void> {\n const entryUrl = resolveSriTargetUrl(url, options);\n\n const response = await fetchResponse(entryUrl, { timeout: \"30 seconds\" });\n if (!response.ok) {\n console.warn(`[SRI] Failed to fetch ${entryUrl} for verification: ${response.status}`);\n return;\n }\n\n const computed = await computeSriHashFromResponse(response, entryUrl, options);\n\n if (computed !== expectedIntegrity) {\n throw new Error(\n `[SRI] Integrity check failed for ${entryUrl}\\n Expected: ${expectedIntegrity}\\n Computed: ${computed}`,\n );\n }\n}\n\nexport class IntegrityRegistry {\n private hashes = new Map<string, string>();\n\n register(url: string, integrity: string): void {\n this.hashes.set(url, integrity);\n }\n\n registerEntry(baseUrl: string, integrity: string): void {\n this.hashes.set(resolveEntryUrl(baseUrl), integrity);\n }\n\n get(url: string): string | undefined {\n return this.hashes.get(url);\n }\n\n has(url: string): boolean {\n return this.hashes.has(url);\n }\n\n entries(): IterableIterator<[string, string]> {\n return this.hashes.entries();\n }\n}\n\nfunction extractIntegrityHashes(config: Record<string, unknown>): Map<string, string> {\n const hashes = new Map<string, string>();\n const app = config.app as Record<string, Record<string, unknown>> | undefined;\n const plugins = config.plugins as Record<string, Record<string, unknown>> | undefined;\n\n if (app) {\n for (const [, entry] of Object.entries(app)) {\n if (entry?.integrity && entry?.production) {\n hashes.set(resolveEntryUrl(entry.production as string), entry.integrity as string);\n }\n }\n }\n\n if (plugins) {\n for (const [, entry] of Object.entries(plugins)) {\n if (entry?.integrity && entry?.production) {\n hashes.set(resolveEntryUrl(entry.production as string), entry.integrity as string);\n }\n }\n }\n\n return hashes;\n}\n\nexport async function verifyConfigAgainstChain(\n localConfig: Record<string, unknown>,\n bosUrl: string,\n): Promise<{ verified: boolean; mismatches: string[] }> {\n const mismatches: string[] = [];\n\n let chainConfig: Record<string, unknown>;\n try {\n chainConfig = await fetchBosConfigFromFastKv<Record<string, unknown>>(bosUrl);\n } catch (error) {\n console.warn(\n `[Attestation] Failed to fetch on-chain config: ${error instanceof Error ? error.message : String(error)}`,\n );\n return { verified: false, mismatches: [\"chain-fetch-failed\"] };\n }\n\n const localHashes = extractIntegrityHashes(localConfig);\n const chainHashes = extractIntegrityHashes(chainConfig);\n\n for (const [url, chainHash] of chainHashes) {\n const localHash = localHashes.get(url);\n if (localHash && localHash !== chainHash) {\n mismatches.push(url);\n console.error(\n `[Attestation] Integrity mismatch for ${url}\\n Local: ${localHash}\\n Chain: ${chainHash}`,\n );\n }\n }\n\n if (mismatches.length === 0 && localHashes.size > 0) {\n console.log(\n `[Attestation] Local config verified against on-chain anchor (${localHashes.size} entries checked)`,\n );\n }\n\n return { verified: mismatches.length === 0, mismatches };\n}\n\nexport interface DeployResultEntry {\n url: string;\n integrity?: string;\n urlField: string;\n integrityField?: string;\n}\n\nfunction setNestedPath(obj: Record<string, unknown>, dottedPath: string, value: unknown): void {\n const keys = dottedPath.split(\".\");\n let current = obj;\n for (let i = 0; i < keys.length - 1; i += 1) {\n const key = keys[i]!;\n if (current[key] === undefined || current[key] === null || typeof current[key] !== \"object\") {\n current[key] = {};\n }\n current = current[key] as Record<string, unknown>;\n }\n current[keys[keys.length - 1]!] = value;\n}\n\nfunction deleteNestedPath(obj: Record<string, unknown>, dottedPath: string): void {\n const keys = dottedPath.split(\".\");\n let current = obj;\n for (let i = 0; i < keys.length - 1; i += 1) {\n const key = keys[i]!;\n if (current[key] === undefined || typeof current[key] !== \"object\") return;\n current = current[key] as Record<string, unknown>;\n }\n delete current[keys[keys.length - 1]!];\n}\n\nexport function reportDeployResult(opts: {\n url: string;\n integrity?: string | null;\n bosConfigPath: string;\n urlField: string;\n integrityField?: string;\n}): void {\n console.log(\n `[BOS_DEPLOY] url=${opts.url} urlField=${opts.urlField} integrityField=${opts.integrityField ?? \"\"} integrity=${opts.integrity ?? \"\"}`,\n );\n\n try {\n const config = JSON.parse(readFileSync(opts.bosConfigPath, \"utf8\")) as Record<string, unknown>;\n setNestedPath(config, opts.urlField, opts.url);\n if (opts.integrityField) {\n if (opts.integrity) {\n setNestedPath(config, opts.integrityField, opts.integrity);\n } else {\n deleteNestedPath(config, opts.integrityField);\n }\n }\n writeFileSync(opts.bosConfigPath, `${JSON.stringify(config, null, 2)}\\n`);\n console.log(` ✅ Updated bos.config.json: ${opts.urlField}`);\n if (opts.integrityField && opts.integrity) {\n console.log(` ✅ Updated bos.config.json: ${opts.integrityField}`);\n }\n } catch (err) {\n console.error(\" ❌ Failed to update bos.config.json:\", (err as Error).message);\n }\n}\n\nexport function parseDeployLines(output: string): DeployResultEntry[] {\n const results: DeployResultEntry[] = [];\n for (const line of output.split(\"\\n\")) {\n if (!line.includes(\"[BOS_DEPLOY]\")) continue;\n const urlMatch = line.match(/url=(\\S+)/);\n const urlFieldMatch = line.match(/urlField=(\\S+)/);\n if (!urlMatch || !urlFieldMatch) continue;\n const integrityFieldMatch = line.match(/integrityField=(\\S+)/);\n const integrityMatch = line.match(/integrity=(\\S+)/);\n results.push({\n url: urlMatch[1],\n urlField: urlFieldMatch[1],\n integrityField: integrityFieldMatch?.[1] || undefined,\n integrity: integrityMatch?.[1] || undefined,\n });\n }\n return results;\n}\n\nexport function applyDeployResults(\n config: Record<string, unknown>,\n results: DeployResultEntry[],\n): Record<string, unknown> {\n const merged = structuredClone(config);\n for (const result of results) {\n setNestedPath(merged, result.urlField, result.url);\n if (result.integrityField) {\n if (result.integrity) {\n setNestedPath(merged, result.integrityField, result.integrity);\n } else {\n deleteNestedPath(merged, result.integrityField);\n }\n }\n }\n return merged;\n}\n\nexport function findPluginKey(bosConfigPath: string, pluginDir: string): string | null {\n const config = JSON.parse(readFileSync(bosConfigPath, \"utf8\")) as Record<string, unknown>;\n const plugins = config.plugins as Record<string, Record<string, unknown>> | undefined;\n if (!plugins) return null;\n const configRoot = join(bosConfigPath, \"..\");\n const normalizedPluginDir = pluginDir.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n for (const [key, plugin] of Object.entries(plugins)) {\n const dev = plugin?.development;\n if (typeof dev !== \"string\" || !dev.startsWith(\"local:\")) continue;\n const resolved = join(configRoot, dev.slice(\"local:\".length))\n .replace(/\\\\/g, \"/\")\n .replace(/\\/+$/, \"\");\n if (resolved === normalizedPluginDir) return key;\n }\n return null;\n}\n"],"mappings":"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"}
|
package/dist/integrity.d.cts
CHANGED
|
@@ -20,25 +20,21 @@ declare function verifyConfigAgainstChain(localConfig: Record<string, unknown>,
|
|
|
20
20
|
mismatches: string[];
|
|
21
21
|
}>;
|
|
22
22
|
interface DeployResultEntry {
|
|
23
|
-
label: string;
|
|
24
23
|
url: string;
|
|
25
24
|
integrity?: string;
|
|
26
25
|
urlField: string;
|
|
27
26
|
integrityField?: string;
|
|
28
27
|
}
|
|
29
|
-
declare function
|
|
28
|
+
declare function reportDeployResult(opts: {
|
|
30
29
|
url: string;
|
|
31
30
|
integrity?: string | null;
|
|
32
31
|
bosConfigPath: string;
|
|
33
32
|
urlField: string;
|
|
34
33
|
integrityField?: string;
|
|
35
|
-
label: string;
|
|
36
34
|
}): void;
|
|
37
|
-
declare function
|
|
38
|
-
declare function readAllDeployResults(baseDir: string): DeployResultEntry[];
|
|
35
|
+
declare function parseDeployLines(output: string): DeployResultEntry[];
|
|
39
36
|
declare function applyDeployResults(config: Record<string, unknown>, results: DeployResultEntry[]): Record<string, unknown>;
|
|
40
|
-
declare function cleanDeployResultDir(baseDir: string): void;
|
|
41
37
|
declare function findPluginKey(bosConfigPath: string, pluginDir: string): string | null;
|
|
42
38
|
//#endregion
|
|
43
|
-
export { DeployResultEntry, IntegrityRegistry, applyDeployResults,
|
|
39
|
+
export { DeployResultEntry, IntegrityRegistry, applyDeployResults, computeSriHash, computeSriHashForUrl, findPluginKey, parseDeployLines, reportDeployResult, resolveEntryUrl, verifyConfigAgainstChain, verifySriForUrl };
|
|
44
40
|
//# sourceMappingURL=integrity.d.cts.map
|
package/dist/integrity.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrity.d.cts","names":[],"sources":["../src/integrity.ts"],"mappings":";UAQU,aAAA;EACR,eAAA;EACA,QAAA;AAAA;AAAA,iBAGc,cAAA,CAAe,OAAA,WAAkB,MAAA;AAAA,iBAyD3B,oBAAA,CACpB,GAAA,UACA,OAAA,GAAU,aAAA,GACT,OAAA;AAAA,iBAmBa,eAAA,CAAgB,GAAA;AAAA,iBAOV,eAAA,CACpB,GAAA,UACA,iBAAA,UACA,OAAA,GAAU,aAAA,GACT,OAAA;AAAA,cAkBU,iBAAA;EAAA,QACH,MAAA;EAER,QAAA,CAAS,GAAA,UAAa,SAAA;EAItB,aAAA,CAAc,OAAA,UAAiB,SAAA;EAI/B,GAAA,CAAI,GAAA;EAIJ,GAAA,CAAI,GAAA;EAIJ,OAAA,CAAA,GAAW,gBAAA;AAAA;AAAA,iBA6BS,wBAAA,CACpB,WAAA,EAAa,MAAA,mBACb,MAAA,WACC,OAAA;EAAU,QAAA;EAAmB,UAAA;AAAA;AAAA,UAmCf,iBAAA;EACf,
|
|
1
|
+
{"version":3,"file":"integrity.d.cts","names":[],"sources":["../src/integrity.ts"],"mappings":";UAQU,aAAA;EACR,eAAA;EACA,QAAA;AAAA;AAAA,iBAGc,cAAA,CAAe,OAAA,WAAkB,MAAA;AAAA,iBAyD3B,oBAAA,CACpB,GAAA,UACA,OAAA,GAAU,aAAA,GACT,OAAA;AAAA,iBAmBa,eAAA,CAAgB,GAAA;AAAA,iBAOV,eAAA,CACpB,GAAA,UACA,iBAAA,UACA,OAAA,GAAU,aAAA,GACT,OAAA;AAAA,cAkBU,iBAAA;EAAA,QACH,MAAA;EAER,QAAA,CAAS,GAAA,UAAa,SAAA;EAItB,aAAA,CAAc,OAAA,UAAiB,SAAA;EAI/B,GAAA,CAAI,GAAA;EAIJ,GAAA,CAAI,GAAA;EAIJ,OAAA,CAAA,GAAW,gBAAA;AAAA;AAAA,iBA6BS,wBAAA,CACpB,WAAA,EAAa,MAAA,mBACb,MAAA,WACC,OAAA;EAAU,QAAA;EAAmB,UAAA;AAAA;AAAA,UAmCf,iBAAA;EACf,GAAA;EACA,SAAA;EACA,QAAA;EACA,cAAA;AAAA;AAAA,iBA2Bc,kBAAA,CAAmB,IAAA;EACjC,GAAA;EACA,SAAA;EACA,aAAA;EACA,QAAA;EACA,cAAA;AAAA;AAAA,iBA0Bc,gBAAA,CAAiB,MAAA,WAAiB,iBAAA;AAAA,iBAmBlC,kBAAA,CACd,MAAA,EAAQ,MAAA,mBACR,OAAA,EAAS,iBAAA,KACR,MAAA;AAAA,iBAea,aAAA,CAAc,aAAA,UAAuB,SAAA"}
|
package/dist/integrity.d.mts
CHANGED
|
@@ -20,25 +20,21 @@ declare function verifyConfigAgainstChain(localConfig: Record<string, unknown>,
|
|
|
20
20
|
mismatches: string[];
|
|
21
21
|
}>;
|
|
22
22
|
interface DeployResultEntry {
|
|
23
|
-
label: string;
|
|
24
23
|
url: string;
|
|
25
24
|
integrity?: string;
|
|
26
25
|
urlField: string;
|
|
27
26
|
integrityField?: string;
|
|
28
27
|
}
|
|
29
|
-
declare function
|
|
28
|
+
declare function reportDeployResult(opts: {
|
|
30
29
|
url: string;
|
|
31
30
|
integrity?: string | null;
|
|
32
31
|
bosConfigPath: string;
|
|
33
32
|
urlField: string;
|
|
34
33
|
integrityField?: string;
|
|
35
|
-
label: string;
|
|
36
34
|
}): void;
|
|
37
|
-
declare function
|
|
38
|
-
declare function readAllDeployResults(baseDir: string): DeployResultEntry[];
|
|
35
|
+
declare function parseDeployLines(output: string): DeployResultEntry[];
|
|
39
36
|
declare function applyDeployResults(config: Record<string, unknown>, results: DeployResultEntry[]): Record<string, unknown>;
|
|
40
|
-
declare function cleanDeployResultDir(baseDir: string): void;
|
|
41
37
|
declare function findPluginKey(bosConfigPath: string, pluginDir: string): string | null;
|
|
42
38
|
//#endregion
|
|
43
|
-
export { DeployResultEntry, IntegrityRegistry, applyDeployResults,
|
|
39
|
+
export { DeployResultEntry, IntegrityRegistry, applyDeployResults, computeSriHash, computeSriHashForUrl, findPluginKey, parseDeployLines, reportDeployResult, resolveEntryUrl, verifyConfigAgainstChain, verifySriForUrl };
|
|
44
40
|
//# sourceMappingURL=integrity.d.mts.map
|
package/dist/integrity.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrity.d.mts","names":[],"sources":["../src/integrity.ts"],"mappings":";UAQU,aAAA;EACR,eAAA;EACA,QAAA;AAAA;AAAA,iBAGc,cAAA,CAAe,OAAA,WAAkB,MAAA;AAAA,iBAyD3B,oBAAA,CACpB,GAAA,UACA,OAAA,GAAU,aAAA,GACT,OAAA;AAAA,iBAmBa,eAAA,CAAgB,GAAA;AAAA,iBAOV,eAAA,CACpB,GAAA,UACA,iBAAA,UACA,OAAA,GAAU,aAAA,GACT,OAAA;AAAA,cAkBU,iBAAA;EAAA,QACH,MAAA;EAER,QAAA,CAAS,GAAA,UAAa,SAAA;EAItB,aAAA,CAAc,OAAA,UAAiB,SAAA;EAI/B,GAAA,CAAI,GAAA;EAIJ,GAAA,CAAI,GAAA;EAIJ,OAAA,CAAA,GAAW,gBAAA;AAAA;AAAA,iBA6BS,wBAAA,CACpB,WAAA,EAAa,MAAA,mBACb,MAAA,WACC,OAAA;EAAU,QAAA;EAAmB,UAAA;AAAA;AAAA,UAmCf,iBAAA;EACf,
|
|
1
|
+
{"version":3,"file":"integrity.d.mts","names":[],"sources":["../src/integrity.ts"],"mappings":";UAQU,aAAA;EACR,eAAA;EACA,QAAA;AAAA;AAAA,iBAGc,cAAA,CAAe,OAAA,WAAkB,MAAA;AAAA,iBAyD3B,oBAAA,CACpB,GAAA,UACA,OAAA,GAAU,aAAA,GACT,OAAA;AAAA,iBAmBa,eAAA,CAAgB,GAAA;AAAA,iBAOV,eAAA,CACpB,GAAA,UACA,iBAAA,UACA,OAAA,GAAU,aAAA,GACT,OAAA;AAAA,cAkBU,iBAAA;EAAA,QACH,MAAA;EAER,QAAA,CAAS,GAAA,UAAa,SAAA;EAItB,aAAA,CAAc,OAAA,UAAiB,SAAA;EAI/B,GAAA,CAAI,GAAA;EAIJ,GAAA,CAAI,GAAA;EAIJ,OAAA,CAAA,GAAW,gBAAA;AAAA;AAAA,iBA6BS,wBAAA,CACpB,WAAA,EAAa,MAAA,mBACb,MAAA,WACC,OAAA;EAAU,QAAA;EAAmB,UAAA;AAAA;AAAA,UAmCf,iBAAA;EACf,GAAA;EACA,SAAA;EACA,QAAA;EACA,cAAA;AAAA;AAAA,iBA2Bc,kBAAA,CAAmB,IAAA;EACjC,GAAA;EACA,SAAA;EACA,aAAA;EACA,QAAA;EACA,cAAA;AAAA;AAAA,iBA0Bc,gBAAA,CAAiB,MAAA,WAAiB,iBAAA;AAAA,iBAmBlC,kBAAA,CACd,MAAA,EAAQ,MAAA,mBACR,OAAA,EAAS,iBAAA,KACR,MAAA;AAAA,iBAea,aAAA,CAAc,aAAA,UAAuB,SAAA"}
|
package/dist/integrity.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fetchResponse } from "./http-client.mjs";
|
|
2
2
|
import { fetchBosConfigFromFastKv } from "./fastkv.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
6
|
|
|
@@ -144,24 +144,8 @@ function deleteNestedPath(obj, dottedPath) {
|
|
|
144
144
|
}
|
|
145
145
|
delete current[keys[keys.length - 1]];
|
|
146
146
|
}
|
|
147
|
-
function
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
function writeDeployResult(opts) {
|
|
151
|
-
const resultDir = process.env.BOS_DEPLOY_RESULT_DIR;
|
|
152
|
-
if (resultDir) {
|
|
153
|
-
mkdirSync(resultDir, { recursive: true });
|
|
154
|
-
const entry = {
|
|
155
|
-
label: opts.label,
|
|
156
|
-
url: opts.url,
|
|
157
|
-
integrity: opts.integrity ?? void 0,
|
|
158
|
-
urlField: opts.urlField,
|
|
159
|
-
integrityField: opts.integrityField
|
|
160
|
-
};
|
|
161
|
-
writeFileSync(join(resultDir, `${sanitizeFilename(opts.label)}.json`), JSON.stringify(entry, null, 2));
|
|
162
|
-
console.log(` ✅ Deploy result: ${opts.urlField}`);
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
147
|
+
function reportDeployResult(opts) {
|
|
148
|
+
console.log(`[BOS_DEPLOY] url=${opts.url} urlField=${opts.urlField} integrityField=${opts.integrityField ?? ""} integrity=${opts.integrity ?? ""}`);
|
|
165
149
|
try {
|
|
166
150
|
const config = JSON.parse(readFileSync(opts.bosConfigPath, "utf8"));
|
|
167
151
|
setNestedPath(config, opts.urlField, opts.url);
|
|
@@ -174,33 +158,21 @@ function writeDeployResult(opts) {
|
|
|
174
158
|
console.error(" ❌ Failed to update bos.config.json:", err.message);
|
|
175
159
|
}
|
|
176
160
|
}
|
|
177
|
-
function
|
|
178
|
-
if (!existsSync(resultDir)) return [];
|
|
161
|
+
function parseDeployLines(output) {
|
|
179
162
|
const results = [];
|
|
180
|
-
for (const
|
|
181
|
-
if (!
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const subdirPath = join(baseDir, subdir);
|
|
194
|
-
try {
|
|
195
|
-
const stat = readdirSync(subdirPath);
|
|
196
|
-
for (const file of stat) {
|
|
197
|
-
if (!file.endsWith(".json")) continue;
|
|
198
|
-
try {
|
|
199
|
-
const content = JSON.parse(readFileSync(join(subdirPath, file), "utf8"));
|
|
200
|
-
results.push(content);
|
|
201
|
-
} catch {}
|
|
202
|
-
}
|
|
203
|
-
} catch {}
|
|
163
|
+
for (const line of output.split("\n")) {
|
|
164
|
+
if (!line.includes("[BOS_DEPLOY]")) continue;
|
|
165
|
+
const urlMatch = line.match(/url=(\S+)/);
|
|
166
|
+
const urlFieldMatch = line.match(/urlField=(\S+)/);
|
|
167
|
+
if (!urlMatch || !urlFieldMatch) continue;
|
|
168
|
+
const integrityFieldMatch = line.match(/integrityField=(\S+)/);
|
|
169
|
+
const integrityMatch = line.match(/integrity=(\S+)/);
|
|
170
|
+
results.push({
|
|
171
|
+
url: urlMatch[1],
|
|
172
|
+
urlField: urlFieldMatch[1],
|
|
173
|
+
integrityField: integrityFieldMatch?.[1] || void 0,
|
|
174
|
+
integrity: integrityMatch?.[1] || void 0
|
|
175
|
+
});
|
|
204
176
|
}
|
|
205
177
|
return results;
|
|
206
178
|
}
|
|
@@ -213,13 +185,6 @@ function applyDeployResults(config, results) {
|
|
|
213
185
|
}
|
|
214
186
|
return merged;
|
|
215
187
|
}
|
|
216
|
-
function cleanDeployResultDir(baseDir) {
|
|
217
|
-
if (existsSync(baseDir)) rmSync(baseDir, {
|
|
218
|
-
recursive: true,
|
|
219
|
-
force: true
|
|
220
|
-
});
|
|
221
|
-
mkdirSync(baseDir, { recursive: true });
|
|
222
|
-
}
|
|
223
188
|
function findPluginKey(bosConfigPath, pluginDir) {
|
|
224
189
|
const plugins = JSON.parse(readFileSync(bosConfigPath, "utf8")).plugins;
|
|
225
190
|
if (!plugins) return null;
|
|
@@ -234,5 +199,5 @@ function findPluginKey(bosConfigPath, pluginDir) {
|
|
|
234
199
|
}
|
|
235
200
|
|
|
236
201
|
//#endregion
|
|
237
|
-
export { IntegrityRegistry, applyDeployResults,
|
|
202
|
+
export { IntegrityRegistry, applyDeployResults, computeSriHash, computeSriHashForUrl, findPluginKey, parseDeployLines, reportDeployResult, resolveEntryUrl, verifyConfigAgainstChain, verifySriForUrl };
|
|
238
203
|
//# sourceMappingURL=integrity.mjs.map
|
package/dist/integrity.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrity.mjs","names":[],"sources":["../src/integrity.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { fetchBosConfigFromFastKv } from \"./fastkv\";\nimport { fetchResponse } from \"./http-client\";\n\nconst DEFAULT_MAX_SRI_RESPONSE_BYTES = 20 * 1024 * 1024;\n\ninterface SriUrlOptions {\n resolveEntryUrl?: boolean;\n maxBytes?: number;\n}\n\nexport function computeSriHash(content: string | Buffer): string {\n return `sha384-${createHash(\"sha384\").update(content).digest(\"base64\")}`;\n}\n\nfunction resolveSriTargetUrl(url: string, options?: SriUrlOptions): string {\n return options?.resolveEntryUrl === false ? url : resolveEntryUrl(url);\n}\n\nfunction getMaxSriResponseBytes(options?: SriUrlOptions): number {\n return options?.maxBytes ?? DEFAULT_MAX_SRI_RESPONSE_BYTES;\n}\n\nasync function computeSriHashFromResponse(\n response: Response,\n url: string,\n options?: SriUrlOptions,\n): Promise<string> {\n const maxBytes = getMaxSriResponseBytes(options);\n const contentLengthHeader = response.headers.get(\"content-length\");\n\n if (contentLengthHeader) {\n const contentLength = Number(contentLengthHeader);\n if (Number.isFinite(contentLength) && contentLength > maxBytes) {\n throw new Error(\n `[SRI] Response for ${url} exceeds max size of ${maxBytes} bytes (${contentLength})`,\n );\n }\n }\n\n if (!response.body) {\n throw new Error(`[SRI] Missing response body for ${url}`);\n }\n\n const hash = createHash(\"sha384\");\n const reader = response.body.getReader();\n let totalBytes = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n await reader.cancel();\n throw new Error(\n `[SRI] Response for ${url} exceeds max size of ${maxBytes} bytes (${totalBytes})`,\n );\n }\n\n hash.update(value);\n }\n\n return `sha384-${hash.digest(\"base64\")}`;\n}\n\nexport async function computeSriHashForUrl(\n url: string,\n options?: SriUrlOptions,\n): Promise<string | null> {\n try {\n const entryUrl = resolveSriTargetUrl(url, options);\n\n const response = await fetchResponse(entryUrl, { timeout: \"30 seconds\" });\n if (!response.ok) {\n console.warn(`[SRI] Failed to fetch ${entryUrl}: ${response.status} ${response.statusText}`);\n return null;\n }\n return await computeSriHashFromResponse(response, entryUrl, options);\n } catch (error) {\n console.warn(\n `[SRI] Error computing integrity for ${url}:`,\n error instanceof Error ? error.message : error,\n );\n return null;\n }\n}\n\nexport function resolveEntryUrl(url: string): string {\n if (url.endsWith(\"/remoteEntry.js\")) return url;\n if (url.endsWith(\"/mf-manifest.json\"))\n return `${url.replace(/\\/mf-manifest\\.json$/, \"\")}/remoteEntry.js`;\n return `${url.replace(/\\/$/, \"\")}/remoteEntry.js`;\n}\n\nexport async function verifySriForUrl(\n url: string,\n expectedIntegrity: string,\n options?: SriUrlOptions,\n): Promise<void> {\n const entryUrl = resolveSriTargetUrl(url, options);\n\n const response = await fetchResponse(entryUrl, { timeout: \"30 seconds\" });\n if (!response.ok) {\n console.warn(`[SRI] Failed to fetch ${entryUrl} for verification: ${response.status}`);\n return;\n }\n\n const computed = await computeSriHashFromResponse(response, entryUrl, options);\n\n if (computed !== expectedIntegrity) {\n throw new Error(\n `[SRI] Integrity check failed for ${entryUrl}\\n Expected: ${expectedIntegrity}\\n Computed: ${computed}`,\n );\n }\n}\n\nexport class IntegrityRegistry {\n private hashes = new Map<string, string>();\n\n register(url: string, integrity: string): void {\n this.hashes.set(url, integrity);\n }\n\n registerEntry(baseUrl: string, integrity: string): void {\n this.hashes.set(resolveEntryUrl(baseUrl), integrity);\n }\n\n get(url: string): string | undefined {\n return this.hashes.get(url);\n }\n\n has(url: string): boolean {\n return this.hashes.has(url);\n }\n\n entries(): IterableIterator<[string, string]> {\n return this.hashes.entries();\n }\n}\n\nfunction extractIntegrityHashes(config: Record<string, unknown>): Map<string, string> {\n const hashes = new Map<string, string>();\n const app = config.app as Record<string, Record<string, unknown>> | undefined;\n const plugins = config.plugins as Record<string, Record<string, unknown>> | undefined;\n\n if (app) {\n for (const [, entry] of Object.entries(app)) {\n if (entry?.integrity && entry?.production) {\n hashes.set(resolveEntryUrl(entry.production as string), entry.integrity as string);\n }\n }\n }\n\n if (plugins) {\n for (const [, entry] of Object.entries(plugins)) {\n if (entry?.integrity && entry?.production) {\n hashes.set(resolveEntryUrl(entry.production as string), entry.integrity as string);\n }\n }\n }\n\n return hashes;\n}\n\nexport async function verifyConfigAgainstChain(\n localConfig: Record<string, unknown>,\n bosUrl: string,\n): Promise<{ verified: boolean; mismatches: string[] }> {\n const mismatches: string[] = [];\n\n let chainConfig: Record<string, unknown>;\n try {\n chainConfig = await fetchBosConfigFromFastKv<Record<string, unknown>>(bosUrl);\n } catch (error) {\n console.warn(\n `[Attestation] Failed to fetch on-chain config: ${error instanceof Error ? error.message : String(error)}`,\n );\n return { verified: false, mismatches: [\"chain-fetch-failed\"] };\n }\n\n const localHashes = extractIntegrityHashes(localConfig);\n const chainHashes = extractIntegrityHashes(chainConfig);\n\n for (const [url, chainHash] of chainHashes) {\n const localHash = localHashes.get(url);\n if (localHash && localHash !== chainHash) {\n mismatches.push(url);\n console.error(\n `[Attestation] Integrity mismatch for ${url}\\n Local: ${localHash}\\n Chain: ${chainHash}`,\n );\n }\n }\n\n if (mismatches.length === 0 && localHashes.size > 0) {\n console.log(\n `[Attestation] Local config verified against on-chain anchor (${localHashes.size} entries checked)`,\n );\n }\n\n return { verified: mismatches.length === 0, mismatches };\n}\n\nexport interface DeployResultEntry {\n label: string;\n url: string;\n integrity?: string;\n urlField: string;\n integrityField?: string;\n}\n\nfunction setNestedPath(obj: Record<string, unknown>, dottedPath: string, value: unknown): void {\n const keys = dottedPath.split(\".\");\n let current = obj;\n for (let i = 0; i < keys.length - 1; i += 1) {\n const key = keys[i]!;\n if (current[key] === undefined || current[key] === null || typeof current[key] !== \"object\") {\n current[key] = {};\n }\n current = current[key] as Record<string, unknown>;\n }\n current[keys[keys.length - 1]!] = value;\n}\n\nfunction deleteNestedPath(obj: Record<string, unknown>, dottedPath: string): void {\n const keys = dottedPath.split(\".\");\n let current = obj;\n for (let i = 0; i < keys.length - 1; i += 1) {\n const key = keys[i]!;\n if (current[key] === undefined || typeof current[key] !== \"object\") return;\n current = current[key] as Record<string, unknown>;\n }\n delete current[keys[keys.length - 1]!];\n}\n\nfunction sanitizeFilename(name: string): string {\n return name.replace(/[^A-Za-z0-9_-]/g, \"-\");\n}\n\nexport function writeDeployResult(opts: {\n url: string;\n integrity?: string | null;\n bosConfigPath: string;\n urlField: string;\n integrityField?: string;\n label: string;\n}): void {\n const resultDir = process.env.BOS_DEPLOY_RESULT_DIR;\n\n if (resultDir) {\n mkdirSync(resultDir, { recursive: true });\n const entry: DeployResultEntry = {\n label: opts.label,\n url: opts.url,\n integrity: opts.integrity ?? undefined,\n urlField: opts.urlField,\n integrityField: opts.integrityField,\n };\n const resultFile = join(resultDir, `${sanitizeFilename(opts.label)}.json`);\n writeFileSync(resultFile, JSON.stringify(entry, null, 2));\n console.log(` ✅ Deploy result: ${opts.urlField}`);\n return;\n }\n\n try {\n const config = JSON.parse(readFileSync(opts.bosConfigPath, \"utf8\")) as Record<string, unknown>;\n setNestedPath(config, opts.urlField, opts.url);\n if (opts.integrityField) {\n if (opts.integrity) {\n setNestedPath(config, opts.integrityField, opts.integrity);\n } else {\n deleteNestedPath(config, opts.integrityField);\n }\n }\n writeFileSync(opts.bosConfigPath, `${JSON.stringify(config, null, 2)}\\n`);\n console.log(` ✅ Updated bos.config.json: ${opts.urlField}`);\n if (opts.integrityField && opts.integrity) {\n console.log(` ✅ Updated bos.config.json: ${opts.integrityField}`);\n }\n } catch (err) {\n console.error(\" ❌ Failed to update bos.config.json:\", (err as Error).message);\n }\n}\n\nexport function readDeployResults(resultDir: string): DeployResultEntry[] {\n if (!existsSync(resultDir)) return [];\n const results: DeployResultEntry[] = [];\n for (const file of readdirSync(resultDir)) {\n if (!file.endsWith(\".json\")) continue;\n try {\n const content = JSON.parse(readFileSync(join(resultDir, file), \"utf8\")) as DeployResultEntry;\n results.push(content);\n } catch {\n // skip malformed files\n }\n }\n return results;\n}\n\nexport function readAllDeployResults(baseDir: string): DeployResultEntry[] {\n if (!existsSync(baseDir)) return [];\n const results: DeployResultEntry[] = [];\n for (const subdir of readdirSync(baseDir)) {\n const subdirPath = join(baseDir, subdir);\n try {\n const stat = readdirSync(subdirPath);\n for (const file of stat) {\n if (!file.endsWith(\".json\")) continue;\n try {\n const content = JSON.parse(\n readFileSync(join(subdirPath, file), \"utf8\"),\n ) as DeployResultEntry;\n results.push(content);\n } catch {\n // skip malformed files\n }\n }\n } catch {\n // not a directory, skip\n }\n }\n return results;\n}\n\nexport function applyDeployResults(\n config: Record<string, unknown>,\n results: DeployResultEntry[],\n): Record<string, unknown> {\n const merged = structuredClone(config);\n for (const result of results) {\n setNestedPath(merged, result.urlField, result.url);\n if (result.integrityField) {\n if (result.integrity) {\n setNestedPath(merged, result.integrityField, result.integrity);\n } else {\n deleteNestedPath(merged, result.integrityField);\n }\n }\n }\n return merged;\n}\n\nexport function cleanDeployResultDir(baseDir: string): void {\n if (existsSync(baseDir)) {\n rmSync(baseDir, { recursive: true, force: true });\n }\n mkdirSync(baseDir, { recursive: true });\n}\n\nexport function findPluginKey(bosConfigPath: string, pluginDir: string): string | null {\n const config = JSON.parse(readFileSync(bosConfigPath, \"utf8\")) as Record<string, unknown>;\n const plugins = config.plugins as Record<string, Record<string, unknown>> | undefined;\n if (!plugins) return null;\n const configRoot = join(bosConfigPath, \"..\");\n const normalizedPluginDir = pluginDir.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n for (const [key, plugin] of Object.entries(plugins)) {\n const dev = plugin?.development;\n if (typeof dev !== \"string\" || !dev.startsWith(\"local:\")) continue;\n const resolved = join(configRoot, dev.slice(\"local:\".length))\n .replace(/\\\\/g, \"/\")\n .replace(/\\/+$/, \"\");\n if (resolved === normalizedPluginDir) return key;\n }\n return null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"integrity.mjs","names":[],"sources":["../src/integrity.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { fetchBosConfigFromFastKv } from \"./fastkv\";\nimport { fetchResponse } from \"./http-client\";\n\nconst DEFAULT_MAX_SRI_RESPONSE_BYTES = 20 * 1024 * 1024;\n\ninterface SriUrlOptions {\n resolveEntryUrl?: boolean;\n maxBytes?: number;\n}\n\nexport function computeSriHash(content: string | Buffer): string {\n return `sha384-${createHash(\"sha384\").update(content).digest(\"base64\")}`;\n}\n\nfunction resolveSriTargetUrl(url: string, options?: SriUrlOptions): string {\n return options?.resolveEntryUrl === false ? url : resolveEntryUrl(url);\n}\n\nfunction getMaxSriResponseBytes(options?: SriUrlOptions): number {\n return options?.maxBytes ?? DEFAULT_MAX_SRI_RESPONSE_BYTES;\n}\n\nasync function computeSriHashFromResponse(\n response: Response,\n url: string,\n options?: SriUrlOptions,\n): Promise<string> {\n const maxBytes = getMaxSriResponseBytes(options);\n const contentLengthHeader = response.headers.get(\"content-length\");\n\n if (contentLengthHeader) {\n const contentLength = Number(contentLengthHeader);\n if (Number.isFinite(contentLength) && contentLength > maxBytes) {\n throw new Error(\n `[SRI] Response for ${url} exceeds max size of ${maxBytes} bytes (${contentLength})`,\n );\n }\n }\n\n if (!response.body) {\n throw new Error(`[SRI] Missing response body for ${url}`);\n }\n\n const hash = createHash(\"sha384\");\n const reader = response.body.getReader();\n let totalBytes = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n await reader.cancel();\n throw new Error(\n `[SRI] Response for ${url} exceeds max size of ${maxBytes} bytes (${totalBytes})`,\n );\n }\n\n hash.update(value);\n }\n\n return `sha384-${hash.digest(\"base64\")}`;\n}\n\nexport async function computeSriHashForUrl(\n url: string,\n options?: SriUrlOptions,\n): Promise<string | null> {\n try {\n const entryUrl = resolveSriTargetUrl(url, options);\n\n const response = await fetchResponse(entryUrl, { timeout: \"30 seconds\" });\n if (!response.ok) {\n console.warn(`[SRI] Failed to fetch ${entryUrl}: ${response.status} ${response.statusText}`);\n return null;\n }\n return await computeSriHashFromResponse(response, entryUrl, options);\n } catch (error) {\n console.warn(\n `[SRI] Error computing integrity for ${url}:`,\n error instanceof Error ? error.message : error,\n );\n return null;\n }\n}\n\nexport function resolveEntryUrl(url: string): string {\n if (url.endsWith(\"/remoteEntry.js\")) return url;\n if (url.endsWith(\"/mf-manifest.json\"))\n return `${url.replace(/\\/mf-manifest\\.json$/, \"\")}/remoteEntry.js`;\n return `${url.replace(/\\/$/, \"\")}/remoteEntry.js`;\n}\n\nexport async function verifySriForUrl(\n url: string,\n expectedIntegrity: string,\n options?: SriUrlOptions,\n): Promise<void> {\n const entryUrl = resolveSriTargetUrl(url, options);\n\n const response = await fetchResponse(entryUrl, { timeout: \"30 seconds\" });\n if (!response.ok) {\n console.warn(`[SRI] Failed to fetch ${entryUrl} for verification: ${response.status}`);\n return;\n }\n\n const computed = await computeSriHashFromResponse(response, entryUrl, options);\n\n if (computed !== expectedIntegrity) {\n throw new Error(\n `[SRI] Integrity check failed for ${entryUrl}\\n Expected: ${expectedIntegrity}\\n Computed: ${computed}`,\n );\n }\n}\n\nexport class IntegrityRegistry {\n private hashes = new Map<string, string>();\n\n register(url: string, integrity: string): void {\n this.hashes.set(url, integrity);\n }\n\n registerEntry(baseUrl: string, integrity: string): void {\n this.hashes.set(resolveEntryUrl(baseUrl), integrity);\n }\n\n get(url: string): string | undefined {\n return this.hashes.get(url);\n }\n\n has(url: string): boolean {\n return this.hashes.has(url);\n }\n\n entries(): IterableIterator<[string, string]> {\n return this.hashes.entries();\n }\n}\n\nfunction extractIntegrityHashes(config: Record<string, unknown>): Map<string, string> {\n const hashes = new Map<string, string>();\n const app = config.app as Record<string, Record<string, unknown>> | undefined;\n const plugins = config.plugins as Record<string, Record<string, unknown>> | undefined;\n\n if (app) {\n for (const [, entry] of Object.entries(app)) {\n if (entry?.integrity && entry?.production) {\n hashes.set(resolveEntryUrl(entry.production as string), entry.integrity as string);\n }\n }\n }\n\n if (plugins) {\n for (const [, entry] of Object.entries(plugins)) {\n if (entry?.integrity && entry?.production) {\n hashes.set(resolveEntryUrl(entry.production as string), entry.integrity as string);\n }\n }\n }\n\n return hashes;\n}\n\nexport async function verifyConfigAgainstChain(\n localConfig: Record<string, unknown>,\n bosUrl: string,\n): Promise<{ verified: boolean; mismatches: string[] }> {\n const mismatches: string[] = [];\n\n let chainConfig: Record<string, unknown>;\n try {\n chainConfig = await fetchBosConfigFromFastKv<Record<string, unknown>>(bosUrl);\n } catch (error) {\n console.warn(\n `[Attestation] Failed to fetch on-chain config: ${error instanceof Error ? error.message : String(error)}`,\n );\n return { verified: false, mismatches: [\"chain-fetch-failed\"] };\n }\n\n const localHashes = extractIntegrityHashes(localConfig);\n const chainHashes = extractIntegrityHashes(chainConfig);\n\n for (const [url, chainHash] of chainHashes) {\n const localHash = localHashes.get(url);\n if (localHash && localHash !== chainHash) {\n mismatches.push(url);\n console.error(\n `[Attestation] Integrity mismatch for ${url}\\n Local: ${localHash}\\n Chain: ${chainHash}`,\n );\n }\n }\n\n if (mismatches.length === 0 && localHashes.size > 0) {\n console.log(\n `[Attestation] Local config verified against on-chain anchor (${localHashes.size} entries checked)`,\n );\n }\n\n return { verified: mismatches.length === 0, mismatches };\n}\n\nexport interface DeployResultEntry {\n url: string;\n integrity?: string;\n urlField: string;\n integrityField?: string;\n}\n\nfunction setNestedPath(obj: Record<string, unknown>, dottedPath: string, value: unknown): void {\n const keys = dottedPath.split(\".\");\n let current = obj;\n for (let i = 0; i < keys.length - 1; i += 1) {\n const key = keys[i]!;\n if (current[key] === undefined || current[key] === null || typeof current[key] !== \"object\") {\n current[key] = {};\n }\n current = current[key] as Record<string, unknown>;\n }\n current[keys[keys.length - 1]!] = value;\n}\n\nfunction deleteNestedPath(obj: Record<string, unknown>, dottedPath: string): void {\n const keys = dottedPath.split(\".\");\n let current = obj;\n for (let i = 0; i < keys.length - 1; i += 1) {\n const key = keys[i]!;\n if (current[key] === undefined || typeof current[key] !== \"object\") return;\n current = current[key] as Record<string, unknown>;\n }\n delete current[keys[keys.length - 1]!];\n}\n\nexport function reportDeployResult(opts: {\n url: string;\n integrity?: string | null;\n bosConfigPath: string;\n urlField: string;\n integrityField?: string;\n}): void {\n console.log(\n `[BOS_DEPLOY] url=${opts.url} urlField=${opts.urlField} integrityField=${opts.integrityField ?? \"\"} integrity=${opts.integrity ?? \"\"}`,\n );\n\n try {\n const config = JSON.parse(readFileSync(opts.bosConfigPath, \"utf8\")) as Record<string, unknown>;\n setNestedPath(config, opts.urlField, opts.url);\n if (opts.integrityField) {\n if (opts.integrity) {\n setNestedPath(config, opts.integrityField, opts.integrity);\n } else {\n deleteNestedPath(config, opts.integrityField);\n }\n }\n writeFileSync(opts.bosConfigPath, `${JSON.stringify(config, null, 2)}\\n`);\n console.log(` ✅ Updated bos.config.json: ${opts.urlField}`);\n if (opts.integrityField && opts.integrity) {\n console.log(` ✅ Updated bos.config.json: ${opts.integrityField}`);\n }\n } catch (err) {\n console.error(\" ❌ Failed to update bos.config.json:\", (err as Error).message);\n }\n}\n\nexport function parseDeployLines(output: string): DeployResultEntry[] {\n const results: DeployResultEntry[] = [];\n for (const line of output.split(\"\\n\")) {\n if (!line.includes(\"[BOS_DEPLOY]\")) continue;\n const urlMatch = line.match(/url=(\\S+)/);\n const urlFieldMatch = line.match(/urlField=(\\S+)/);\n if (!urlMatch || !urlFieldMatch) continue;\n const integrityFieldMatch = line.match(/integrityField=(\\S+)/);\n const integrityMatch = line.match(/integrity=(\\S+)/);\n results.push({\n url: urlMatch[1],\n urlField: urlFieldMatch[1],\n integrityField: integrityFieldMatch?.[1] || undefined,\n integrity: integrityMatch?.[1] || undefined,\n });\n }\n return results;\n}\n\nexport function applyDeployResults(\n config: Record<string, unknown>,\n results: DeployResultEntry[],\n): Record<string, unknown> {\n const merged = structuredClone(config);\n for (const result of results) {\n setNestedPath(merged, result.urlField, result.url);\n if (result.integrityField) {\n if (result.integrity) {\n setNestedPath(merged, result.integrityField, result.integrity);\n } else {\n deleteNestedPath(merged, result.integrityField);\n }\n }\n }\n return merged;\n}\n\nexport function findPluginKey(bosConfigPath: string, pluginDir: string): string | null {\n const config = JSON.parse(readFileSync(bosConfigPath, \"utf8\")) as Record<string, unknown>;\n const plugins = config.plugins as Record<string, Record<string, unknown>> | undefined;\n if (!plugins) return null;\n const configRoot = join(bosConfigPath, \"..\");\n const normalizedPluginDir = pluginDir.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n for (const [key, plugin] of Object.entries(plugins)) {\n const dev = plugin?.development;\n if (typeof dev !== \"string\" || !dev.startsWith(\"local:\")) continue;\n const resolved = join(configRoot, dev.slice(\"local:\".length))\n .replace(/\\\\/g, \"/\")\n .replace(/\\/+$/, \"\");\n if (resolved === normalizedPluginDir) return key;\n }\n return null;\n}\n"],"mappings":"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"}
|