diff --git a/workspaces/ai-integrations/.changeset/kserve-connector-discovery-auth.md b/workspaces/ai-integrations/.changeset/kserve-connector-discovery-auth.md new file mode 100644 index 0000000000..a3fdec3050 --- /dev/null +++ b/workspaces/ai-integrations/.changeset/kserve-connector-discovery-auth.md @@ -0,0 +1,16 @@ +--- +'@red-hat-developer-hub/backstage-plugin-catalog-backend-module-model-catalog': minor +'@red-hat-developer-hub/backstage-plugin-catalog-techdoc-url-reader-backend': minor +'@red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend': patch +--- + +Integrate Backstage discovery and auth services for connector communication. + +The model-catalog entity provider now resolves the connector base URL via the +discovery service and authenticates with backend-to-backend service tokens +instead of unauthenticated direct HTTP calls. The `fromConfig` factory method +accepts `discovery` and `auth` as additional required dependencies. + +The techdoc URL reader adds bearer-token authentication when fetching model +cards and replaces hostname-based bridge URL matching with path-based matching +that uses the connector plugin ID. diff --git a/workspaces/ai-integrations/.prettierignore b/workspaces/ai-integrations/.prettierignore index 1cfaa89479..4f5a69b9d0 100644 --- a/workspaces/ai-integrations/.prettierignore +++ b/workspaces/ai-integrations/.prettierignore @@ -1,5 +1,6 @@ dist dist-types +dist-dynamic coverage .vscode .eslintrc.js diff --git a/workspaces/ai-integrations/app-config.yaml b/workspaces/ai-integrations/app-config.yaml index 22b302cccc..d2cd8cb3c7 100644 --- a/workspaces/ai-integrations/app-config.yaml +++ b/workspaces/ai-integrations/app-config.yaml @@ -77,7 +77,7 @@ integrations: techdocs: builder: 'local' # Alternatives - 'external' generator: - runIn: 'docker' # Alternatives - 'local' + runIn: 'local' # 'docker' # Alternatives - 'local' publisher: type: 'local' # Alternatives - 'googleGcs' or 'awsS3'. Read documentation for using alternatives. @@ -99,9 +99,11 @@ catalog: - allow: [Component, System, API, Resource, Location] providers: modelCatalog: - # The field underneath here can be any value that you feel represents your model catalog bridge instance - development: + # The field underneath should list the connector plugin ID that the entity provider accesses through + # the discovery service + kserve-kubeflow-connector: # `http://localhost:9090` works in both local testing and when the bridge is running as a sidecar # we'll hardcode for now and see about env vars later on once we officially take on running the bridge as # a separate pod - baseUrl: 'http://localhost:9090' + # baseUrl: 'http://localhost:9090' + name: my-k8s-cluster diff --git a/workspaces/ai-integrations/openspec/changes/transition-oai-connector-to-kserve-plugin/.openspec.yaml b/workspaces/ai-integrations/openspec/changes/transition-oai-connector-to-kserve-plugin/.openspec.yaml new file mode 100644 index 0000000000..6916718247 --- /dev/null +++ b/workspaces/ai-integrations/openspec/changes/transition-oai-connector-to-kserve-plugin/.openspec.yaml @@ -0,0 +1,3 @@ +schema: spec-driven +created: 2026-05-29 +status: draft diff --git a/workspaces/ai-integrations/openspec/changes/transition-oai-connector-to-kserve-plugin/design.md b/workspaces/ai-integrations/openspec/changes/transition-oai-connector-to-kserve-plugin/design.md new file mode 100644 index 0000000000..0eea3065ad --- /dev/null +++ b/workspaces/ai-integrations/openspec/changes/transition-oai-connector-to-kserve-plugin/design.md @@ -0,0 +1,117 @@ +## Context + +The existing OpenShift AI Connector uses a golang-based sidecar architecture: a K8s controller watches `InferenceService` resources, a `rhoai-normalizer` converts data to `ModelCatalog` JSON, a `storage-rest` sidecar serves it, and a `location` sidecar exposes discovery. The `catalog-backend-module-model-catalog` entity provider in RHDH polls the bridge sidecar's REST API to ingest entities. + +The RHDHPLAN-944 spike (RHIDP-11757) produced a working prototype on branch [`gabemontero/rhdh-plugins:kserve-kubeflow-connector`](https://github.com/gabemontero/rhdh-plugins/tree/kserve-kubeflow-connector) that replaces the golang sidecars with a TypeScript backend plugin (`kserve-kubeflow-connector-backend`) using `@kubernetes/client-node` Informers and REST clients. The prototype was demoed successfully against RHOAI. + +This design builds on that prototype. The primary remaining decisions are around entity type modeling (upstream alignment), credential configuration (move off env vars), model registry removal, and whether the result is a community plugin or downstream-only. + +### Stakeholders + +- **Gabe Montero** — Feature lead, prototype author +- **Ben Wilcock** — PM/reporter +- **COPE team** — Upstream Backstage engagement +- **RHOAI team** — KubeFlow Model Catalog API compatibility + +## Goals / Non-Goals + +**Goals:** + +- Standalone dynamic plugin with zero sidecar containers required +- Direct K8s Informer on KServe `InferenceService` resources (replacing golang controller) +- Direct REST client for KubeFlow Model Catalog APIs (replacing bridge sidecar) +- Entity type aligned with upstream Backstage API entity discriminated union (or compatible fallback) +- Credential configuration via Backstage K8s plugin config (not env vars) +- Compatible with generic KServe installations (not just RHOAI) +- Compatible with RHOAI 2.25+ for Model Catalog features +- Community Supported status (replacing Developer Preview) + +**Non-Goals:** + +- KubeFlow Model Registry integration (being removed, not replaced) +- Frontend UI changes (ai-experience plugin is a separate concern, being moved/removed) +- Merging catalog-techdoc-url-reader-backend into the connector plugin (deferred per Decision 6; prototype modified it but the current plugin-to-plugin approach is kept for initial release) +- Migration tooling for users on the current sidecar architecture +- Support for non-KServe model servers (SageMaker, Azure ML, etc.) +- MLFlow Model Registry integration + +## Decisions + +### Decision 1: Two-plugin architecture — connector + entity provider + +**Choice:** Keep the `kserve-kubeflow-connector-backend` plugin separate from `catalog-backend-module-model-catalog`. The connector plugin owns data acquisition (Informers, REST clients, in-memory state) and exposes REST endpoints. The entity provider module polls those endpoints to ingest catalog entities. + +**Rationale:** This matches the prototype's architecture and mirrors the existing sidecar separation of concerns — the connector replaces the sidecars, the entity provider remains the catalog integration point. It also allows the connector to be used independently of the Backstage catalog (e.g., for direct API consumption). + +**Alternative considered:** Merge everything into a single plugin. Rejected because it couples data acquisition lifecycle to entity provider scheduling, and makes it harder to test or reuse the connector independently. + +### Decision 2: K8s credential configuration via Backstage K8s plugin config + +**Choice:** Migrate from `K8S_TOKEN` / `KUBECONFIG` env vars to using Backstage's existing K8s plugin configuration (`kubernetes.clusterLocatorMethods` in `app-config.yaml`), following the pattern used by the [OCM plugin](https://github.com/backstage/community-plugins/tree/main/workspaces/ocm/plugins/ocm). + +**Rationale:** Env vars are a prototype shortcut. Backstage has a well-established K8s config pattern that supports multiple clusters, service account tokens, and OIDC. Using it means platform engineers don't need to learn a new config surface. It also positions the plugin better for upstream acceptance. + +**Alternative considered:** Custom plugin-specific config section. Rejected because it duplicates what Backstage already provides and would be a blocker for upstream acceptance. + +**Open question:** The prototype also uses `LIFECYCLE`, `OWNER`, and `POLLING_INTERVAL` env vars. These should move to `app-config.yaml` under `catalog.providers.modelCatalog` (extending the existing config schema), but the exact shape needs to be finalized. + +### Decision 3: Entity type — upstream API discriminated union, with catalog-model fallback + +**Choice:** First attempt to get `ai-model-server` accepted into the upstream Backstage API entity discriminated union (aligning with what merged for MCP servers). If upstream rejects this, fall back to using Backstage's catalog model layer to create a custom entity type whose schema matches the API discriminated union shape. + +**Rationale:** PM is aligned on this approach. The MCP server entity type precedent shows upstream is open to extending the API kind. Schema alignment in the fallback case means minimal code change if upstream acceptance comes later. + +**Impact on delivery:** The upstream path requires RFC/BEP engagement (external dependency, timeline measured in weeks/months). The fallback can be implemented immediately. Implementation should use an abstraction layer so the entity type source is swappable. + +**Alternative considered:** Use existing Component/Resource/API kinds (current approach). Rejected because it doesn't accurately represent what AI model servers are, and PM wants alignment with the upstream direction. + +### Decision 4: Remove KubeFlow Model Registry (KFMR) interaction + +**Choice:** Remove all KFMR client code (`Kfmr.ts`, related types, KFMR-specific label handling in `InformerService.ts`). The connector will only interact with: + +- KServe API (K8s Informer on `InferenceService` CRs) +- KubeFlow Model Catalog API (REST client for `CatalogSource`, `CatalogModel`/`ModelCard`) + +**Rationale:** KFMR is explicitly out of scope in RHDHPLAN-404. The prototype includes it because it was a direct golang conversion, but the feature definition calls for dropping it. This significantly reduces the connector's surface area (~837 lines in `Kfmr.ts` alone, plus cross-references in `InformerService.ts`). + +**Risk:** If RHOAI's KubeFlow Model Catalog API depends on KFMR data for model card resolution, we'll need to verify that the catalog API alone is sufficient. Validate against RHOAI 2.25+. + +### Decision 5: Community plugin vs. downstream-only + +**Choice:** Target community plugin in `backstage/community-plugins`, contingent on COPE approval. If COPE blocks, deliver as downstream RHDH dynamic plugin. + +**Rationale:** Community is a goal of RHDHPLAN-404 and broadens the user base. The community vs. downstream decision also affects K8s client usage (community plugins tend to use K8s SDK directly, downstream could use Backstage's K8s plugin). + +**Impact:** Community plugin path requires the upstream entity type decision (Decision 3) to be at least partially resolved — either accepted upstream, or the fallback approach must be demonstrably compatible. This gates the final packaging step but not the core implementation. + +### Decision 6: TechDocs / model card integration approach + +**Choice:** For the initial release, keep the prototype's approach of serving model cards via the connector's REST API. The prototype already modified `catalog-techdoc-url-reader-backend` to enable this plugin-to-plugin integration. Defer merging the techdoc reader into the connector (a TODO from the spike) to a follow-up. + +**Rationale:** The plugin-to-plugin REST call workaround works — the prototype demonstrated this with modifications to both `kserve-kubeflow-connector-backend` (serving model cards) and `catalog-techdoc-url-reader-backend` (consuming them). Merging the two is cleaner but shouldn't block the primary deliverable. If the plugin moves upstream, the upstream community may have opinions on the right pattern. + +## Risks / Trade-offs + +**Upstream entity type timeline is unbounded** → Implement the fallback (custom entity type via catalog model layer) first. Treat upstream acceptance as a future enhancement, not a blocker. The abstraction layer from Decision 3 makes switching cheap. + +**KFMR removal may break Model Catalog features on RHOAI** → Validate early against RHOAI 2.25+ that KubeFlow Model Catalog API works independently of Model Registry. If it doesn't, scope down to KServe-only for initial release and add KubeFlow Catalog support when the API is confirmed standalone. + +**K8s credential config migration may surface edge cases** → The OCM plugin is the reference implementation. If Backstage's K8s plugin config doesn't cover a specific RHOAI auth pattern (e.g., custom CA bundles for internal clusters), document it as a known limitation and address in a follow-up. + +**InformerService is 1400 lines of ported golang** → The prototype was Claude-assisted conversion. It works (demoed), but may contain patterns that don't fit TypeScript idioms. Plan for a refactoring pass during implementation, but don't let it block delivery. + +**Community plugin acceptance is not guaranteed** → COPE may require changes. Keep the plugin architecture clean enough that it can be packaged either way without major rework. + +## Migration Plan + +1. **No automatic migration** — users on the sidecar architecture must manually remove sidecar containers from their RHDH Deployment YAML and update `app-config.yaml` with the new plugin config +2. **Documentation** — rewrite the installation guide with a clear "migrating from sidecar connector" section +3. **Extensions Catalog** — replace the old entry; the old plugin name/package should not be reused to avoid confusion +4. **Rollback** — users can revert to the sidecar architecture by re-adding the sidecar containers and reverting config; the two approaches are independent + +## Open Questions + +1. **KubeFlow Model Catalog API independence** — Does the Catalog API on RHOAI 2.25+ work without Model Registry? Needs validation before KFMR removal is finalized. +2. **Exact `app-config.yaml` schema** — What does the config shape look like after merging K8s plugin config with model catalog provider config? Need to prototype and document. +3. **COPE approval timeline** — When can we get a decision on community plugin acceptance? This gates final packaging but not implementation. +4. **Upstream RFC/BEP status** — What's the state of the MCP server entity type decisions? Ben Lambert was to circle back — those decisions inform our AI Model Server proposal. diff --git a/workspaces/ai-integrations/openspec/changes/transition-oai-connector-to-kserve-plugin/proposal.md b/workspaces/ai-integrations/openspec/changes/transition-oai-connector-to-kserve-plugin/proposal.md new file mode 100644 index 0000000000..7e042e8f5a --- /dev/null +++ b/workspaces/ai-integrations/openspec/changes/transition-oai-connector-to-kserve-plugin/proposal.md @@ -0,0 +1,61 @@ +## Why + +The current OpenShift AI Connector for RHDH requires three sidecar containers (`location`, `storage-rest`, `rhoai-normalizer`) patched into the RHDH Deployment YAML, making it heavy and difficult to install via Helm Chart or Operator. This friction has limited adoption — no RHDH customers have approached us for POCs or deployment of the current Developer Preview. The connector also only works with RHOAI, excluding users of generic KServe or Kubeflow installations. + +Refactoring to a standalone dynamic plugin that talks directly to KServe/KubeFlow APIs eliminates the sidecar requirement, broadens compatibility to any KServe-compatible platform, and positions the plugin for upstream Backstage community donation. The 1.10 development spike (RHDHPLAN-944) is complete, and PM alignment exists on the entity modeling approach — now is the time to execute. + +## Starting Point + +The spike (RHIDP-11757) produced a working prototype on branch [`gabemontero/rhdh-plugins:kserve-kubeflow-connector`](https://github.com/gabemontero/rhdh-plugins/tree/kserve-kubeflow-connector) that serves as the starting point for this work. The prototype includes: + +- A new `kserve-kubeflow-connector-backend` plugin with: + - K8s TypeScript Informer on KServe `InferenceService` resources (`InformerService.ts`) + - KServe inference service → ModelCatalog conversion (`KServe.ts`) + - KubeFlow Model Registry client with REST calls (`Kfmr.ts`) + - Full type definitions ported from the golang connector (`types.ts`) +- Modifications to the existing `catalog-backend-module-model-catalog` entity provider and config +- Modifications to `catalog-techdoc-url-reader-backend` for plugin-to-plugin TechDocs/model card integration + +Known TODOs from the prototype (per RHIDP-11757 comments): + +- Additional unit tests for the converted golang→typescript code +- TechDocs/model card integration workarounds (plugin-to-plugin REST calls should be merged into the connector plugin) +- K8s credential config currently uses env vars (`KUBECONFIG`, `K8S_TOKEN`); needs to migrate to Backstage K8s plugin config pattern (like OCM plugin) +- Model registry interaction to be removed per feature scope + +## What Changes + +- **Remove sidecar dependency**: Replace the golang-based controller + bridge architecture with a TypeScript backend plugin using K8s TypeScript Informers for KServe and REST clients for KubeFlow +- **New entity type modeling**: Attempt to add `ai-model-server` to the upstream Backstage API entity discriminated union; fallback to using the catalog model layer to create a new entity type whose schema aligns with the recently merged MCP server API entity extension +- **Remove model registry interaction**: Drop KubeFlow Model Registry integration (out of scope per feature definition) +- **Reduce entity surface**: Move from Component/Resource/traditional API entities to the new API/remotes type from upstream Backstage +- **Finalize credential configuration**: Use the existing Backstage K8s plugin config and/or new plugin config for core K8s credentials and KubeFlow Model Catalog connection/credentials +- **Update documentation**: Rewrite installation guide to remove sidecar instructions, add KServe/KubeFlow configuration section +- **Update Extensions Catalog**: Replace old OpenShift AI Connector entry with new KServe/KubeFlow Connector listing +- **Transition support status**: Move from "Developer Preview" to "Community Supported" +- **New blog post**: Communicate the simplified plugin-only approach vs. the previous sidecar-based setup + +## Capabilities + +### New Capabilities + +- `kserve-inference-service-informer`: TypeScript K8s Informer-based discovery of KServe InferenceService resources, replacing the golang controller sidecar +- `kubeflow-model-catalog-client`: REST client integration with KubeFlow Model Catalog APIs (CatalogSource, CatalogModel/ModelCard) +- `ai-model-server-entity-type`: New Backstage catalog entity type for AI Model Servers, schema-aligned with the upstream API entity discriminated union (or fallback custom entity type) + +### Modified Capabilities + +- `model-catalog-entity-provider`: Existing `ModelCatalogResourceEntityProvider` refactored to use direct K8s/KServe APIs instead of bridge sidecar; entity output changes from Component/Resource/API to new API/remotes type +- `plugin-configuration`: Configuration schema changes — sidecar-related config removed, KServe endpoint and K8s credential config added + +## Out of Scope + +- `workspaces/ai-integrations/plugins/ai-experience/`, `ai-experience-backend/`, `ai-experience-common/`: The ai-experience component is a separate concern that is being moved and/or removed — not part of this refactor + +## Impact + +- `workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/`: Major refactor — `BridgeResourceConnector` replaced with direct KServe/KubeFlow clients, `ModelCatalogGenerator` updated for new entity types, `ModelCatalogResourceEntityProvider` rewritten +- Upstream Backstage: RFC/BEP for AI Model Server entity mapping (external dependency) +- RHDH Extensions Catalog: Entry replacement (old connector removed, new KServe/KubeFlow connector added) +- Documentation: Full rewrite of installation/configuration chapter +- Sizing: 17 PD code, 8 PD docs/blog diff --git a/workspaces/ai-integrations/package.json b/workspaces/ai-integrations/package.json index c1278cd9f8..e493bf97fd 100644 --- a/workspaces/ai-integrations/package.json +++ b/workspaces/ai-integrations/package.json @@ -13,7 +13,7 @@ "tsc": "tsc", "tsc:full": "tsc --skipLibCheck true --incremental false", "build:all": "backstage-cli repo build --all", - "build:api-reports": "yarn build:api-reports:only --tsc", + "build:api-reports": "yarn tsc:full && yarn build:api-reports:only", "build:api-reports:only": "backstage-repo-tools api-reports -o ae-wrong-input-file-type,ae-undocumented --validate-release-tags", "build:knip-reports": "backstage-repo-tools knip-reports", "clean": "backstage-cli repo clean", diff --git a/workspaces/ai-integrations/packages/backend/package.json b/workspaces/ai-integrations/packages/backend/package.json index 92838609c0..c8297cda1a 100644 --- a/workspaces/ai-integrations/packages/backend/package.json +++ b/workspaces/ai-integrations/packages/backend/package.json @@ -50,6 +50,7 @@ "@red-hat-developer-hub/backstage-plugin-catalog-backend-module-catalog-backend-module-ai-resource-extensions": "workspace:^", "@red-hat-developer-hub/backstage-plugin-catalog-backend-module-model-catalog": "workspace:^", "@red-hat-developer-hub/backstage-plugin-catalog-techdoc-url-reader-backend": "workspace:^", + "@red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend": "workspace:^", "app": "link:../app", "better-sqlite3": "^12.0.0", "node-gyp": "^10.0.0", diff --git a/workspaces/ai-integrations/packages/backend/src/index.ts b/workspaces/ai-integrations/packages/backend/src/index.ts index 940dbf1616..3e8bbbd0cb 100644 --- a/workspaces/ai-integrations/packages/backend/src/index.ts +++ b/workspaces/ai-integrations/packages/backend/src/index.ts @@ -82,4 +82,9 @@ backend.add( '@red-hat-developer-hub/backstage-plugin-catalog-backend-module-catalog-backend-module-ai-resource-extensions' ), ); +backend.add( + import( + '@red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend' + ), +); backend.start(); diff --git a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/config.d.ts b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/config.d.ts index cb03585db9..88272996c1 100644 --- a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/config.d.ts +++ b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/config.d.ts @@ -23,8 +23,7 @@ export interface Config { /** * ModelCatalogConfig */ - baseUrl: string; - name?: string; + baseUrl?: string; system?: string; owner?: string; schedule?: SchedulerServiceTaskScheduleDefinitionConfig; diff --git a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/report.api.md b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/report.api.md index d5cb822b32..b9ab651b4b 100644 --- a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/report.api.md +++ b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/report.api.md @@ -14,10 +14,18 @@ export default catalogModuleModelCatalogResourceEntityProvider; export function fetchModelCatalogFromKey( baseUrl: string, modelCatalogKey: string, + token?: { + token: string; + }, ): Promise; // @public -export function fetchModelCatalogKeys(baseUrl: string): Promise; +export function fetchModelCatalogKeys( + baseUrl: string, + token: { + token: string; + }, +): Promise; // @public export interface ModelCatalogKeys { diff --git a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/BridgeResourceConnector.test.ts b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/BridgeResourceConnector.test.ts index fb26cb158f..39ee89a862 100644 --- a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/BridgeResourceConnector.test.ts +++ b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/BridgeResourceConnector.test.ts @@ -44,7 +44,7 @@ global.fetch = jest.fn(url => { status: 401, json: () => 'error', }); - } else if (url === 'fake-url/example-model') { + } else if (url === 'fake-url/models/example-model') { return Promise.resolve({ ok: true, status: 200, @@ -70,7 +70,9 @@ describe('fetchModelCatalogKeys', () => { streamStream.emit('data', 'test'); streamStream.emit('end'); }); - const catalogKeys: string[] = await fetchModelCatalogKeys('fake-url'); + const catalogKeys: string[] = await fetchModelCatalogKeys('fake-url', { + token: 'fake-token', + }); expect(catalogKeys.length).toEqual(3); expect(catalogKeys).toEqual(['example-model', 'model-two', 'model-three']); }); @@ -82,7 +84,8 @@ describe('fetchModelCatalogKeys', () => { streamStream.emit('end'); }); await expect( - async () => await fetchModelCatalogKeys('errorTest'), + async () => + await fetchModelCatalogKeys('errorTest', { token: 'fake-token' }), ).rejects.toThrow(); }); }); @@ -97,7 +100,7 @@ describe('fetchModelCatalogFromKey', () => { }); const catalog: ModelCatalog = await fetchModelCatalogFromKey( 'fake-url', - '/example-model', + 'example-model', ); expect(catalog.models === undefined).toBe(false); expect(catalog.models.length).toEqual(1); @@ -111,7 +114,8 @@ describe('fetchModelCatalogFromKey', () => { streamStream.emit('end'); }); await expect( - async () => await fetchModelCatalogKeys('errorTest'), + async () => + await fetchModelCatalogKeys('errorTest', { token: 'fake-token' }), ).rejects.toThrow(); }); }); diff --git a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/BridgeResourceConnector.ts b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/BridgeResourceConnector.ts index dcb15913d9..a69c08c002 100644 --- a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/BridgeResourceConnector.ts +++ b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/BridgeResourceConnector.ts @@ -29,10 +29,14 @@ export interface ModelCatalogKeys { */ export async function fetchModelCatalogKeys( baseUrl: string, + token: { token: string }, ): Promise { - // ToDo: Discover catalog-info endpoint? const res = await fetch(`${baseUrl}/list`, { method: 'GET', + headers: { + Authorization: `Bearer ${token.token}`, + 'Content-Type': 'application/json', + }, }); if (!res.ok) { @@ -50,9 +54,20 @@ export async function fetchModelCatalogKeys( export async function fetchModelCatalogFromKey( baseUrl: string, modelCatalogKey: string, + token?: { token: string }, ): Promise { - const res = await fetch(`${baseUrl}${modelCatalogKey}`, { + let tok = ''; + if (token) { + tok = token?.token; + } + const url = `${baseUrl}/models/${modelCatalogKey}`; + console.log(`Fetching model catalog key ${url}`); + const res = await fetch(url, { method: 'GET', + headers: { + Authorization: `Bearer ${tok}`, + 'Content-Type': 'application/json', + }, }); if (!res.ok) { diff --git a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/ModelCatalogGenerator.ts b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/ModelCatalogGenerator.ts index b2f8a33797..71d19c70f6 100644 --- a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/ModelCatalogGenerator.ts +++ b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/ModelCatalogGenerator.ts @@ -46,13 +46,19 @@ export function ParseCatalogJSON(jsonStr: string): ModelCatalog { // An optional logger parameter can be passed if you wish log output from the generator export function GenerateCatalogEntities( modelCatalog: ModelCatalog, + svcUrl?: string, logger?: LoggerService, ): Entity[] { // Generate the Resource entities for the Model(s) let modelCatalogEntities: Entity[] = []; const models: Model[] = modelCatalog.models; modelCatalogEntities = modelCatalogEntities.concat( - GenerateModelResourceEntities(models, modelCatalog.modelServer, logger), + GenerateModelResourceEntities( + models, + modelCatalog.modelServer, + logger, + svcUrl, + ), ); // Generate the Model Server and Model Server APi entity, if present @@ -82,6 +88,7 @@ export function GenerateModelResourceEntities( models: Model[], modelServer?: ModelServer, logger?: LoggerService, + svcUrl?: string, ): ResourceEntity[] { const modelResourceEntities: ResourceEntity[] = []; models.forEach(model => { @@ -142,7 +149,11 @@ export function GenerateModelResourceEntities( if (key === 'TechDocs') { let techdocsUrl: string = model.annotations![key]; techdocsUrl = techdocsUrl.trim(); + // TODO GGM prepend svc URL if (techdocsUrl !== '') { + if (svcUrl !== undefined) { + techdocsUrl = svcUrl + techdocsUrl; + } modelResourceEntity.metadata.annotations![ 'backstage.io/techdocs-ref' ] = `url:${techdocsUrl}`; diff --git a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/module.ts b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/module.ts index 8f88583bbb..b507555f9d 100644 --- a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/module.ts +++ b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/module.ts @@ -35,13 +35,15 @@ export const catalogModuleModelCatalogResourceEntityProvider = deps: { catalog: catalogProcessingExtensionPoint, config: coreServices.rootConfig, + discovery: coreServices.discovery, + auth: coreServices.auth, logger: coreServices.logger, scheduler: coreServices.scheduler, }, - async init({ catalog, config, logger, scheduler }) { - catalog.addEntityProvider( - ModelCatalogResourceEntityProvider.fromConfig( - { config, logger }, + async init({ catalog, config, discovery, auth, logger, scheduler }) { + try { + const ep = ModelCatalogResourceEntityProvider.fromConfig( + { config, logger, discovery, auth }, { schedule: scheduler.createScheduledTaskRunner({ frequency: { seconds: 30 }, @@ -49,8 +51,12 @@ export const catalogModuleModelCatalogResourceEntityProvider = }), scheduler: scheduler, }, - ), - ); + ); + catalog.addEntityProvider(ep); + } catch (error) { + console.error(error); + throw error; + } }, }); }, diff --git a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/ModelCatalogResourceEntityProvider.test.ts b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/ModelCatalogResourceEntityProvider.test.ts index cbef39ec57..85551ca3e6 100644 --- a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/ModelCatalogResourceEntityProvider.test.ts +++ b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/ModelCatalogResourceEntityProvider.test.ts @@ -96,6 +96,8 @@ describe('ModelCatalogResourceEntityProvider', () => { { config: mockServices.rootConfig({ data: CONFIG }), logger: mockServices.logger.mock(), + discovery: mockServices.discovery.mock(), + auth: mockServices.auth.mock(), }, { schedule, @@ -125,6 +127,15 @@ describe('ModelCatalogResourceEntityProvider', () => { { config: mockServices.rootConfig({ data: CONFIG }), logger: mockServices.logger.mock(), + discovery: mockServices.discovery.mock({ + getBaseUrl: jest.fn().mockResolvedValue('http://localhost:9090'), + }), + auth: mockServices.auth.mock({ + getOwnServiceCredentials: jest.fn().mockResolvedValue({}), + getPluginRequestToken: jest + .fn() + .mockResolvedValue({ token: 'mock-token' }), + }), }, { schedule, @@ -149,6 +160,15 @@ describe('ModelCatalogResourceEntityProvider', () => { { config: mockServices.rootConfig({ data: CONFIG }), logger: mockServices.logger.mock(), + discovery: mockServices.discovery.mock({ + getBaseUrl: jest.fn().mockResolvedValue('http://localhost:9090'), + }), + auth: mockServices.auth.mock({ + getOwnServiceCredentials: jest.fn().mockResolvedValue({}), + getPluginRequestToken: jest + .fn() + .mockResolvedValue({ token: 'mock-token' }), + }), }, { schedule, diff --git a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/ModelCatalogResourceEntityProvider.ts b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/ModelCatalogResourceEntityProvider.ts index e1ccc1468f..ee7d33e487 100644 --- a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/ModelCatalogResourceEntityProvider.ts +++ b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/ModelCatalogResourceEntityProvider.ts @@ -14,6 +14,8 @@ * limitations under the License. */ import type { + AuthService, + DiscoveryService, LoggerService, SchedulerService, SchedulerServiceTaskRunner, @@ -25,7 +27,6 @@ import { import { ANNOTATION_LOCATION, ANNOTATION_ORIGIN_LOCATION, - Entity, } from '@backstage/catalog-model'; import { @@ -43,9 +44,11 @@ import { GenerateCatalogEntities } from '../clients/ModelCatalogGenerator'; * @public */ export class ModelCatalogResourceEntityProvider implements EntityProvider { - private readonly env: string; + private readonly name: string; private readonly baseUrl: string; private readonly logger: LoggerService; + private readonly discovery: DiscoveryService; + private readonly auth: AuthService; private readonly scheduleFn: () => Promise; private connection?: EntityProviderConnection; @@ -57,12 +60,14 @@ export class ModelCatalogResourceEntityProvider implements EntityProvider { deps: { config: Config; logger: LoggerService; + discovery: DiscoveryService; + auth: AuthService; }, options: | { schedule: SchedulerServiceTaskRunner } | { scheduler: SchedulerService }, ): ModelCatalogResourceEntityProvider[] { - const { config, logger } = deps; + const { config, logger, discovery, auth } = deps; const providerConfigs = readModelCatalogApiEntityConfigs(config); @@ -83,6 +88,8 @@ export class ModelCatalogResourceEntityProvider implements EntityProvider { return new ModelCatalogResourceEntityProvider( providerConfig, logger, + discovery, + auth, taskRunner, ); }); @@ -91,10 +98,14 @@ export class ModelCatalogResourceEntityProvider implements EntityProvider { private constructor( config: ModelCatalogConfig, logger: LoggerService, + discovery: DiscoveryService, + auth: AuthService, taskRunner: SchedulerServiceTaskRunner, ) { - this.env = config.id; + this.name = config.id; this.baseUrl = config.baseUrl; + this.discovery = discovery; + this.auth = auth; this.logger = logger.child({ target: this.getProviderName(), }); @@ -116,7 +127,7 @@ export class ModelCatalogResourceEntityProvider implements EntityProvider { if (isError(error)) { // Ensure that we don't log any sensitive internal data: this.logger.error( - `Error while syncing resources from Model Catalog ${this.baseUrl}`, + `Error while syncing resources from Model Catalog ${this.name}`, { // Default Error properties: name: error.name, @@ -135,7 +146,7 @@ export class ModelCatalogResourceEntityProvider implements EntityProvider { /** [2]: Model Catalog entity provider must have a unique name */ getProviderName(): string { - return `ModelCatalogResourceEntityProvider:${this.env}`; + return `ModelCatalogResourceEntityProvider:${this.name}`; } /** [3]: Connect Backstage catalog engine to ModelCatalogEntityProvider */ @@ -150,26 +161,40 @@ export class ModelCatalogResourceEntityProvider implements EntityProvider { throw new Error('Not initialized'); } this.logger.info( - `Discovering ResourceEntities from Model Server ${this.baseUrl}`, + `Discovering ResourceEntities from Model Server ${this.name}`, ); /** [5]: Fetch the model catalog keys from the bridge and fetch the corresponding catalog entries. */ - let catalogKeys = await fetchModelCatalogKeys(this.baseUrl); + // the api docs for this method says to run it each time vs. once during init, as the URL can change + const svcUrl = await this.discovery.getBaseUrl(this.name); + let url = this.baseUrl; + if (svcUrl.length > 0 && url.length === 0) { + url = svcUrl; + } + const backendToken = await this.auth.getPluginRequestToken({ + onBehalfOf: await this.auth.getOwnServiceCredentials(), + targetPluginId: this.name, + }); + let catalogKeys = await fetchModelCatalogKeys(url, backendToken); // If no models are registered yet, the catalogKeys array may be null, so handle it by setting it to be an emptyList if (catalogKeys === null || catalogKeys === undefined) { catalogKeys = []; } - let entityList: Entity[] = []; this.logger.debug(`Found ${catalogKeys.length} model catalogs`); this.logger.debug(`Fetched ModelCatalog: ${JSON.stringify(catalogKeys)}`); - await Promise.all( - catalogKeys.map(async key => { - const catalog = await fetchModelCatalogFromKey(this.baseUrl, key); - const catalogEntities = GenerateCatalogEntities(catalog); - entityList = entityList.concat(catalogEntities); - }), - ); + const entityList = ( + await Promise.all( + catalogKeys.map(async key => { + const catalog = await fetchModelCatalogFromKey( + url, + key, + backendToken, + ); + return GenerateCatalogEntities(catalog, url); + }), + ) + ).flat(); entityList.forEach(entity => { if (entity.metadata.annotations === undefined) { diff --git a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/config.ts b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/config.ts index 33641a4d1a..4c3aede450 100644 --- a/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/config.ts +++ b/workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/config.ts @@ -43,7 +43,10 @@ function readModelCatalogApiEntityConfig( id: string, config: Config, ): ModelCatalogConfig { - const baseUrl = config.getString('baseUrl'); + let baseUrl = ''; + if (config.has('baseUrl')) { + baseUrl = config.getString('baseUrl'); + } const schedule = config.has('schedule') ? readSchedulerServiceTaskScheduleDefinitionFromConfig( diff --git a/workspaces/ai-integrations/plugins/catalog-techdoc-url-reader-backend/src/plugin.test.ts b/workspaces/ai-integrations/plugins/catalog-techdoc-url-reader-backend/src/plugin.test.ts index 3f5dd7669e..7470918cbb 100644 --- a/workspaces/ai-integrations/plugins/catalog-techdoc-url-reader-backend/src/plugin.test.ts +++ b/workspaces/ai-integrations/plugins/catalog-techdoc-url-reader-backend/src/plugin.test.ts @@ -136,7 +136,15 @@ describe('ModeCatalogBridgeTechdocUrlReader', () => { describe('bridgePredicate', () => { it('should match default localhost URL', () => { - const reader = newReader({}); + const reader = newReader({ + catalog: { + providers: { + modelCatalog: { + test: {}, + }, + }, + }, + }); expect( reader.bridgePredicate( new URL('https://localhost:9090/modelcard/test'), diff --git a/workspaces/ai-integrations/plugins/catalog-techdoc-url-reader-backend/src/plugin.ts b/workspaces/ai-integrations/plugins/catalog-techdoc-url-reader-backend/src/plugin.ts index 276b3b3830..532bdd8f23 100644 --- a/workspaces/ai-integrations/plugins/catalog-techdoc-url-reader-backend/src/plugin.ts +++ b/workspaces/ai-integrations/plugins/catalog-techdoc-url-reader-backend/src/plugin.ts @@ -32,6 +32,8 @@ import { UrlReaderServiceReadTreeResponseFile, UrlReaderServiceReadTreeResponseDirOptions, LoggerService, + DiscoveryService, + AuthService, } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; @@ -101,7 +103,10 @@ export function readBridgeConfigs(config: Config): BridgeConfig[] { } export function readBridgeConfig(id: string, config: Config): BridgeConfig { - const url = config.getString('baseUrl'); + let url = ''; + if (config.has('baseUrl')) { + url = config.getString('baseUrl'); + } return { id, baseUrl: url }; } @@ -110,6 +115,13 @@ export class ModeCatalogBridgeTechdocUrlReader implements UrlReaderService { private readonly logger: LoggerService; private readonly bridgeConfigs: BridgeConfig[]; + // TODO we are limited in which core services can be passed into the ReaderFactory, so as a work around we + // define these globals that are set in the plugin init method; if we merge this plugin with the + // kserve-kubeflow-connector plugins, and bypass the need for plugin to plug REST calls, we can + // bypass the need for the discover and auth services. + static discovery: DiscoveryService; + static auth: AuthService; + static factory: ReaderFactory = ({ config, logger }) => { const reader = new ModeCatalogBridgeTechdocUrlReader(config, logger); const predicate = (url: URL) => reader.bridgePredicate(url); @@ -133,22 +145,10 @@ export class ModeCatalogBridgeTechdocUrlReader implements UrlReaderService { bridgePredicate = (url: URL): boolean => { for (let index = 0; index < this.bridgeConfigs.length; index++) { const bc = this.bridgeConfigs[index]; - const bcUrl = new URL(bc.baseUrl); - if ( - url.hostname === bcUrl.hostname && - url.port === bcUrl.port && - url.pathname.startsWith('/modelcard') - ) { + if (url.pathname.includes('modelcard') && url.pathname.includes(bc.id)) { return true; } } - if ( - url.hostname === 'localhost' && - url.port === '9090' && - url.pathname.startsWith('/modelcard') - ) { - return true; - } return false; }; @@ -159,7 +159,30 @@ export class ModeCatalogBridgeTechdocUrlReader implements UrlReaderService { this.logger.info(`ModelCatalogBridgeTechdocUrlReader.readUrl of ${url}`); let response: Response; try { + // TODO so the token obtained here looks like a toke, but it still got + // 401 / unauthorized when trying to access the router REST endpoints + // of the kserve-kubeflow-connector; hence, are using of the static + // admin token 'RHDH_TOKEN' that immediately follows; *IF* we determin + // that the model card integration works with the upstream version + // of kubeflow model catalog/registry, we'll need to dive into possible + // alternatives to this work around. Possibly merging the techdoc + // reader extension into the kserve-kubeflow-connector and byppassing + // the need for the plugin to plugin REST call might be required here. + const token = + await ModeCatalogBridgeTechdocUrlReader.auth.getPluginRequestToken({ + onBehalfOf: + await ModeCatalogBridgeTechdocUrlReader.auth.getOwnServiceCredentials(), + targetPluginId: urlReaderFactoriesServiceRef.id, + }); + let tok = token.token; + if (process.env.RHDH_TOKEN && process.env.RHDH_TOKEN.length > 0) { + tok = process.env.RHDH_TOKEN; + } response = await fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${tok}`, + }, signal: options?.signal as any, }); } catch (e) { @@ -258,12 +281,17 @@ export const catalogTechdocUrlReaderPlugin = createServiceFactory({ service: urlReaderFactoriesServiceRef, deps: { logger: coreServices.logger, + discovery: coreServices.discovery, + auth: coreServices.auth, }, - async factory({ logger }) { + async factory({ logger, discovery, auth }) { logger .child({ source: 'catalogTechdocUrlReaderPlugin"' }) .info('Registering the model catalog bridge URL reader '); + ModeCatalogBridgeTechdocUrlReader.discovery = discovery; + ModeCatalogBridgeTechdocUrlReader.auth = auth; + return ModeCatalogBridgeTechdocUrlReader.factory; }, }); diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/.eslintrc.js b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/.eslintrc.js new file mode 100644 index 0000000000..9184408ae4 --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/.eslintrc.js @@ -0,0 +1,16 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/README.md b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/README.md new file mode 100644 index 0000000000..25221f3ef4 --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/README.md @@ -0,0 +1,32 @@ +# kserve-kubeflow-connector + +This plugin backend was templated using the Backstage CLI. You should replace this text with a description of your plugin backend. + +## Installation + +This plugin is installed via the `@red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend` package. To install it to your backend package, run the following command: + +```bash +# From your root directory +yarn --cwd packages/backend add @red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend +``` + +Then add the plugin to your backend in `packages/backend/src/index.ts`: + +```ts +const backend = createBackend(); +// ... +backend.add( + import( + '@red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend' + ), +); +``` + +## Development + +This plugin backend can be started in a standalone mode from directly in this +package with `yarn start`. It is a limited setup that is most convenient when +developing the plugin backend itself. + +If you want to run the entire project, including the frontend, run `yarn start` from the root directory. diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/dev/index.ts b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/dev/index.ts new file mode 100644 index 0000000000..304463576d --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/dev/index.ts @@ -0,0 +1,26 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createBackend } from '@backstage/backend-defaults'; +import { mockServices } from '@backstage/backend-test-utils'; + +const backend = createBackend(); + +backend.add(mockServices.auth.factory()); +backend.add(mockServices.httpAuth.factory()); + +backend.add(import('../src')); + +backend.start(); diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/package.json b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/package.json new file mode 100644 index 0000000000..a289f54093 --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/package.json @@ -0,0 +1,58 @@ +{ + "name": "@red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend", + "version": "0.1.0", + "license": "Apache-2.0", + "private": true, + "main": "src/index.ts", + "types": "src/index.ts", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "repository": { + "type": "git", + "url": "https://github.com/redhat-developer/rhdh-plugins", + "directory": "workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend" + }, + "backstage": { + "role": "backend-plugin", + "pluginId": "kserve-kubeflow-connector", + "pluginPackage": "@backstage/plugin-backend", + "pluginPackages": [ + "@red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend" + ] + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-defaults": "^0.13.1", + "@backstage/backend-plugin-api": "^1.5.0", + "@backstage/catalog-client": "^1.9.1", + "@backstage/errors": "^1.2.7", + "@backstage/plugin-catalog-node": "^1.20.0", + "@backstage/types": "^1.2.2", + "@kubernetes/client-node": "^0.20.0", + "express": "^4.17.1", + "express-promise-router": "^4.1.0", + "undici": "^6.19.0", + "zod": "^3.22.4" + }, + "devDependencies": { + "@backstage/backend-test-utils": "^1.10.0", + "@backstage/cli": "^0.34.5", + "@types/express": "^4.17.6", + "@types/supertest": "^2.0.12", + "supertest": "^6.2.4" + }, + "files": [ + "dist" + ] +} diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/report.api.md b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/report.api.md new file mode 100644 index 0000000000..637c6a62d3 --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @public +const kserveKubeflowConnectorPlugin: BackendFeature; +export default kserveKubeflowConnectorPlugin; + +// (No @packageDocumentation comment for this package) +``` diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/index.ts b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/index.ts new file mode 100644 index 0000000000..cfe2efe1b0 --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { kserveKubeflowConnectorPlugin as default } from './plugin'; diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/plugin.ts b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/plugin.ts new file mode 100644 index 0000000000..ed3b18abb9 --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/plugin.ts @@ -0,0 +1,45 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './router'; +import { setupInformer } from './services/InformerService'; + +/** + * kserveKubeflowConnectorPlugin backend plugin + * + * @public + */ +export const kserveKubeflowConnectorPlugin = createBackendPlugin({ + pluginId: 'kserve-kubeflow-connector', + register(env) { + env.registerInit({ + deps: { + httpAuth: coreServices.httpAuth, + httpRouter: coreServices.httpRouter, + logger: coreServices.logger, + }, + async init({ logger, httpRouter }) { + setupInformer().catch(error => { + logger.error('Failed to set up informer:', error); + }); + httpRouter.use(await createRouter()); + }, + }); + }, +}); diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/router.ts b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/router.ts new file mode 100644 index 0000000000..dd90c02a21 --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/router.ts @@ -0,0 +1,84 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// import { InputError } from '@backstage/errors'; +// import { z } from 'zod'; +import express from 'express'; +import Router from 'express-promise-router'; +// import { todoListServiceRef } from './services/TodoListService'; +import { + getDiscoveryUris, + getModelCatalog, + getModelCard, +} from './services/InformerService'; + +export async function createRouter(): Promise { + const router = Router(); + router.use(express.json()); + + // router.use('/', async (req, res, next) => { + // console.log(`${req.method} ${req.originalUrl}`); + // if ('/foo'.includes(req.path)) { + // res.status(200); + // } else { + // return next(); + // } + // }); + + // List all model catalog URIs (matching Go handleCatalogDiscoveryGet, server.go lines 162-182) + router.get('/list', async (_req, res) => { + try { + const discoveryResponse = getDiscoveryUris(); + res.status(200).json(discoveryResponse); + } catch (error) { + console.error('Error getting discovery URIs:', error); + res.status(500).json({ error: 'Internal server error' }); + } + }); + + router.get('/modelcard/:sourceId/:modelName', async (req, res) => { + try { + const sourceId = req.params.sourceId; + const modelName = req.params.modelName; + const modelCard = getModelCard(`${sourceId}/${modelName}`); + if (modelCard) { + res.setHeader('Content-Type', 'text/markdown'); + res.status(200).send(modelCard); + } else { + res.status(404).json({ error: 'Not Found' }); + } + } catch (error) { + console.error('Error getting model card:', error); + res.status(500).json({ error: 'Internal server error' }); + } + }); + + router.get('/models/:model/:version', async (req, res) => { + try { + const key = `${req.params.model}/${req.params.version}`; + const modelCatalog = getModelCatalog(key); + if (modelCatalog) { + res.status(200).json(modelCatalog); + } else { + res.status(404).json({ error: 'Not Found' }); + } + } catch (error) { + console.error('Error getting model catalog:', error); + res.status(500).json({ error: 'Internal server error' }); + } + }); + + return router; +} diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/InformerService.ts b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/InformerService.ts new file mode 100644 index 0000000000..d8c5ce0364 --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/InformerService.ts @@ -0,0 +1,1406 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as k8s from '@kubernetes/client-node'; +import { + type ReconcilerConfig, + type InferenceService, + type RegisteredModel, + type ModelVersion, + type ModelArtifact, + type KFMRInferenceService, + type ServingEnvironment, + type KServeInferenceService, + type DiscoveryResponse, + KFMRClient, + InferenceServiceState, +} from './types'; +import { ModelCatalog } from './types'; // '@redhat-ai-dev/model-catalog-types'; +import { + callBackstagePrinters, + getKubeFlowInferenceServicesForModelVersion, + loopOverKFMR, + sanitizeName as kfmrSanitizeName, + setupKFMR, +} from './Kfmr'; +import { callBackstagePrinters as callKServeBackstagePrinters } from './KServe'; + +const inference_service_group = 'serving.kserve.io'; +const inference_service_version = 'v1beta1'; +const inference_service_plural = 'inferenceservices'; + +// Re-export route constants for backwards compatibility +export { route_group, route_version, route_plural } from './types'; + +// Model card metadata interface (from server.go line 30-35) +interface ModelCardMetadata { + content: string; + lastUpdateTimeSinceEpoch: string; + updateCount: number; + needToUpdate: boolean; +} + +// Global model cards storage (from server.go line 23) +// This stores model card content indexed by modelCardKey +const modelCards = new Map(); + +// Model catalog metadata interface +interface ModelCatalogMetadata { + catalogData: ModelCatalog; + lastUpdateTimeSinceEpoch: string; + normalizerType: NormalizerType; + updateCount: number; + needToUpdate: boolean; +} + +// Global model catalog storage +// This stores model catalog data indexed by importKey +const modelCatalog = new Map(); + +// Constants for condition types (matching Go constants from bridgerest package) +const INF_SVC_IngressReady_CONDITION = 'IngressReady'; +const INF_SVC_PredictorReady_CONDITION = 'PredictorReady'; +const INF_SVC_Ready_CONDITION = 'Ready'; + +// Label constants for KFMR-managed InferenceServices +const INF_SVC_RM_ID_LABEL = 'modelregistry.opendatahub.io/registered-model-id'; +const INF_SVC_MV_ID_LABEL = 'modelregistry.opendatahub.io/model-version-id'; +// const INF_SVC_INF_SVC_ID_LABEL = +// 'modelregistry.opendatahub.io/inference-service-id'; + +// Normalizer types +enum NormalizerType { + KubeflowNormalizer = 'kubeflow', + KServeNormalizer = 'kserve', +} + +// Types are imported from ./types to avoid circular dependencies +// Re-export for backwards compatibility +export type { + Route, + RouteIngress, + RouteStatus, + ReconcilerConfig, +} from './types'; + +// Result type for processKFMR +interface ProcessKFMRResult { + importKey: string; + lastUpdateTimeSinceEpoch: string; + modelCardKey: string; + modelCard?: string; + catalogData: ModelCatalog; +} + +// Helper function to sanitize names (matching Go util.SanitizeName) +function sanitizeName(name: string): string { + return name.toLowerCase().replace(/[^a-z0-9-]/g, '-'); +} + +// Helper function to build import key (matching Go util.BuildImportKeyAndURI) +function buildImportKeyAndURI( + namespace: string, + name: string, + // format: string, +): [string, string] { + const sanitizedNs = sanitizeName(namespace); + const sanitizedName = sanitizeName(name); + const importKey = `${sanitizedNs}/${sanitizedName}`; + const uri = `/models/${importKey}`; + return [importKey, uri]; +} + +// Helper function to get authentication status for an InferenceService +// Converted from Go GetAuthentication method (kserve.go line 358-382) +// When auth is configured, a service account is created whose name is prefixed with +// the inference service's name, and with the inference service set as an owner reference +async function getAuthentication( + coreClient: k8s.CoreV1Api | undefined, + namespace: string, + inferenceServiceName: string, +): Promise { + if (!coreClient) { + console.log( + `getAuthentication: No coreClient available for ${namespace}/${inferenceServiceName}`, + ); + return false; + } + + try { + const response = await coreClient.listNamespacedServiceAccount(namespace); + const saList = response.body.items; + + for (const sa of saList) { + if (!sa.metadata?.ownerReferences) { + continue; + } + + for (const ownerRef of sa.metadata.ownerReferences) { + if ( + ownerRef.kind === 'InferenceService' && + ownerRef.name === inferenceServiceName + ) { + console.log( + `getAuthentication: Found ServiceAccount ${sa.metadata.name} with InferenceService owner reference for ${namespace}/${inferenceServiceName}`, + ); + return true; + } + } + } + } catch (error) { + console.error( + `getAuthentication: Error listing ServiceAccounts for ${namespace}/${inferenceServiceName}:`, + error, + ); + } + + return false; +} + +// Helper function to list InferenceServices from informer cache or API +// First tries the informer cache, then falls back to API if cache is empty +async function listInferenceServices( + client: k8s.CustomObjectsApi, + informer?: k8s.Informer & k8s.ObjectCache, + labelFilter?: { [key: string]: string }, +): Promise { + // First try to get from informer cache + if (informer) { + const cachedList = informer.list() as InferenceService[]; + if (cachedList && cachedList.length > 0) { + console.log( + `listInferenceServices: Got ${cachedList.length} InferenceServices from informer cache`, + ); + + // Apply label filter if provided + if (labelFilter && Object.keys(labelFilter).length > 0) { + const filtered = cachedList.filter(is => { + if (!is.metadata.labels) return false; + for (const [key, value] of Object.entries(labelFilter)) { + if (is.metadata.labels[key] !== value) { + return false; + } + } + return true; + }); + console.log( + `listInferenceServices: Filtered to ${filtered.length} InferenceServices by labels`, + ); + if (filtered.length > 0) { + return filtered; + } + } else { + return cachedList; + } + } + } + + // Fall back to API call + console.log( + 'listInferenceServices: Informer cache empty, falling back to API', + ); + try { + // Build label selector string if filter provided + let labelSelector: string | undefined; + if (labelFilter && Object.keys(labelFilter).length > 0) { + labelSelector = Object.entries(labelFilter) + .map(([k, v]) => `${k}=${v}`) + .join(','); + } + + const response = await client.listNamespacedCustomObject( + inference_service_group, + inference_service_version, + '', + inference_service_plural, + undefined, + undefined, + undefined, + undefined, + labelSelector, + ); + + const items = (response.body as any).items as InferenceService[]; + console.log( + `listInferenceServices: Got ${ + items?.length || 0 + } InferenceServices from API`, + ); + return items || []; + } catch (error) { + console.error('listInferenceServices: Error listing from API:', error); + return []; + } +} + +// Helper function to check if KServe InferenceService maps to KFMR model +// Converted from Go util.KServeInferenceServiceMapping (utils.go line 123) +function kserveInferenceServiceMapping( + registeredModelId: string, + modelVersionId: string, + is: InferenceService, +): boolean { + // Check if labels exist (Go line 124-126) + if (!is.metadata.labels) { + return false; + } + + // Check registered model ID label (Go line 128-135) + const rmVal = is.metadata.labels[INF_SVC_RM_ID_LABEL]; + if (!rmVal) { + return false; + } + + if (registeredModelId.trim() !== rmVal.trim()) { + return false; + } + + // Check model version ID label (Go line 137-144) + const mvVal = is.metadata.labels[INF_SVC_MV_ID_LABEL]; + if (!mvVal) { + return false; + } + + if (modelVersionId.trim() !== mvVal.trim()) { + return false; + } + + // All checks passed (Go line 146) + return true; +} + +// Process KFMR (KubeFlow Model Registry) integration +// Converted from Go processKFMR method (controller.go line 442) +async function processKFMR( + namespace: string, + name: string, + is: InferenceService, + config: ReconcilerConfig, +): Promise { + console.log(`processKFMR: Processing ${namespace}/${name}`); + + // Check if KFMR is configured (Go line 444-448) + if (config.kfmrClients.size === 0) { + console.log( + `processKFMR: No KFMR routes configured for ${namespace}/${name}`, + ); + return null; + } + + console.log(`processKFMR: Have KFMR clients for ${namespace}/${name}`); + const replacer = (str: string) => str.replace(/ /g, ''); // Go line 451 + + const kfmrRMs: RegisteredModel[] = []; + const kfmrISs: KFMRInferenceService[] = []; + + // Loop over KFMR clients (Go line 455) + for (const [key, kfmr] of config.kfmrClients.entries()) { + try { + // List registered models (Go line 456) + const rms = await kfmr.listRegisteredModels(); + console.log( + `processKFMR: Found ${rms.length} registered models with registry ${key}`, + ); + kfmrRMs.push(...rms); + + // List inference services (Go line 464) + const iss = await kfmr.listInferenceServices(); + console.log( + `processKFMR: Found ${iss.length} inference services from ${key}`, + ); + kfmrISs.push(...iss); + } catch (error) { + console.error( + `processKFMR: Error listing models or services for ${namespace}/${name}:`, + error, + ); + continue; + } + + // Path 1: No KubeFlow inference services - match by model/version name (Go line 472) + if (kfmrISs.length === 0) { + console.log( + `processKFMR: No KubeFlow inference services for registry ${key}`, + ); + + for (const rm of kfmrRMs) { + if (!rm.id) continue; + + try { + // List model versions (Go line 476) + const mvs = await kfmr.listModelVersions(rm.id); + console.log( + `processKFMR: Found ${mvs.length} model versions for registered model ${rm.id}`, + ); + + for (const mv of mvs) { + if (!mv.id) continue; + + // Check if KServe InferenceService maps to this model version (Go line 482) + if (kserveInferenceServiceMapping(rm.id, mv.id, is)) { + console.log( + `processKFMR: Found mapping between KServe IS and model version ${mv.id}`, + ); + + // Get model artifacts (Go line 485) + let mas: ModelArtifact[] = []; + try { + mas = await kfmr.listModelArtifacts(mv.id); + console.log( + `processKFMR: Found ${mas.length} model artifacts for model version ${mv.id}`, + ); + } catch (error) { + console.error( + `processKFMR: Error getting model artifacts for ${mv.id}:`, + error, + ); + } + + if (!mas || mas.length === 0) { + console.log( + `processKFMR: No model artifacts, bypassing backstage printers`, + ); + continue; + } + + // Get authentication status for the KServe InferenceService + const authentication = await getAuthentication( + config.coreClient, + is.metadata.namespace, + is.metadata.name, + ); + + // Call backstage printers (Go line 497) + const catalogData: ModelCatalog = await callBackstagePrinters( + config.defaultOwner, + config.defaultLifecycle, + rm, + mv, + mas, + null, + is as KServeInferenceService, + authentication, + ); + console.log( + `processKFMR: Generated catalog data with ${ + catalogData.models.length + } models and ${catalogData.modelServer ? 1 : 0} model servers`, + ); + + // Build import key (Go line 515) + const [importKey] = buildImportKeyAndURI( + sanitizeName(rm.name), + sanitizeName(mv.name), + ); + + // Get last update timestamp (Go line 516) + let lastUpdateTimeSinceEpoch = mv.lastUpdateTimeSinceEpoch || ''; + if ( + rm.lastUpdateTimeSinceEpoch && + rm.lastUpdateTimeSinceEpoch > lastUpdateTimeSinceEpoch + ) { + lastUpdateTimeSinceEpoch = rm.lastUpdateTimeSinceEpoch; + } + + // Get model card if catalog URL exists (Go line 522) + let modelCard: string | undefined; + let modelCardKey = ''; + if (kfmr.rootCatalogURL) { + for (const ma of mas) { + if (ma.modelSourceClass && ma.modelSourceName) { + try { + modelCard = await kfmr.getModelCard( + ma.modelSourceClass, + ma.modelSourceName, + ); + modelCardKey = + replacer(ma.modelSourceClass) + + replacer(ma.modelSourceName); + console.log( + `processKFMR: Built modelCardKey ${modelCardKey}`, + ); + break; + } catch (error) { + console.error( + `processKFMR: Error getting model card:`, + error, + ); + } + } + } + } + + return { + importKey, + lastUpdateTimeSinceEpoch, + modelCardKey, + modelCard, + catalogData, + }; + } + } + } catch (error) { + console.error( + `processKFMR: Error listing model versions for ${rm.id}:`, + error, + ); + } + } + } + + // Path 2: Found KubeFlow inference services - match with KServe (Go line 542) + console.log( + `processKFMR: Found KubeFlow inference services while processing KServe IS ${namespace}/${name}`, + ); + + for (const rm of kfmrRMs) { + if (!rm.id) { + console.log( + `processKFMR: Registered model ${rm.name} has no ID, skipping`, + ); + continue; + } + + for (const kfmrIS of kfmrISs) { + // Check if KubeFlow IS matches registered model and KServe IS name (Go line 551) + if ( + kfmrIS.id && + kfmrIS.registeredModelId === rm.id && + kfmrIS.name && + is.metadata.name.startsWith(kfmrIS.name) + ) { + console.log( + `processKFMR: KServe IS name match, checking namespace ${namespace} and serving environment ${kfmrIS.servingEnvironmentId}`, + ); + + if (!kfmrIS.servingEnvironmentId) continue; + + // Get serving environment (Go line 556) + let se: ServingEnvironment; + try { + se = await kfmr.getServingEnvironment(kfmrIS.servingEnvironmentId); + } catch (error) { + console.error( + `processKFMR: Error getting serving environment ${kfmrIS.servingEnvironmentId}:`, + error, + ); + continue; + } + + // Check if serving environment name matches namespace (Go line 562) + if (se.name === namespace) { + console.log(`processKFMR: Matched KServe IS ${namespace}/${name}`); + + if (!kfmrIS.modelVersionId) continue; + + // Get model version (Go line 569) + let mv: ModelVersion; + try { + mv = await kfmr.getModelVersion(kfmrIS.modelVersionId); + } catch (error) { + console.error( + `processKFMR: Error getting model version ${kfmrIS.modelVersionId}:`, + error, + ); + continue; + } + + // Get model artifacts (Go line 574) + let mas: ModelArtifact[] = []; + try { + mas = await kfmr.listModelArtifacts(kfmrIS.modelVersionId); + } catch (error) { + console.error( + `processKFMR: Error getting model artifacts for ${kfmrIS.modelVersionId}:`, + error, + ); + } + + if (!mv || !mas || mas.length === 0) { + console.log( + `processKFMR: Missing model version or artifacts, bypassing backstage printers`, + ); + continue; + } + + // Get authentication status for the KServe InferenceService + const authentication = await getAuthentication( + config.coreClient, + is.metadata.namespace, + is.metadata.name, + ); + + // Call backstage printers (Go line 585) + const catalogData: ModelCatalog = await callBackstagePrinters( + config.defaultOwner, + config.defaultLifecycle, + rm, + mv, + mas, + kfmrIS as KFMRInferenceService, + is as KServeInferenceService, + authentication, + ); + console.log( + `processKFMR: Generated catalog data with ${ + catalogData.models.length + } models and ${catalogData.modelServer ? 1 : 0} model servers`, + ); + + // Build import key (Go line 602) + const [importKey] = buildImportKeyAndURI( + sanitizeName(rm.name), + sanitizeName(mv.name), + ); + + // Get last update timestamp (Go line 603) + let lastUpdateTimeSinceEpoch = mv.lastUpdateTimeSinceEpoch || ''; + if ( + rm.lastUpdateTimeSinceEpoch && + rm.lastUpdateTimeSinceEpoch > lastUpdateTimeSinceEpoch + ) { + lastUpdateTimeSinceEpoch = rm.lastUpdateTimeSinceEpoch; + } + + // Get model card if catalog URL exists (Go line 609) + let modelCard: string | undefined; + let modelCardKey = ''; + if (kfmr.rootCatalogURL) { + for (const ma of mas) { + if (ma.modelSourceClass && ma.modelSourceName) { + try { + modelCard = await kfmr.getModelCard( + ma.modelSourceClass, + ma.modelSourceName, + ); + modelCardKey = + replacer(ma.modelSourceClass) + + replacer(ma.modelSourceName); + console.log( + `processKFMR: Built modelCardKey ${modelCardKey}`, + ); + break; + } catch (error) { + console.error( + `processKFMR: Error getting model card:`, + error, + ); + } + } + } + } + + console.log( + `processKFMR: KServe IS ${namespace}/${name} returning importKey ${importKey}`, + ); + return { + importKey, + lastUpdateTimeSinceEpoch, + modelCardKey, + modelCard, + catalogData, + }; + } + } + } + } + } + + // No match found, but not an error - caller can process as KServe-only (Go line 633) + console.log(`processKFMR: No KFMR match for ${namespace}/${name}`); + return null; +} + +// Helper function to check if InferenceService status is ready +function isInferenceServiceReady(is: InferenceService): boolean { + if (!is.status) { + console.log( + `InferenceService ${is.metadata.namespace}/${is.metadata.name} has no status`, + ); + return false; + } + + // Check if conditions exist + if (!is.status.conditions || is.status.conditions.length === 0) { + console.log( + `InferenceService ${is.metadata.namespace}/${is.metadata.name} has no conditions`, + ); + return false; + } + + // Check model status transition status + if (is.status.modelStatus?.transitionStatus !== 'UpToDate') { + console.log( + `InferenceService ${is.metadata.namespace}/${is.metadata.name} transitionStatus is not UpToDate: ${is.status.modelStatus?.transitionStatus}`, + ); + return false; + } + + // Check required conditions + for (const condition of is.status.conditions) { + if ( + condition.type === INF_SVC_IngressReady_CONDITION || + condition.type === INF_SVC_PredictorReady_CONDITION || + condition.type === INF_SVC_Ready_CONDITION + ) { + if (condition.status !== 'True') { + console.log( + `InferenceService ${is.metadata.namespace}/${is.metadata.name} condition ${condition.type} is not True: ${condition.status}`, + ); + return false; + } + } + } + + // Check URL exists + if (!is.status.url && !is.status.address?.url) { + console.log( + `InferenceService ${is.metadata.namespace}/${is.metadata.name} has no URL`, + ); + return false; + } + + return true; +} + +// Main reconciliation logic (converted from Go Reconcile method starting at line 366) +async function reconcileInferenceService( + is: InferenceService, + config: ReconcilerConfig, +): Promise { + const namespace = is.metadata.namespace; + const name = is.metadata.name; + + console.log(`Reconciling InferenceService: ${namespace}/${name}`); + + // Variables to track the reconciliation state + let importKey = ''; + let lastUpdateTimeSinceEpoch = ''; + let modelCardKey = ''; + let modelCard: string | undefined; + let catalogData: ModelCatalog | undefined; + let normalizerType = NormalizerType.KubeflowNormalizer; + + // Step 1: Process KFMR if routes are available (line 365-369 in Go) + if (config.kfmrClients.size > 0) { + console.log(`Processing KFMR for ${namespace}/${name}`); + const result = await processKFMR(namespace, name, is, config); + if (result) { + importKey = result.importKey; + lastUpdateTimeSinceEpoch = result.lastUpdateTimeSinceEpoch; + modelCardKey = result.modelCardKey; + modelCard = result.modelCard; + catalogData = result.catalogData; + } + } + + // Step 2: Handle KServe-only scenario if no importKey (lines 371-408 in Go) + if (!importKey) { + console.log(`Processing KServe-only mode for ${namespace}/${name}`); + normalizerType = NormalizerType.KServeNormalizer; + + // Wait for status to reach a functional, ready state + if (!isInferenceServiceReady(is)) { + console.log( + `InferenceService ${namespace}/${name} is not ready yet, will retry later`, + ); + // In a real implementation, this would requeue the reconciliation + return; + } + + // Get authentication status by checking for ServiceAccount with InferenceService owner reference + const authentication = await getAuthentication( + config.coreClient, + namespace, + name, + ); + + // Call backstage printers (equivalent to kserve.CallBackstagePrinters in Go) + console.log(`Calling backstage printers for ${namespace}/${name}`); + catalogData = await callKServeBackstagePrinters( + config.defaultOwner, + config.defaultLifecycle, + is, + authentication, + ); + console.log( + `Generated KServe catalog data with ${ + catalogData.models.length + } models and ${catalogData.modelServer ? 1 : 0} model servers`, + ); + + // Build import key + [importKey] = buildImportKeyAndURI(namespace, name); + console.log(`Built importKey: ${importKey}`); + } + + // Step 3: Process buffer and send to storage (lines 410-413 in Go) + if (!catalogData) { + console.error( + `No catalog data available for ${namespace}/${name}, skipping processModelCatalog`, + ); + return; + } + + console.log( + `Processing buffer for ${namespace}/${name} with importKey: ${importKey}`, + ); + await processModelCatalog( + importKey, + normalizerType, + lastUpdateTimeSinceEpoch, + modelCardKey, + modelCard, + catalogData, + ); + + console.log(`Successfully reconciled InferenceService: ${namespace}/${name}`); +} + +// Helper function to process buffer and send to storage (matching Go processBWriter) +async function processModelCatalog( + importKey: string, + normalizerType: NormalizerType, + lastUpdateTimeSinceEpoch: string, + modelCardKey: string, + modelCard: string | undefined, + catalogData: ModelCatalog, +): Promise { + console.log( + `processModelCatalog - key: ${importKey}, type: ${normalizerType}, epoch: ${lastUpdateTimeSinceEpoch}, modelCardKey: ${modelCardKey}`, + ); + console.log( + `processModelCatalog - catalogData has ${ + catalogData.models.length + } models and ${catalogData.modelServer ? 1 : 0} model servers`, + ); + + // Handle model catalog storage + if (importKey && importKey.length > 0) { + const existingCatalog = modelCatalog.get(importKey); + + if (!existingCatalog) { + // Create new model catalog metadata entry + const mcm: ModelCatalogMetadata = { + catalogData: catalogData, + lastUpdateTimeSinceEpoch: lastUpdateTimeSinceEpoch, + normalizerType: normalizerType, + needToUpdate: true, + updateCount: 0, + }; + modelCatalog.set(importKey, mcm); + console.log( + `processModelCatalog: Created new model catalog entry for key ${importKey}`, + ); + } else { + // Update existing model catalog metadata if timestamp changed + if ( + existingCatalog.lastUpdateTimeSinceEpoch !== lastUpdateTimeSinceEpoch + ) { + existingCatalog.lastUpdateTimeSinceEpoch = lastUpdateTimeSinceEpoch; + existingCatalog.catalogData = catalogData; + existingCatalog.normalizerType = normalizerType; + existingCatalog.needToUpdate = true; + existingCatalog.updateCount = 0; + modelCatalog.set(importKey, existingCatalog); + console.log( + `processModelCatalog: Updated model catalog entry for key ${importKey} (timestamp changed)`, + ); + } else { + console.log( + `processModelCatalog: Model catalog for key ${importKey} already up to date`, + ); + } + } + } + + // Handle model card storage (converted from server.go lines 219-234) + if (modelCardKey && modelCardKey.length > 0) { + const existingMcm = modelCards.get(modelCardKey); + + if (!existingMcm) { + // Create new model card metadata entry + const mcm: ModelCardMetadata = { + content: modelCard || '', + lastUpdateTimeSinceEpoch: lastUpdateTimeSinceEpoch, + needToUpdate: true, + updateCount: 0, + }; + modelCards.set(modelCardKey, mcm); + console.log( + `processModelCatalog: Created new model card entry for key ${modelCardKey}`, + ); + } else { + // Update existing model card metadata if timestamp changed + if (existingMcm.lastUpdateTimeSinceEpoch !== lastUpdateTimeSinceEpoch) { + existingMcm.lastUpdateTimeSinceEpoch = lastUpdateTimeSinceEpoch; + existingMcm.content = modelCard || existingMcm.content; + existingMcm.needToUpdate = true; + existingMcm.updateCount = 0; + modelCards.set(modelCardKey, existingMcm); + console.log( + `processModelCatalog: Updated model card entry for key ${modelCardKey} (timestamp changed)`, + ); + } else { + console.log( + `processModelCatalog: Model card for key ${modelCardKey} already up to date`, + ); + } + } + } +} + +// Helper function to call backstage printers and process model catalog +// Converted from innerStartCallBackstagePrinters (controller.go line 839-878) +async function innerStartCallBackstagePrinters( + kfmr: KFMRClient, + rm: RegisteredModel, + mv: ModelVersion, + kfmrIS: KFMRInferenceService | null, + kserveIS: InferenceService | null, + maa: ModelArtifact[], + replacer: (str: string) => string, + importKey: string, + lastUpdateTimeSinceEpoch: string, + config: ReconcilerConfig, + authentication: boolean = false, +): Promise { + // Call backstage printers (Go line 852) + const catalogData: ModelCatalog = await callBackstagePrinters( + config.defaultOwner, + config.defaultLifecycle, + rm, + mv, + maa, + kfmrIS as KFMRInferenceService | null, + kserveIS as KServeInferenceService | null, + authentication, + ); + + // Get model card if catalog URL exists (Go line 859-870) + let modelCard: string | undefined; + let modelCardKey = ''; + if (kfmr.rootCatalogURL) { + for (const ma of maa) { + if (ma.modelSourceClass && ma.modelSourceName) { + try { + modelCard = await kfmr.getModelCard( + ma.modelSourceClass, + ma.modelSourceName, + ); + modelCardKey = + replacer(ma.modelSourceClass) + replacer(ma.modelSourceName); + console.log(`innerStart: built modelCardKey ${modelCardKey}`); + break; + } catch (error) { + console.error('innerStart: error getting model card:', error); + } + } + } + } + + // Process model catalog (Go line 872) + await processModelCatalog( + importKey, + NormalizerType.KubeflowNormalizer, + lastUpdateTimeSinceEpoch, + modelCardKey, + modelCard, + catalogData, + ); +} + +// Main polling/sync function (converted from Go innerStart method starting at line 651) +// This is called on delete events and during background polling to sync the current state +async function innerStart( + client: k8s.CustomObjectsApi, + // coreClient: k8s.CoreV1Api, + config: ReconcilerConfig, +): Promise { + console.log('innerStart: Beginning reconciliation sync'); + + const updConfig = await setupKFMR(config); + + const keys: string[] = []; + + // Step 1: Process KFMR registries (lines 658-794 in Go) + const replacer = (str: string) => str.replace(/ /g, ''); + console.log(`innerStart: len kfmr ${updConfig.kfmrClients.size}`); + + for (const [registryKey, kfmr] of updConfig.kfmrClients.entries()) { + try { + // Call loopOverKFMR to get registered models, model versions, and model artifacts (Go line 664) + const { registeredModels, modelVersionsMap, modelArtifactsMap } = + await loopOverKFMR(kfmr as KFMRClient); + + console.log( + `innerStart: len rms ${registeredModels.length} mvs ${modelVersionsMap.size} mas ${modelArtifactsMap.size}`, + ); + + // Process each registered model (Go line 670) + for (const rm of registeredModels) { + const rmNameKey = kfmrSanitizeName(rm.name); + + // Get model versions for this registered model (Go line 671) + const mva = modelVersionsMap.get(rmNameKey); + if (!mva) { + console.log(`innerStart: mvs rm disconnect ${rm.name}`); + continue; + } + + // Get model artifacts map for this registered model (Go line 676) + const maa = modelArtifactsMap.get(rmNameKey); + if (!maa) { + console.log(`innerStart: mas rm disconnect ${rm.name}`); + continue; + } + + let foundKServe = false; + + // Process each model version (Go line 682) + for (const mv of mva) { + if (!mv.id) continue; + + // Build import key (Go line 684) + const [importKey] = buildImportKeyAndURI( + kfmrSanitizeName(rm.name), + kfmrSanitizeName(mv.name), + ); + console.log( + `innerStart: importKey ${importKey} from rm ${rm.name} mv ${mv.name}`, + ); + + // Get last update timestamp (Go line 686-688) + let lastUpdateTimeSinceEpoch = mv.lastUpdateTimeSinceEpoch || ''; + if ( + rm.lastUpdateTimeSinceEpoch && + rm.lastUpdateTimeSinceEpoch > lastUpdateTimeSinceEpoch + ) { + lastUpdateTimeSinceEpoch = rm.lastUpdateTimeSinceEpoch; + } + + // Add import key to keys array (Go line 690) + keys.push(importKey); + + // Get model artifacts for this model version + const mvArtifacts = maa.get(mv.id) || []; + + // Get KubeFlow inference services for this model version (Go line 700-701) + let mvISL: KFMRInferenceService[] = []; + try { + mvISL = await getKubeFlowInferenceServicesForModelVersion( + kfmr as KFMRClient, + mv, + ); + } catch (error) { + console.error( + 'innerStart: error listing kubeflow inference services:', + error, + ); + continue; + } + + // If no KubeFlow inference services, call backstage printers without KServe (Go line 706-722) + if (mvISL.length === 0) { + try { + // No KServe InferenceService, so authentication is false + await innerStartCallBackstagePrinters( + kfmr as KFMRClient, + rm, + mv, + null, + null, + mvArtifacts, + replacer, + importKey, + lastUpdateTimeSinceEpoch, + config, + false, + ); + } catch (error) { + console.log( + `innerStart: callBackstage printers len mvISL 0 error: ${error}`, + ); + } + continue; + } + + // Process each KubeFlow inference service (Go line 724) + for (const kis of mvISL) { + // Check if deployed (Go line 725-732) + if (kis.desiredState !== InferenceServiceState.Deployed) { + console.log( + `innerStart: kubeflow infsvc ${kis.name} id ${kis.id} not deployed`, + ); + continue; + } + + // Find matching KServe inference service by labels (Go line 734-753) + let kserveIS: InferenceService | null = null; + const labelFilter = { + [INF_SVC_RM_ID_LABEL]: rm.id!, + [INF_SVC_MV_ID_LABEL]: mv.id!, + }; + const matchingISList = await listInferenceServices( + client, + config.informer, + labelFilter, + ); + if (matchingISList.length > 0) { + kserveIS = matchingISList[0]; + console.log( + `innerStart: found kserve infsvc ${kserveIS.metadata.namespace}:${kserveIS.metadata.name} from rm ${rm.id} mv ${mv.id} kubeflow is ${kis.id}`, + ); + } + + if (!kserveIS) { + continue; + } + + // Get authentication status for the KServe InferenceService + const authentication = await getAuthentication( + config.coreClient, + kserveIS.metadata.namespace, + kserveIS.metadata.name, + ); + + // Call backstage printers with both KubeFlow and KServe (Go line 759-776) + try { + await innerStartCallBackstagePrinters( + kfmr as KFMRClient, + rm, + mv, + kis, + kserveIS, + mvArtifacts, + replacer, + importKey, + lastUpdateTimeSinceEpoch, + config, + authentication, + ); + } catch (error) { + console.error( + `innerStart: error from call backstage printers: ${error}`, + ); + } + + // Break since only one kubeflow infsvc can match to kserve infsvc (Go line 776) + foundKServe = true; + break; + } + + // If no KServe match found, call backstage printers without KServe (Go line 778-791) + if (!foundKServe) { + try { + // No KServe InferenceService, so authentication is false + await innerStartCallBackstagePrinters( + kfmr as KFMRClient, + rm, + mv, + null, + null, + mvArtifacts, + replacer, + importKey, + lastUpdateTimeSinceEpoch, + config, + false, + ); + } catch (error) { + console.error( + `innerStart: error from call backstage printers (no kserve): ${error}`, + ); + } + } + } + } + } catch (error) { + console.error(`innerStart: err looping over KFMR ${registryKey}:`, error); + } + } + + // Step 2: List all KServe InferenceServices (lines 796-824 in Go) + console.log('innerStart: Listing all KServe InferenceServices'); + + try { + const inferenceServices = await listInferenceServices( + client, + config.informer, + ); + console.log( + `innerStart: Found ${inferenceServices.length} KServe InferenceServices`, + ); + + for (const is of inferenceServices) { + let skip = false; + + // Skip InferenceServices managed by KubeFlow (lines 803-816 in Go) + if (is.metadata.labels && config.kfmrClients.size > 0) { + for (const labelKey of Object.keys(is.metadata.labels)) { + if ( + labelKey === INF_SVC_MV_ID_LABEL || + labelKey === INF_SVC_RM_ID_LABEL + ) { + console.log( + `innerStart: Skipping InferenceService ${is.metadata.namespace}/${is.metadata.name} since it is managed by KubeFlow`, + ); + skip = true; + break; + } + } + } + + if (!skip) { + // Build import key for KServe-only InferenceService (line 819) + const [importKey] = buildImportKeyAndURI( + is.metadata.namespace, + is.metadata.name, + ); + console.log( + `innerStart: Adding importKey ${importKey} for KServe InferenceService ${is.metadata.namespace}/${is.metadata.name}`, + ); + keys.push(importKey); + } + } + } catch (error) { + console.error('innerStart: Error listing KServe InferenceServices:', error); + } + + // Step 3: Clean up stale entries from modelCatalog (Go lines 826-835) + // Remove any model catalog entries whose keys are no longer present in the current reconciliation + const keysToDelete: string[] = []; + for (const catalogKey of modelCatalog.keys()) { + if (!keys.includes(catalogKey)) { + console.log( + `innerStart: Model catalog key ${catalogKey} no longer exists in current keys, marking for deletion`, + ); + keysToDelete.push(catalogKey); + } + } + + for (const keyToDelete of keysToDelete) { + modelCatalog.delete(keyToDelete); + console.log( + `innerStart: Deleted stale model catalog entry: ${keyToDelete}`, + ); + } + + if (keysToDelete.length > 0) { + console.log( + `innerStart: Cleaned up ${keysToDelete.length} stale model catalog entries`, + ); + } + + console.log('innerStart: Reconciliation sync complete'); +} + +// Get discovery URIs from model catalog (matching Go handleCatalogDiscoveryGet, server.go lines 162-182) +// Returns all URIs from modelCatalog that have valid catalog data +export function getDiscoveryUris(): DiscoveryResponse { + const uris: string[] = []; + + // Iterate over model catalog entries + // Since we cannot delete handlers in some routing frameworks, when we delete a location, + // rather than removing from the map, we might set contents to null/undefined, + // so we check for that before deciding to include the URI + for (const [uri, metadata] of modelCatalog.entries()) { + // Only include URIs where catalogData exists and is valid + if (metadata.catalogData) { + uris.push(uri); + } + } + + return { uris }; +} + +export function getModelCatalog(id: string): ModelCatalog | undefined { + const mcm = modelCatalog.get(id); + if (mcm) { + return mcm.catalogData; + } + return undefined; +} + +export function getModelCard(id: string): string | undefined { + const mcm = modelCards.get(id); + if (mcm) { + return mcm?.content; + } + return undefined; +} + +export const setupInformer = async () => { + const kc = new k8s.KubeConfig(); + kc.loadFromDefault(); + + const client = kc.makeApiClient(k8s.CustomObjectsApi); + const coreClient = kc.makeApiClient(k8s.CoreV1Api); + + let k8sToken: string | undefined = ''; + const currentUser = kc.getCurrentUser(); + if (currentUser !== null) { + k8sToken = currentUser.token; + } else { + const users = kc.getUsers(); + for (const user of users) { + if (user.token !== null) { + k8sToken = user.token; + break; + } + } + } + if (process.env.K8S_TOKEN && process.env.K8S_TOKEN.length > 0) { + k8sToken = process.env.K8S_TOKEN; + } + + // Initialize configuration from environment variables + const config: ReconcilerConfig = { + kfmrClients: new Map(), + kfmrRoutes: new Map(), + kfmrCatalogRoute: undefined, + defaultLifecycle: process.env.LIFECYCLE || 'production', + defaultOwner: process.env.OWNER || 'default-owner', + k8sToken: k8sToken, + routeClient: client, + coreClient: coreClient, + }; + + console.log('Reconciler configuration (before setupKFMR):', { + defaultLifecycle: config.defaultLifecycle, + defaultOwner: config.defaultOwner, + kfmrClients: config.kfmrClients.size, + }); + + // Setup KFMR clients (equivalent to Go line 263: reconciler.setupKFMR(ctx)) + try { + await setupKFMR(config); + console.log( + `Reconciler configuration (after setupKFMR): KFMR clients initialized: ${config.kfmrClients.size}`, + ); + } catch (error) { + console.error('Error setting up KFMR:', error); + } + + const listFn: k8s.ListPromise = () => + client.listClusterCustomObject( + inference_service_group, + inference_service_version, + inference_service_plural, + ) as any; + + config.informer = k8s.makeInformer( + kc, + `/apis/${inference_service_group}/${inference_service_version}/${inference_service_plural}`, + listFn, + ); + + config.informer.on('add', async (obj: InferenceService) => { + console.log( + `Added: ${obj.metadata.name} in namespace ${obj.metadata.namespace}`, + ); + + // Execute the reconciliation logic (converted from Go Reconcile method) + try { + await reconcileInferenceService(obj, config); + } catch (error) { + console.error( + `Error reconciling InferenceService ${obj.metadata.namespace}/${obj.metadata.name}:`, + error, + ); + } + }); + + config.informer.on('update', async (obj: InferenceService) => { + console.log( + `Updated: ${obj.metadata.name} in namespace ${obj.metadata.namespace}`, + ); + + // Execute the reconciliation logic for updates as well + try { + await reconcileInferenceService(obj, config); + } catch (error) { + console.error( + `Error reconciling InferenceService ${obj.metadata.namespace}/${obj.metadata.name}:`, + error, + ); + } + }); + + config.informer.on('delete', async (obj: InferenceService) => { + console.log( + `Deleted: ${obj.metadata.name} in namespace ${obj.metadata.namespace}`, + ); + + // Delete processing: Call innerStart to sync the current state (Go code line 339-351) + // This will: + // 1. Poll KFMR to remove URLs/routes from model entries that depended on this InferenceService + // 2. If the delete resulted from archiving, remove the model from storage + // 3. Update the current key set to reflect the deletion + try { + console.log( + `Initiating delete processing for ${obj.metadata.namespace}/${obj.metadata.name}`, + ); + await innerStart(client, /* coreClient,*/ config); + console.log( + `Delete processing completed for ${obj.metadata.namespace}/${obj.metadata.name}`, + ); + } catch (error) { + console.error( + `Error during delete processing for ${obj.metadata.namespace}/${obj.metadata.name}:`, + error, + ); + } + }); + + config.informer.on('error', (err: any) => { + console.error('Informer error:', err); + // Restart informer after a delay + setTimeout(() => { + config.informer?.start(); + }, 5000); + }); + + console.log('Starting informer for InferenceServices...'); + await config.informer.start(); + console.log('Informer started.'); + + // Optional: Start background polling to supplement the informer + // This matches the Go Start method (lines 639-649) + // The controller relist does not duplicate delete events, so background polling + // provides more fine-grained control over what we attempt to relist + const pollingInterval = parseInt( + process.env.POLLING_INTERVAL || '120000', + 10, + ); // Default 2 minutes + + if (pollingInterval > 0) { + console.log( + `Starting background polling every ${pollingInterval / 1000} seconds`, + ); + // Store the timer in case we need to stop it later + (config.informer as any).__pollingTimer = setInterval(async () => { + try { + console.log('Background polling: Calling innerStart'); + await innerStart(client, /* coreClient,*/ config); + } catch (error) { + console.error('Background polling: Error during innerStart:', error); + } + }, pollingInterval); + } + + return config.informer; +}; diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/KServe.ts b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/KServe.ts new file mode 100644 index 0000000000..ab1abf25e2 --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/KServe.ts @@ -0,0 +1,311 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Converted from kserve.go in model-catalog-bridge + +import { PropertyKeys } from './Kfmr'; +import { + type ModelCatalog, + type Model, + type ModelServer, + Type as APIType, +} from './types'; // '@redhat-ai-dev/model-catalog-types'; + +// Annotation prefix (from brdgtypes package) +const ANNOTATION_PREFIX = 'model-catalog-bridge.ai.redhat.com/'; + +// Model framework constants (from kserve.go line 25-36) +const FRAMEWORK_SKLEARN = 'sklearn'; +const FRAMEWORK_XGBOOST = 'xgboost'; +const FRAMEWORK_TENSORFLOW = 'tensorflow'; +const FRAMEWORK_PYTORCH = 'pytorch'; +const FRAMEWORK_TRITON = 'triton'; +const FRAMEWORK_ONNX = 'onnx'; +const FRAMEWORK_HUGGINGFACE = 'huggingface'; +const FRAMEWORK_PMML = 'pmml'; +const FRAMEWORK_LIGHTGBM = 'lightgbm'; +const FRAMEWORK_PADDLE = 'paddle'; + +// InferenceService interface (matching KServe API) +export interface KServeInferenceService { + metadata: { + name: string; + namespace: string; + labels?: { [key: string]: string }; + annotations?: { [key: string]: string }; + }; + spec: { + predictor: { + sklearn?: any; + xgboost?: any; + tensorflow?: any; + pytorch?: any; + triton?: any; + onnx?: any; + huggingface?: any; + pmml?: any; + lightgbm?: any; + paddle?: any; + model?: { + modelFormat: { + name: string; + version?: string; + }; + storageURI?: string; + storage?: { + path?: string; + }; + }; + }; + explainer?: { + art?: { + type: string; + }; + }; + }; + status?: { + url?: { + toString(): string; + }; + address?: { + url: string; + }; + components?: { + [key: string]: { + url?: { + toString(): string; + }; + restURL?: { + toString(): string; + }; + grpcURL?: { + toString(): string; + }; + }; + }; + }; +} + +// Re-export types from @redhat-ai-dev/model-catalog-types for use by consumers +export type { ModelCatalog, Model, ModelServer }; + +// Helper function: Sanitize name +function sanitizeName(name: string): string { + return name.toLowerCase().replace(/[^a-z0-9-]/g, '-'); +} + +// Helper function: Fix key for annotation (kserve.go line 315) +function fixKeyForAnnotation(key: string): string { + const lowerKey = key.toLowerCase(); + return lowerKey.replace(/ /g, ''); +} + +// Helper function: Get string property value from annotations (kserve.go line 322) +function getStringPropVal( + key: string, + is: KServeInferenceService, +): string | undefined { + if (!is || !is.metadata.annotations) { + return undefined; + } + + const annotationKey = `${ANNOTATION_PREFIX}${fixKeyForAnnotation(key)}`; + const val = is.metadata.annotations[annotationKey]; + + return val || undefined; +} + +// Get name (namespace_name format) - kserve.go line 54 +function getName(is: KServeInferenceService): string { + return `${is.metadata.namespace}_${is.metadata.name}`; +} + +// Get description - kserve.go line 60 +function getDescription(is: KServeInferenceService): string { + return `KServe instance ${is.metadata.namespace}:${is.metadata.name}`; +} + +// Get tags from predictor spec - kserve.go line 113 +function getTags(is: KServeInferenceService): string[] { + const tags: string[] = []; + + if (!is) { + return tags; + } + + const predictor = is.spec.predictor; + + // Check predictor types (Go uses fallthrough, so we check all) + if (predictor.sklearn) tags.push(FRAMEWORK_SKLEARN); + if (predictor.xgboost) tags.push(FRAMEWORK_XGBOOST); + if (predictor.tensorflow) tags.push(FRAMEWORK_TENSORFLOW); + if (predictor.pytorch) tags.push(FRAMEWORK_PYTORCH); + if (predictor.triton) tags.push(FRAMEWORK_TRITON); + if (predictor.onnx) tags.push(FRAMEWORK_ONNX); + if (predictor.huggingface) tags.push(FRAMEWORK_HUGGINGFACE); + if (predictor.pmml) tags.push(FRAMEWORK_PMML); + if (predictor.lightgbm) tags.push(FRAMEWORK_LIGHTGBM); + if (predictor.paddle) tags.push(FRAMEWORK_PADDLE); + + // Generic model format + if (predictor.model) { + const modelFormat = predictor.model.modelFormat; + let tag = modelFormat.name; + if (modelFormat.version) { + tag = `${tag}-${modelFormat.version}`; + } + tags.push(tag.toLowerCase()); + } + + // Explainer + if (is.spec.explainer?.art) { + tags.push(is.spec.explainer.art.type.toLowerCase()); + } + + return tags; +} + +// Get tags from labels - used for ModelServer and API - kserve.go line 391 +function getTagsFromLabels(is: KServeInferenceService): string[] { + const tags: string[] = []; + + if (!is.metadata.labels) { + return tags; + } + + for (const [k, v] of Object.entries(is.metadata.labels)) { + const tag = `${sanitizeName(k)}-${sanitizeName(v)}`; + tags.push(sanitizeName(tag)); + } + + return tags; +} + +// Get artifact location URL - kserve.go line 580 +function getArtifactLocationURL( + is: KServeInferenceService, +): string | undefined { + const model = is.spec.predictor.model; + + if (model?.storageURI) { + return model.storageURI; + } + + if (model?.storage?.path) { + return `s3://${model.storage.path}`; + } + + return undefined; +} + +// Main function: Call backstage printers for KServe +// Converted from CallBackstagePrinters (kserve.go line 260) +export async function callBackstagePrinters( + owner: string, + lifecycle: string, + is: KServeInferenceService, + authentication: boolean = false, +): Promise { + console.log( + `KServe.callBackstagePrinters: namespace=${is.metadata.namespace}, name=${is.metadata.name}, authentication=${authentication}`, + ); + + return generateModelCatalog(owner, lifecycle, is, authentication); +} + +// Generate model catalog (kserve.go line 269-276) +function generateModelCatalog( + owner: string, + lifecycle: string, + is: KServeInferenceService, + authentication: boolean, +): ModelCatalog { + const name = `${sanitizeName(getName(is))}`; + + // Get property values with fallbacks + const ownerValue = + getStringPropVal(PropertyKeys.Owner, is) || sanitizeName(owner); + const lifecycleValue = + getStringPropVal(PropertyKeys.Lifecycle, is) || lifecycle; + const description = + getStringPropVal(PropertyKeys.DescriptionKey, is) || getDescription(is); + const techdocsUrl = getStringPropVal(PropertyKeys.TechDocsKey, is); + + // Build model object (kserve.go line 646-674) + const model: Model = { + name: name, + owner: sanitizeName(ownerValue), + lifecycle: lifecycleValue, + description: description, + tags: getTags(is), + artifactLocationURL: getArtifactLocationURL(is), + ethics: getStringPropVal(PropertyKeys.EthicsKey, is), + howToUseURL: getStringPropVal(PropertyKeys.HowToUseKey, is), + support: getStringPropVal(PropertyKeys.SupportKey, is), + training: getStringPropVal(PropertyKeys.TrainingKey, is), + usage: getStringPropVal(PropertyKeys.UsageKey, is), + license: getStringPropVal(PropertyKeys.LicenseKey, is), + annotations: { + 'model-name': is.metadata.name, + ...(techdocsUrl ? { [PropertyKeys.TechDocsKey]: techdocsUrl } : {}), + }, + }; + + // Determine API type + const apiTypeStr = getStringPropVal(PropertyKeys.APITypeKey, is); + let apiType = APIType.Openapi; + if (apiTypeStr) { + switch (apiTypeStr.toLowerCase()) { + case 'graphql': + apiType = APIType.Graphql; + break; + case 'asyncapi': + apiType = APIType.Asyncapi; + break; + case 'grpc': + apiType = APIType.Grpc; + break; + default: + apiType = APIType.Openapi; + } + } + + // Build model server object (kserve.go line 679-698) + const modelServer: ModelServer = { + name: sanitizeName(name), + owner: sanitizeName(ownerValue), + lifecycle: lifecycleValue, + description: description, + homepageURL: getStringPropVal(PropertyKeys.HomepageURLKey, is), + usage: getStringPropVal(PropertyKeys.UsageKey, is), + tags: getTagsFromLabels(is), + authentication: authentication, + API: { + type: apiType, + spec: getStringPropVal(PropertyKeys.APISpecKey, is) || 'TBD', + tags: getTagsFromLabels(is), + url: is.status?.url?.toString() || is.status?.address?.url || '', + }, + }; + + return { + models: [model], + modelServer: modelServer, + }; +} + +// Export helper functions that may be needed +export { getName, getDescription, getTags }; diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/Kfmr.ts b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/Kfmr.ts new file mode 100644 index 0000000000..ada5bfe659 --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/Kfmr.ts @@ -0,0 +1,837 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Converted from kfmr.go in model-catalog-bridge + +import { Agent } from 'undici'; + +import { + ModelCatalog, + Model, + ModelServer, + API, + Type as APIType, +} from './types'; // '@redhat-ai-dev/model-catalog-types'; + +// Agent to skip TLS verification +const tlsSkipAgent = new Agent({ + connect: { + rejectUnauthorized: false, + }, +}); + +import { + type ReconcilerConfig, + type Route, + type RegisteredModel, + type RegisteredModelList, + type ModelVersion, + type ModelVersionList, + type ModelArtifact, + type ModelArtifactList, + type KFMRInferenceService, + type InferenceServiceList, + type ServingEnvironment, + type CatalogModel, + type KServeInferenceService, + type MetadataValue, + type KFMRClient, + type LoopOverKFMRResult, + RegisteredModelState, + ModelVersionState, + route_group, + route_version, + route_plural, +} from './types'; + +// Constants (from kfmr.go line 26-30) +const TAG_REGEXP = '^[a-z0-9:+#]+(\\-[a-z0-9:+#]+)*$'; + +// Environment variable constants +const MODEL_REGISTRY_ROUTE_ENV_VAR = 'MODEL_REGISTRY_ROUTE'; +const MODEL_REGISTRY_TOKEN_ENV_VAR = 'MODEL_REGISTRY_TOKEN'; +const KFMR_BASE_URI = '/api/model_registry/v1alpha3'; +const KFMR_CATALOG_BASE_URI = '/api/model_catalog/v1alpha1'; + +// REST API URI constants (from pkg/rest/kfmr.go) +const LIST_REG_MODEL_URI = '/registered_models'; +// @ts-ignore +const GET_REG_MODEL_URI = '/registered_models/%s'; +// @ts-ignore +const LIST_VERSIONS_OFF_REG_MODELS_URI = '/registered_models/%s/versions'; +// @ts-ignore +const LIST_ARTIFACTS_OFF_VERSIONS_URI = '/model_versions/%s/artifacts'; +// @ts-ignore +const LIST_INFERENCE_SERVICES_URI = '/inference_services'; +// @ts-ignore +const GET_SERVING_ENV_URI = '/serving_environments/%s'; +// @ts-ignore +const GET_MODEL_ARTIFACT_URI = '/model_artifacts/%s'; +// @ts-ignore +const GET_MODEL_VERSION_URI = '/model_versions/%s'; +// Catalog API URI (from pkg/rest/kfmr.go line 25) +const GET_CATALOG_MODEL_URI = '/sources/%s/models/%s'; + +// Helper function for making GET requests to the model registry +// Converted from Go getFromModelRegistry method (rest.go line 57-71) +async function getFromModelRegistry(url: string, token: string): Promise { + const response = await fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + // @ts-ignore - dispatcher is a valid option for Node.js fetch via undici + dispatcher: tlsSkipAgent, + }); + + if (!response.ok) { + const body = await response.text(); + throw new Error( + `GET request to ${url} failed with status ${response.status}: ${body}`, + ); + } + + console.log(`GET request to ${url} returned ok`); + return response.json(); +} + +// Setup KFMR configuration +// Converted from Go setupKFMR method (controller.go line 113-206) +export async function setupKFMR( + config: ReconcilerConfig, +): Promise { + // Check if KFMR clients already initialized (Go line 114-116) + if (config.kfmrClients.size > 0) { + console.log('setupKFMR: KFMR clients already initialized'); + return config; + } + + // String replacer to remove \r and \n (Go line 118-120) + const replacer = (str: string) => str.replace(/\r/g, '').replace(/\n/g, ''); + + let mrRoute = process.env[MODEL_REGISTRY_ROUTE_ENV_VAR] || ''; + mrRoute = replacer(mrRoute); + const routeTuples = mrRoute.split(','); + + console.log(`setupKFMR: route env var ${mrRoute}`); + + // Process each route tuple from environment variable (Go line 123-157) + for (const routeTuple of routeTuples) { + if (routeTuple.length === 0) { + continue; + } + + const parts = routeTuple.split(':'); + let kfmrRoute: Route | undefined; + let ns = ''; + let name = parts[0]; + + if (parts.length > 1) { + ns = parts[0]; + name = parts[1]; + } + + try { + // Handle namespace-based route lookup (Go line 135-149) + if (ns === '' && config.routeClient) { + // List all routes and find by name + const listResponse = + await config.routeClient.listNamespacedCustomObject( + route_group, + route_version, + ns, + route_plural, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + false, + ); + const routes = (listResponse.body as any).items as Route[]; + for (const route of routes) { + if (route.metadata.name === name) { + kfmrRoute = route; + break; + } + } + } else if (config.routeClient) { + // Get specific route by namespace and name (Go line 148) + const getResponse = await config.routeClient.getNamespacedCustomObject( + route_group, + route_version, + ns, + route_plural, + name, + undefined, + ); + kfmrRoute = getResponse.body as Route; + } + + // Store route if it has ingress (Go line 154-156) + if ( + kfmrRoute && + kfmrRoute.status?.ingress && + kfmrRoute.status.ingress.length > 0 + ) { + config.kfmrRoutes.set(routeTuple, kfmrRoute); + } + } catch (error) { + console.error( + `setupKFMR: error fetching model registry route ${routeTuple}:`, + error, + ); + continue; + } + } + + console.log(`setupKFMR: env var route list len ${config.kfmrRoutes.size}`); + + // If no routes found via env var, try label-based query (Go line 160-180) + if (config.kfmrRoutes.size === 0 && config.routeClient) { + try { + const listResponse = await config.routeClient.listNamespacedCustomObject( + route_group, + route_version, + '', + route_plural, + undefined, + undefined, + undefined, + undefined, + 'app.kubernetes.io/managed-by=model-registry-operator', + undefined, + undefined, + undefined, + undefined, + false, + ); + const routes = (listResponse.body as any).items as Route[]; + + for (const route of routes) { + const key = `${route.metadata.namespace}:${route.metadata.name}`; + console.log(`setupKFMR: query found route ${key}`); + + if (route.metadata.name.includes('catalog')) { + // Catalog is supposed to be a singleton (Go line 171-175) + console.log(`setupKFMR: found catalog ${route.metadata.name}`); + config.kfmrCatalogRoute = route; + continue; + } + + console.log( + `setupKFMR: found registry ${route.metadata.name} storing into map with key ${key}`, + ); + config.kfmrRoutes.set(key, route); + } + } catch (error) { + console.error('setupKFMR: error listing routes by label:', error); + } + } + + // Get KFMR token (Go line 182-186) + let kfmrToken = process.env[MODEL_REGISTRY_TOKEN_ENV_VAR] || ''; + kfmrToken = replacer(kfmrToken); + if (kfmrToken.length === 0) { + kfmrToken = config.k8sToken || ''; + } + + // Create KFMR client for each route (Go line 187-204) + for (const [key, kfmrRoute] of config.kfmrRoutes.entries()) { + // Check if client already exists (Go line 188-192) + if (config.kfmrClients.has(key)) { + console.log( + `setupKFMR: loop through routes check against kfmr key ${key} - already exists`, + ); + continue; + } + + if (!kfmrRoute.status?.ingress || kfmrRoute.status.ingress.length === 0) { + console.log(`setupKFMR: route ${key} has no ingress, skipping`); + continue; + } + + // Create KFMRClient wrapper (Go line 193-200) + const rootRegistryURL = `https://${kfmrRoute.status.ingress[0].host}${KFMR_BASE_URI}`; + let rootCatalogURL: string | undefined; + + if ( + config.kfmrCatalogRoute?.status?.ingress && + config.kfmrCatalogRoute.status.ingress.length > 0 + ) { + rootCatalogURL = `https://${config.kfmrCatalogRoute.status.ingress[0].host}${KFMR_CATALOG_BASE_URI}`; + } + + // Create the KFMRClient instance + const kfmrClient: KFMRClient = { + rootRegistryURL, + rootCatalogURL, + token: kfmrToken, + // Converted from ListRegisteredModels (registeredmodel.go line 10-22) + listRegisteredModels: async (): Promise => { + const url = rootRegistryURL + LIST_REG_MODEL_URI; + const data: RegisteredModelList = await getFromModelRegistry( + url, + kfmrToken, + ); + return data.items || []; + }, + // Converted from ListInferenceServices (inferenceservice.go line 10-25) + listInferenceServices: async (): Promise => { + const url = rootRegistryURL + LIST_INFERENCE_SERVICES_URI; + const data: InferenceServiceList = await getFromModelRegistry( + url, + kfmrToken, + ); + return data.items || []; + }, + // Converted from ListModelVersions (modelversion.go line 10-22) + listModelVersions: async ( + registeredModelId: string, + ): Promise => { + const url = + rootRegistryURL + + LIST_VERSIONS_OFF_REG_MODELS_URI.replace('%s', registeredModelId); + const data: ModelVersionList = await getFromModelRegistry( + url, + kfmrToken, + ); + return data.items || []; + }, + // Converted from ListModelArtifacts (modelartifact.go line 11-23) + listModelArtifacts: async ( + modelVersionId: string, + ): Promise => { + const url = + rootRegistryURL + + LIST_ARTIFACTS_OFF_VERSIONS_URI.replace('%s', modelVersionId); + const data: ModelArtifactList = await getFromModelRegistry( + url, + kfmrToken, + ); + return data.items || []; + }, + // Converted from GetServingEnvironment (servingenvironment.go line 10-22) + getServingEnvironment: async ( + servingEnvironmentId: string, + ): Promise => { + const url = + rootRegistryURL + + GET_SERVING_ENV_URI.replace('%s', servingEnvironmentId); + const data: ServingEnvironment = await getFromModelRegistry( + url, + kfmrToken, + ); + return data; + }, + // Converted from GetModelVersions (modelversion.go line 24-36) + getModelVersion: async ( + modelVersionId: string, + ): Promise => { + const url = + rootRegistryURL + GET_MODEL_VERSION_URI.replace('%s', modelVersionId); + const data: ModelVersion = await getFromModelRegistry(url, kfmrToken); + return data; + }, + // Converted from GetModelCard (catalogmodel.go line 44-50) + getModelCard: async ( + sourceId: string, + modelName: string, + ): Promise => { + if (!rootCatalogURL) { + console.log('getModelCard: no catalog URL configured'); + return undefined; + } + // URL-encode spaces (Go line 27-30) + const encodedSourceId = sourceId.replace(/ /g, '%20'); + const encodedModelName = modelName.replace(/ /g, '%20'); + const url = + rootCatalogURL + + GET_CATALOG_MODEL_URI.replace('%s', encodedSourceId).replace( + '%s', + encodedModelName, + ); + const data: CatalogModel = await getFromModelRegistry(url, kfmrToken); + return data.readme; + }, + }; + + console.log( + `setupKFMR: storing route ${key} into kfmr with URL ${rootRegistryURL}`, + ); + config.kfmrClients.set(key, kfmrClient); + } + + console.log(`setupKFMR: initialized ${config.kfmrClients.size} KFMR clients`); + return config; +} + +// Normalizer formats +export enum NormalizerFormat { + JsonArrayFormat = 'json-array', + CatalogInfoYamlFormat = 'catalog-info.yaml', +} + +// Custom property keys (from brdgtypes package) +export const PropertyKeys = { + LicenseKey: 'license', + TechDocsKey: 'TechDocs', + RHOAIModelCatalogSourceModelVersion: + 'rhoai-model-catalog-source-model-version', + RHOAIModelCatalogSourceModelKey: 'rhoai-model-catalog-source-model', + RHOAIModelCatalogRegisteredFromKey: 'rhoai-model-catalog-registered-from', + RHOAIModelCatalogProviderKey: 'rhoai-model-catalog-provider', + APITypeKey: 'api-type', + RHOAIModelRegistryRegisteredFromCatalogRepositoryName: + 'rhoai-model-registry-registered-from-catalog-repository-name', + RHOAIModelRegistryLastModified: 'last-modified', + Owner: 'owner', + Lifecycle: 'lifecycle', + EthicsKey: 'ethics', + HowToUseKey: 'how-to-use', + SupportKey: 'support', + TrainingKey: 'training', + UsageKey: 'usage', + HomepageURLKey: 'homepage-url', + APISpecKey: 'api-spec', + DescriptionKey: 'description', +}; + +// Re-export types from types.ts for backwards compatibility +export type { + RegisteredModel, + RegisteredModelList, + ModelVersion, + ModelVersionList, + ModelArtifact, + ModelArtifactList, + KFMRInferenceService, + InferenceServiceList, + ServingEnvironment, + CatalogModel, + KServeInferenceService, + MetadataValue, + KFMRClient, + LoopOverKFMRResult, +} from './types'; + +export { + RegisteredModelState, + ModelVersionState, + InferenceServiceState, +} from './types'; + +// Helper function: Extract tags from custom properties +// Converted from getTagsFromCustomProps (kfmr.go line 142) +export function getTagsFromCustomProps( + lastMod: boolean, + props: { [key: string]: MetadataValue }, +): { [key: string]: string } { + const tags: { [key: string]: string } = {}; + const regex = new RegExp(TAG_REGEXP); + + for (const [cpk, cpv] of Object.entries(props)) { + // Skip certain keys (line 146-150) + if (cpk === PropertyKeys.LicenseKey || cpk === PropertyKeys.TechDocsKey) { + console.log('Skip adding TechDocs or License key to tags'); + continue; + } + + // Handle specific property keys (line 151-168) + if ( + cpk === PropertyKeys.RHOAIModelCatalogSourceModelVersion || + cpk === PropertyKeys.RHOAIModelCatalogSourceModelKey || + cpk === PropertyKeys.RHOAIModelCatalogRegisteredFromKey || + cpk === PropertyKeys.RHOAIModelCatalogProviderKey || + cpk === PropertyKeys.APITypeKey || + cpk === PropertyKeys.RHOAIModelRegistryRegisteredFromCatalogRepositoryName + ) { + let v = ''; + if (cpv.metadataStringValue) { + v = cpv.metadataStringValue.stringValue.toLowerCase(); + } + if (v.length > 0 && regex.test(v) && v.length <= 63) { + tags[cpk] = v; + } + continue; + } + + // Handle last modified timestamp (line 169-185) + if (cpk === PropertyKeys.RHOAIModelRegistryLastModified && lastMod) { + let v = ''; + if (cpv.metadataStringValue) { + v = cpv.metadataStringValue.stringValue; + v = v.replace(/:/g, '-'); + v = v.replace(/\./g, '-'); + v = v.replace(/T/g, '-'); + v = v.replace(/Z/g, ''); + v = `last-modified-time-${v}`; + } + if (v.length > 0 && regex.test(v) && v.length <= 63) { + v = v.toLowerCase(); + tags[cpk] = v; + } + continue; + } + + // Default handling (line 186-194) + let v = cpk; + if ( + cpv.metadataStringValue && + cpv.metadataStringValue.stringValue.length > 0 + ) { + v = `${v}-${cpv.metadataStringValue.stringValue.toLowerCase()}`; + } + if (v.length > 0 && regex.test(v) && v.length <= 63) { + tags[cpk] = v; + } + } + + return tags; +} + +// Helper function: Get string property value +// Converted from commonGetStringPropVal (kfmr.go line 199) +export function getStringPropVal( + key: string, + mv: ModelVersion, + rm: RegisteredModel, +): string | undefined { + // Check model version custom properties first + if (mv.customProperties) { + const mvValue = innerGetStringPropVal(key, mv.customProperties); + if (mvValue) { + return mvValue; + } + } + + // Check registered model custom properties + if (rm.customProperties) { + return innerGetStringPropVal(key, rm.customProperties); + } + + return undefined; +} + +// Helper function: Inner get string property value +// Converted from innerGetStringPropVal (kfmr.go line 218) +function innerGetStringPropVal( + key: string, + vmap: { [key: string]: MetadataValue }, +): string | undefined { + const v = vmap[key]; + if (!v) { + return undefined; + } + + if (v.metadataStringValue) { + return v.metadataStringValue.stringValue; + } + + return undefined; +} + +// Re-export types from @redhat-ai-dev/model-catalog-types +export type { ModelCatalog, Model, ModelServer, API }; +export { APIType }; + +// Sanitize name helper +function sanitizeName(name: string): string { + return name.toLowerCase().replace(/[^a-z0-9-]/g, '-'); +} + +// Sanitize model version helper +function sanitizeModelVersion(version: string): string { + // Similar to sanitizeName but may have different rules + return version.toLowerCase().replace(/[^a-z0-9-]/g, '-'); +} + +// Main function: Call backstage printers +// Converted from CallBackstagePrinters (kfmr.go line 711) +export async function callBackstagePrinters( + owner: string, + lifecycle: string, + rm: RegisteredModel, + mv: ModelVersion, + mas: ModelArtifact[], + kfmrIS: KFMRInferenceService | null, + kserveIS: KServeInferenceService | null, + authentication: boolean = false, +): Promise { + console.log( + `callBackstagePrinters: rm=${rm.name}, mv=${mv.name}, authentication=${authentication}`, + ); + + return generateModelCatalog( + owner, + lifecycle, + rm, + mv, + mas, + kfmrIS, + kserveIS, + authentication, + ); +} + +// Generate model catalog +// Converted from PrintModelCatalogPopulator logic (kfmr.go line 726-732) +function generateModelCatalog( + owner: string, + lifecycle: string, + rm: RegisteredModel, + mv: ModelVersion, + mas: ModelArtifact[], + kfmrIS: KFMRInferenceService | null, + kserveIS: KServeInferenceService | null, + authentication: boolean, +): ModelCatalog { + const model: Model = { + name: `${sanitizeName(rm.name)}-${sanitizeModelVersion(mv.name)}`, + owner: getOwner(owner, rm), + lifecycle: getLifecycle(lifecycle, mv, rm), + description: `${rm.description || ''}\n${mv.description || ''}`, + tags: buildTags(rm, mv, mas), + artifactLocationURL: mas.length > 0 ? mas[0].uri : undefined, + annotations: { + 'model-name': `${sanitizeName(rm.name)}-${sanitizeModelVersion(mv.name)}`, + }, + }; + + let techdocsUrl = getStringPropVal(PropertyKeys.TechDocsKey, mv, rm); + if (techdocsUrl === undefined) { + const replacer = (str: string) => str.replace(/ /g, ''); + let modelCardKey = ''; + for (const ma of mas) { + if (ma.modelSourceClass && ma.modelSourceName) { + modelCardKey = + replacer(ma.modelSourceClass) + replacer(ma.modelSourceName); + break; + } + } + techdocsUrl = `/modelcard/${modelCardKey}`; + } + + // @ts-ignore + model.annotations[PropertyKeys.TechDocsKey] = techdocsUrl; + + const modelServer: ModelServer = { + name: '', + owner: getOwner(owner, rm), + lifecycle: getLifecycle(lifecycle, mv, rm), + description: `${rm.description || ''}\n${mv.description || ''}`, + tags: buildTags(rm, mv, mas), + API: { + type: APIType.Openapi, + url: '', + spec: 'TBD', + }, + authentication: authentication, + }; + + if (kfmrIS !== null) { + if (kfmrIS.name !== null) { + modelServer.name = sanitizeName(kfmrIS.name as string); + } + } + if (kserveIS !== null) { + if (modelServer.name.length === 0) { + modelServer.name = sanitizeName(kserveIS.metadata.name); + } + if (modelServer.API) { + modelServer.API.url = + kserveIS.status?.url || kserveIS.status?.address?.url || ''; + } + } + return { + models: [model], + modelServer: modelServer.name.length > 0 ? modelServer : undefined, + }; +} + +// Helper: Get owner with fallback +function getOwner(defaultOwner: string, rm: RegisteredModel): string { + if (defaultOwner && defaultOwner.length > 0) { + return sanitizeName(defaultOwner); + } + if (rm.owner) { + return sanitizeName(rm.owner); + } + return sanitizeName(defaultOwner); +} + +// Helper: Get lifecycle with fallback +function getLifecycle( + defaultLifecycle: string, + mv: ModelVersion, + rm: RegisteredModel, +): string { + const lifecycle = getStringPropVal(PropertyKeys.Lifecycle, mv, rm); + if (lifecycle) { + return sanitizeName(lifecycle); + } + return defaultLifecycle; +} + +// Helper: Build tags from registered model, model version, and artifacts +function buildTags( + rm: RegisteredModel, + mv: ModelVersion, + mas: ModelArtifact[], +): string[] { + const tagsMap: { [key: string]: string } = {}; + + // Get tags from registered model + if (rm.customProperties) { + const rmTags = getTagsFromCustomProps(false, rm.customProperties); + Object.assign(tagsMap, rmTags); + } + + // Get tags from model version + if (mv.customProperties) { + const mvTags = getTagsFromCustomProps(true, mv.customProperties); + Object.assign(tagsMap, mvTags); + } + + // Get tags from model artifacts + for (const ma of mas) { + if (ma.customProperties) { + const maTags = getTagsFromCustomProps(true, ma.customProperties); + Object.assign(tagsMap, maTags); + } + } + + return Object.values(tagsMap); +} + +// Helper function: callKubeflowREST +// Converted from callKubeflowREST (kfmr.go line 110-140) +async function callKubeflowREST( + registeredModelId: string, + kfmr: KFMRClient, +): Promise<{ + modelVersions: ModelVersion[]; + modelArtifacts: Map; +}> { + const finalMVS: ModelVersion[] = []; + const ma = new Map(); + + // List model versions (Go line 112) + const mvs = await kfmr.listModelVersions(registeredModelId); + + for (const mv of mvs) { + // Skip archived model versions (Go line 119-122) + if (mv.state === ModelVersionState.Archived) { + console.log( + `callKubeflowREST: skipping archived model version ${mv.name}`, + ); + continue; + } + + finalMVS.push(mv); + + if (!mv.id) continue; + + // List model artifacts (Go line 125) + let artifacts = await kfmr.listModelArtifacts(mv.id); + + // If no artifacts found for model version, try with registered model ID (Go line 130-136) + if (artifacts.length === 0) { + artifacts = await kfmr.listModelArtifacts(registeredModelId); + } + + ma.set(mv.id, artifacts); + } + + return { modelVersions: finalMVS, modelArtifacts: ma }; +} + +// Helper function: loopOverKFMR +// Converted from LoopOverKFMR (kfmr.go line 32-91) +export async function loopOverKFMR( + kfmr: KFMRClient, +): Promise { + const rmArray: RegisteredModel[] = []; + const mvsMap = new Map(); + const masMap = new Map>(); + + // List all registered models (Go line 40) + const rms = await kfmr.listRegisteredModels(); + + for (const rm of rms) { + // Skip archived registered models (Go line 47-50) + if (rm.state === RegisteredModelState.Archived) { + console.log( + `loopOverKFMR: skipping archived registered model ${rm.name}`, + ); + continue; + } + + if (!rm.id) { + console.log( + `loopOverKFMR: registered model ${rm.name} has no ID, skipping`, + ); + continue; + } + + // Get model versions and artifacts (Go line 53) + const { modelVersions, modelArtifacts } = await callKubeflowREST( + rm.id, + kfmr, + ); + + rmArray.push(rm); + mvsMap.set(sanitizeName(rm.name), modelVersions); + masMap.set(sanitizeName(rm.name), modelArtifacts); + } + + return { + registeredModels: rmArray, + modelVersionsMap: mvsMap, + modelArtifactsMap: masMap, + }; +} + +// Helper function: getKubeFlowInferenceServicesForModelVersion +// Converted from GetKubeFlowInferenceServicesForModelVersion (kfmr.go line 93-108) +export async function getKubeFlowInferenceServicesForModelVersion( + kfmr: KFMRClient, + mv: ModelVersion, +): Promise { + // List all inference services (Go line 95) + const isl = await kfmr.listInferenceServices(); + + // Filter to only include inference services for this model version (Go line 100-105) + const mvISL: KFMRInferenceService[] = []; + for (const is of isl) { + if (is.modelVersionId && is.modelVersionId === mv.id) { + mvISL.push(is); + } + } + + console.log( + `getKubeFlowInferenceServicesForModelVersion: total num kubeflow infsvc ${isl.length}, num matched to model version ${mvISL.length}`, + ); + return mvISL; +} + +// Export additional helper functions that may be needed +export { sanitizeName, sanitizeModelVersion }; diff --git a/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/types.ts b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/types.ts new file mode 100644 index 0000000000..d039e18879 --- /dev/null +++ b/workspaces/ai-integrations/plugins/kserve-kubeflow-connector-backend/src/services/types.ts @@ -0,0 +1,425 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Shared types and constants to avoid circular dependencies between InformerService.ts and Kfmr.ts + +import * as k8s from '@kubernetes/client-node'; + +// Route constants +export const route_group = 'route.openshift.io'; +export const route_version = 'v1'; +export const route_plural = 'routes'; + +// Route interfaces +export interface RouteIngress { + host: string; +} + +export interface RouteStatus { + ingress?: RouteIngress[]; +} + +export interface Route { + apiVersion: string; + kind: string; + metadata: { + name: string; + namespace: string; + uid?: string; + labels?: { [key: string]: string }; + annotations?: { [key: string]: string }; + }; + spec: any; + status?: RouteStatus; +} + +// InferenceService interface (used across modules) +export interface InferenceService { + apiVersion: string; + kind: string; + metadata: { + name: string; + namespace: string; + uid?: string; + labels?: { [key: string]: string }; + annotations?: { [key: string]: string }; + }; + spec: any; + status?: InferenceServiceStatus; +} + +export interface Condition { + type: string; + status: string; + lastTransitionTime?: string; + reason?: string; + message?: string; +} + +export interface ModelStatus { + transitionStatus?: string; + states?: any; +} + +export interface InferenceServiceStatus { + conditions?: Condition[]; + modelStatus?: ModelStatus; + url?: string; + address?: { + url: string; + }; +} + +// KFMR Client interface +export interface KFMRClient { + rootRegistryURL: string; + rootCatalogURL?: string; + token: string; + listRegisteredModels(): Promise; + listInferenceServices(): Promise; + listModelVersions(registeredModelId: string): Promise; + listModelArtifacts(modelVersionId: string): Promise; + getServingEnvironment( + servingEnvironmentId: string, + ): Promise; + getModelVersion(modelVersionId: string): Promise; + getModelCard( + sourceId: string, + modelName: string, + ): Promise; +} + +// Metadata value interface (from openapi package) +export interface MetadataValue { + metadataStringValue?: { + stringValue: string; + }; + metadataIntValue?: { + intValue: number; + }; + metadataBoolValue?: { + boolValue: boolean; + }; + metadataDoubleValue?: { + doubleValue: number; + }; +} + +// Model state enums +export enum RegisteredModelState { + Live = 'LIVE', + Archived = 'ARCHIVED', +} + +export enum ModelVersionState { + Live = 'LIVE', + Archived = 'ARCHIVED', +} + +export enum InferenceServiceState { + Deployed = 'DEPLOYED', + Undeployed = 'UNDEPLOYED', +} + +// KFMR model interfaces +export interface RegisteredModel { + id?: string; + name: string; + lastUpdateTimeSinceEpoch?: string; + description?: string; + owner?: string; + state?: RegisteredModelState; + customProperties?: { [key: string]: MetadataValue }; +} + +export interface RegisteredModelList { + items: RegisteredModel[]; +} + +export interface ModelVersion { + id?: string; + name: string; + lastUpdateTimeSinceEpoch?: string; + registeredModelId?: string; + description?: string; + state?: ModelVersionState; + customProperties?: { [key: string]: MetadataValue }; +} + +export interface ModelVersionList { + items: ModelVersion[]; +} + +export interface ModelArtifact { + id?: string; + name?: string; + modelVersionId?: string; + modelSourceClass?: string; + modelSourceGroup?: string; + modelSourceName?: string; + uri?: string; + description?: string; + customProperties?: { [key: string]: MetadataValue }; +} + +export interface ModelArtifactList { + items: ModelArtifact[]; +} + +export interface KFMRInferenceService { + id?: string; + name?: string; + registeredModelId?: string; + modelVersionId?: string; + servingEnvironmentId?: string; + desiredState?: InferenceServiceState; + runtime?: string; + customProperties?: { [key: string]: MetadataValue }; +} + +export interface InferenceServiceList { + items: KFMRInferenceService[]; +} + +export interface ServingEnvironment { + id?: string; + name?: string; + description?: string; + customProperties?: { [key: string]: MetadataValue }; +} + +// CatalogModel interface (from catalog openapi package) +export interface CatalogModel { + id?: string; + name?: string; + description?: string; + readme?: string; + sourceId?: string; + repositoryName?: string; +} + +export interface KServeInferenceService { + metadata: { + name: string; + namespace: string; + uid?: string; + labels?: { [key: string]: string }; + annotations?: { [key: string]: string }; + }; + spec: any; + status?: { + conditions?: Array<{ + type: string; + status: string; + }>; + url?: string; + address?: { + url: string; + }; + }; +} + +// ReconcilerConfig interface +export interface ReconcilerConfig { + kfmrClients: Map; + kfmrRoutes: Map; + kfmrCatalogRoute?: Route; + defaultLifecycle: string; + defaultOwner: string; + k8sToken?: string; + routeClient?: k8s.CustomObjectsApi; + coreClient?: k8s.CoreV1Api; + informer?: k8s.Informer & k8s.ObjectCache; +} + +// Result type for loopOverKFMR +export interface LoopOverKFMRResult { + registeredModels: RegisteredModel[]; + modelVersionsMap: Map; + modelArtifactsMap: Map>; +} + +// b GGM TODO so I could not get the @redhat-ai-dev/model-catalog-types node module dependency to reconcile, even though +// it does for that entity provider, so duplicating for now +/** + * Schema for defining AI models and model servers, for conversion to Backstage catalog + * entities + */ +export interface ModelCatalog { + /** + * An array of AI models to be imported into the Backstage catalog + */ + models: Model[]; + /** + * A deployed model server running one or more models, exposed over an API + */ + modelServer?: ModelServer; +} + +/** + * A deployed model server running one or more models, exposed over an API + * + * Schema for defining AI model servers, for conversion to Backstage catalog entities + */ +export interface ModelServer { + /** + * Annotations relating to the model server, in key-value pair format + */ + annotations?: { [key: string]: string }; + /** + * The API metadata associated with the model server + */ + API?: API; + /** + * Whether or not the model server requires authentication to access + */ + authentication?: boolean; + /** + * A description of the model server and what it's for + */ + description: string; + /** + * The URL for the model server's homepage, if present + */ + homepageURL?: string; + /** + * The lifecycle state of the model server API + */ + lifecycle: string; + /** + * The name of the model server + */ + name: string; + /** + * The Backstage user that will be responsible for the model server + */ + owner: string; + /** + * Descriptive tags for the model server + */ + tags?: string[]; + /** + * How to use and interact with the model server + */ + usage?: string; +} + +/** + * The API metadata associated with the model server + * + * Schema for defining the API exposed by model servers, for conversion to Backstage catalog + * entities + */ +export interface API { + /** + * Annotations relating to the model, in key-value pair format + */ + annotations?: { [key: string]: string }; + /** + * A link to the schema used by the model server API + */ + spec: string; + /** + * Descriptive tags for the model server's API + */ + tags?: string[]; + /** + * The type of API that the model server exposes + */ + type: Type; + /** + * The URL that the model server's REST API is exposed over, how the model(s) are interacted + * with + */ + url: string; +} + +/** + * The type of API that the model server exposes + */ +export enum Type { + Asyncapi = 'asyncapi', + Graphql = 'graphql', + Grpc = 'grpc', + Openapi = 'openapi', +} + +/** + * An AI model to be imported into the Backstage catalog + * + * Schema for defining AI models conversion to Backstage catalog entities + */ +export interface Model { + /** + * Annotations relating to the model, in key-value pair format + */ + annotations?: { [key: string]: string }; + /** + * A URL to access the model's artifacts, e.g. on HuggingFace, Minio, Github, etc + */ + artifactLocationURL?: string; + /** + * A description of the model and what it's for + */ + description: string; + /** + * Any ethical considerations for the model + */ + ethics?: string; + /** + * The URL pointing to any specific documentation on how to use the model on the model server + */ + howToUseURL?: string; + /** + * The license used by the model (e.g. Apache-2). + */ + license?: string; + /** + * The lifecycle state of the model server API + */ + lifecycle: string; + /** + * The name of the model + */ + name: string; + /** + * The Backstage user that will be responsible for the model + */ + owner: string; + /** + * Support information for the model / where to open issues + */ + support?: string; + /** + * Descriptive tags for the model + */ + tags?: string[]; + /** + * Information on how the model was trained + */ + training?: string; + /** + * How to use and interact with the model + */ + usage?: string; +} + +// DiscoveryResponse type matching Go DicoveryResponse (server.go line 158-160) +export interface DiscoveryResponse { + uris: string[]; +} + +// e GGM diff --git a/workspaces/ai-integrations/yarn.lock b/workspaces/ai-integrations/yarn.lock index 546de898c8..007d8434c6 100644 --- a/workspaces/ai-integrations/yarn.lock +++ b/workspaces/ai-integrations/yarn.lock @@ -55,6 +55,16 @@ __metadata: languageName: node linkType: hard +"@ampproject/remapping@npm:^2.2.0": + version: 2.3.0 + resolution: "@ampproject/remapping@npm:2.3.0" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/81d63cca5443e0f0c72ae18b544cc28c7c0ec2cea46e7cb888bb0e0f411a1191d0d6b7af798d54e30777d8d1488b2ec0732aac2be342d3d7d3ffd271c6f489ed + languageName: node + linkType: hard + "@apidevtools/json-schema-ref-parser@npm:11.7.2": version: 11.7.2 resolution: "@apidevtools/json-schema-ref-parser@npm:11.7.2" @@ -1714,7 +1724,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.26.2, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.8.3": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.26.2, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.8.3": version: 7.29.0 resolution: "@babel/code-frame@npm:7.29.0" dependencies: @@ -1725,7 +1735,37 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.26.10": +"@babel/compat-data@npm:^7.26.5": + version: 7.26.8 + resolution: "@babel/compat-data@npm:7.26.8" + checksum: 10c0/66408a0388c3457fff1c2f6c3a061278dd7b3d2f0455ea29bb7b187fa52c60ae8b4054b3c0a184e21e45f0eaac63cf390737bc7504d1f4a088a6e7f652c068ca + languageName: node + linkType: hard + +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9": + version: 7.26.10 + resolution: "@babel/core@npm:7.26.10" + dependencies: + "@ampproject/remapping": "npm:^2.2.0" + "@babel/code-frame": "npm:^7.26.2" + "@babel/generator": "npm:^7.26.10" + "@babel/helper-compilation-targets": "npm:^7.26.5" + "@babel/helper-module-transforms": "npm:^7.26.0" + "@babel/helpers": "npm:^7.26.10" + "@babel/parser": "npm:^7.26.10" + "@babel/template": "npm:^7.26.9" + "@babel/traverse": "npm:^7.26.10" + "@babel/types": "npm:^7.26.10" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 10c0/e046e0e988ab53841b512ee9d263ca409f6c46e2a999fe53024688b92db394346fa3aeae5ea0866331f62133982eee05a675d22922a4603c3f603aa09a581d62 + languageName: node + linkType: hard + +"@babel/generator@npm:^7.26.10, @babel/generator@npm:^7.7.2": version: 7.26.10 resolution: "@babel/generator@npm:7.26.10" dependencies: @@ -1738,7 +1778,20 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.16.7": +"@babel/helper-compilation-targets@npm:^7.26.5": + version: 7.26.5 + resolution: "@babel/helper-compilation-targets@npm:7.26.5" + dependencies: + "@babel/compat-data": "npm:^7.26.5" + "@babel/helper-validator-option": "npm:^7.25.9" + browserslist: "npm:^4.24.0" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: 10c0/9da5c77e5722f1a2fcb3e893049a01d414124522bbf51323bb1a0c9dcd326f15279836450fc36f83c9e8a846f3c40e88be032ed939c5a9840922bed6073edfb4 + languageName: node + linkType: hard + +"@babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-module-imports@npm:7.25.9" dependencies: @@ -1748,6 +1801,26 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/helper-module-transforms@npm:7.26.0" + dependencies: + "@babel/helper-module-imports": "npm:^7.25.9" + "@babel/helper-validator-identifier": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/ee111b68a5933481d76633dad9cdab30c41df4479f0e5e1cc4756dc9447c1afd2c9473b5ba006362e35b17f4ebddd5fca090233bef8dfc84dca9d9127e56ec3a + languageName: node + linkType: hard + +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.25.9, @babel/helper-plugin-utils@npm:^7.8.0": + version: 7.26.5 + resolution: "@babel/helper-plugin-utils@npm:7.26.5" + checksum: 10c0/cdaba71d4b891aa6a8dfbe5bac2f94effb13e5fa4c2c487667fdbaa04eae059b78b28d85a885071f45f7205aeb56d16759e1bed9c118b94b16e4720ef1ab0f65 + languageName: node + linkType: hard + "@babel/helper-string-parser@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-string-parser@npm:7.29.7" @@ -1762,6 +1835,23 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-option@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-option@npm:7.25.9" + checksum: 10c0/27fb195d14c7dcb07f14e58fe77c44eea19a6a40a74472ec05c441478fa0bb49fa1c32b2d64be7a38870ee48ef6601bdebe98d512f0253aea0b39756c4014f3e + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.26.10": + version: 7.26.10 + resolution: "@babel/helpers@npm:7.26.10" + dependencies: + "@babel/template": "npm:^7.26.9" + "@babel/types": "npm:^7.26.10" + checksum: 10c0/f99e1836bcffce96db43158518bb4a24cf266820021f6461092a776cba2dc01d9fc8b1b90979d7643c5c2ab7facc438149064463a52dd528b21c6ab32509784f + languageName: node + linkType: hard + "@babel/highlight@npm:^7.0.0": version: 7.25.9 resolution: "@babel/highlight@npm:7.25.9" @@ -1774,7 +1864,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.20.15, @babel/parser@npm:^7.26.10, @babel/parser@npm:^7.26.9": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.15, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.26.10, @babel/parser@npm:^7.26.9": version: 7.29.7 resolution: "@babel/parser@npm:7.29.7" dependencies: @@ -1785,6 +1875,193 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-async-generators@npm:^7.8.4": + version: 7.8.4 + resolution: "@babel/plugin-syntax-async-generators@npm:7.8.4" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/d13efb282838481348c71073b6be6245b35d4f2f964a8f71e4174f235009f929ef7613df25f8d2338e2d3e44bc4265a9f8638c6aaa136d7a61fe95985f9725c8 + languageName: node + linkType: hard + +"@babel/plugin-syntax-bigint@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-bigint@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/686891b81af2bc74c39013655da368a480f17dd237bf9fbc32048e5865cb706d5a8f65438030da535b332b1d6b22feba336da8fa931f663b6b34e13147d12dde + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-properties@npm:^7.12.13": + version: 7.12.13 + resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.12.13" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/95168fa186416195280b1264fb18afcdcdcea780b3515537b766cb90de6ce042d42dd6a204a39002f794ae5845b02afb0fd4861a3308a861204a55e68310a120 + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-static-block@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/4464bf9115f4a2d02ce1454411baf9cfb665af1da53709c5c56953e5e2913745b0fcce82982a00463d6facbdd93445c691024e310b91431a1e2f024b158f6371 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-attributes@npm:^7.24.7": + version: 7.26.0 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.26.0" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.9" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/e594c185b12bfe0bbe7ca78dfeebe870e6d569a12128cac86f3164a075fe0ff70e25ddbd97fd0782906b91f65560c9dc6957716b7b4a68aba2516c9b7455e352 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-meta@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.10.4" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/0b08b5e4c3128523d8e346f8cfc86824f0da2697b1be12d71af50a31aff7a56ceb873ed28779121051475010c28d6146a6bfea8518b150b71eeb4e46190172ee + languageName: node + linkType: hard + +"@babel/plugin-syntax-json-strings@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-json-strings@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/e98f31b2ec406c57757d115aac81d0336e8434101c224edd9a5c93cefa53faf63eacc69f3138960c8b25401315af03df37f68d316c151c4b933136716ed6906e + languageName: node + linkType: hard + +"@babel/plugin-syntax-jsx@npm:^7.7.2": + version: 7.25.9 + resolution: "@babel/plugin-syntax-jsx@npm:7.25.9" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.9" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/d56597aff4df39d3decda50193b6dfbe596ca53f437ff2934622ce19a743bf7f43492d3fb3308b0289f5cee2b825d99ceb56526a2b9e7b68bf04901546c5618c + languageName: node + linkType: hard + +"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.10.4" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/2594cfbe29411ad5bc2ad4058de7b2f6a8c5b86eda525a993959438615479e59c012c14aec979e538d60a584a1a799b60d1b8942c3b18468cb9d99b8fd34cd0b + languageName: node + linkType: hard + +"@babel/plugin-syntax-nullish-coalescing-operator@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-nullish-coalescing-operator@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/2024fbb1162899094cfc81152449b12bd0cc7053c6d4bda8ac2852545c87d0a851b1b72ed9560673cbf3ef6248257262c3c04aabf73117215c1b9cc7dd2542ce + languageName: node + linkType: hard + +"@babel/plugin-syntax-numeric-separator@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.10.4" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/c55a82b3113480942c6aa2fcbe976ff9caa74b7b1109ff4369641dfbc88d1da348aceb3c31b6ed311c84d1e7c479440b961906c735d0ab494f688bf2fd5b9bb9 + languageName: node + linkType: hard + +"@babel/plugin-syntax-object-rest-spread@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-object-rest-spread@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/ee1eab52ea6437e3101a0a7018b0da698545230015fc8ab129d292980ec6dff94d265e9e90070e8ae5fed42f08f1622c14c94552c77bcac784b37f503a82ff26 + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-catch-binding@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-catch-binding@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/27e2493ab67a8ea6d693af1287f7e9acec206d1213ff107a928e85e173741e1d594196f99fec50e9dde404b09164f39dec5864c767212154ffe1caa6af0bc5af + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-chaining@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-chaining@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/46edddf2faa6ebf94147b8e8540dfc60a5ab718e2de4d01b2c0bdf250a4d642c2bd47cbcbb739febcb2bf75514dbcefad3c52208787994b8d0f8822490f55e81 + languageName: node + linkType: hard + +"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/69822772561706c87f0a65bc92d0772cea74d6bc0911537904a676d5ff496a6d3ac4e05a166d8125fce4a16605bace141afc3611074e170a994e66e5397787f3 + languageName: node + linkType: hard + +"@babel/plugin-syntax-top-level-await@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/14bf6e65d5bc1231ffa9def5f0ef30b19b51c218fcecaa78cd1bdf7939dfdf23f90336080b7f5196916368e399934ce5d581492d8292b46a2fb569d8b2da106f + languageName: node + linkType: hard + +"@babel/plugin-syntax-typescript@npm:^7.7.2": + version: 7.25.9 + resolution: "@babel/plugin-syntax-typescript@npm:7.25.9" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.9" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/5192ebe11bd46aea68b7a60fd9555465c59af7e279e71126788e59121b86e00b505816685ab4782abe159232b0f73854e804b54449820b0d950b397ee158caa2 + languageName: node + linkType: hard + "@babel/runtime-corejs3@npm:^7.20.7, @babel/runtime-corejs3@npm:^7.22.15, @babel/runtime-corejs3@npm:^7.26.10, @babel/runtime-corejs3@npm:^7.27.1": version: 7.28.4 resolution: "@babel/runtime-corejs3@npm:7.28.4" @@ -1801,7 +2078,7 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.26.9": +"@babel/template@npm:^7.26.9, @babel/template@npm:^7.3.3": version: 7.26.9 resolution: "@babel/template@npm:7.26.9" dependencies: @@ -1812,7 +2089,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.25.9": +"@babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.26.10": version: 7.26.10 resolution: "@babel/traverse@npm:7.26.10" dependencies: @@ -1827,7 +2104,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.25.9, @babel/types@npm:^7.26.10, @babel/types@npm:^7.26.9, @babel/types@npm:^7.29.7": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.10, @babel/types@npm:^7.26.9, @babel/types@npm:^7.29.7, @babel/types@npm:^7.3.3": version: 7.29.7 resolution: "@babel/types@npm:7.29.7" dependencies: @@ -1861,7 +2138,7 @@ __metadata: languageName: node linkType: hard -"@backstage/backend-app-api@npm:^1.7.1": +"@backstage/backend-app-api@npm:^1.3.0, @backstage/backend-app-api@npm:^1.7.1": version: 1.7.1 resolution: "@backstage/backend-app-api@npm:1.7.1" dependencies: @@ -1873,6 +2150,90 @@ __metadata: languageName: node linkType: hard +"@backstage/backend-defaults@npm:^0.13.1": + version: 0.13.1 + resolution: "@backstage/backend-defaults@npm:0.13.1" + dependencies: + "@aws-sdk/abort-controller": "npm:^3.347.0" + "@aws-sdk/client-codecommit": "npm:^3.350.0" + "@aws-sdk/client-s3": "npm:^3.350.0" + "@aws-sdk/credential-providers": "npm:^3.350.0" + "@aws-sdk/types": "npm:^3.347.0" + "@azure/storage-blob": "npm:^12.5.0" + "@backstage/backend-app-api": "npm:^1.3.0" + "@backstage/backend-dev-utils": "npm:^0.1.5" + "@backstage/backend-plugin-api": "npm:^1.5.0" + "@backstage/cli-node": "npm:^0.2.15" + "@backstage/config": "npm:^1.3.6" + "@backstage/config-loader": "npm:^1.10.6" + "@backstage/errors": "npm:^1.2.7" + "@backstage/integration": "npm:^1.18.2" + "@backstage/integration-aws-node": "npm:^0.1.19" + "@backstage/plugin-auth-node": "npm:^0.6.9" + "@backstage/plugin-events-node": "npm:^0.4.17" + "@backstage/plugin-permission-node": "npm:^0.10.6" + "@backstage/types": "npm:^1.2.2" + "@google-cloud/storage": "npm:^7.0.0" + "@keyv/memcache": "npm:^2.0.1" + "@keyv/redis": "npm:^4.0.1" + "@keyv/valkey": "npm:^1.0.1" + "@manypkg/get-packages": "npm:^1.1.3" + "@octokit/rest": "npm:^19.0.3" + "@opentelemetry/api": "npm:^1.9.0" + "@types/cors": "npm:^2.8.6" + "@types/express": "npm:^4.17.6" + archiver: "npm:^7.0.0" + base64-stream: "npm:^1.0.0" + better-sqlite3: "npm:^12.0.0" + compression: "npm:^1.7.4" + concat-stream: "npm:^2.0.0" + cookie: "npm:^0.7.0" + cors: "npm:^2.8.5" + cron: "npm:^3.0.0" + express: "npm:^4.17.1" + express-promise-router: "npm:^4.1.0" + express-rate-limit: "npm:^7.5.0" + fs-extra: "npm:^11.2.0" + git-url-parse: "npm:^15.0.0" + helmet: "npm:^6.0.0" + infinispan: "npm:^0.12.0" + is-glob: "npm:^4.0.3" + jose: "npm:^5.0.0" + keyv: "npm:^5.2.1" + knex: "npm:^3.0.0" + lodash: "npm:^4.17.21" + logform: "npm:^2.3.2" + luxon: "npm:^3.0.0" + minimatch: "npm:^9.0.0" + mysql2: "npm:^3.0.0" + node-fetch: "npm:^2.7.0" + node-forge: "npm:^1.3.1" + p-limit: "npm:^3.1.0" + path-to-regexp: "npm:^8.0.0" + pg: "npm:^8.11.3" + pg-connection-string: "npm:^2.3.0" + pg-format: "npm:^1.0.4" + rate-limit-redis: "npm:^4.2.0" + raw-body: "npm:^2.4.1" + selfsigned: "npm:^2.0.0" + tar: "npm:^6.1.12" + triple-beam: "npm:^1.4.1" + uuid: "npm:^11.0.0" + winston: "npm:^3.2.1" + winston-transport: "npm:^4.5.0" + yauzl: "npm:^3.0.0" + yn: "npm:^4.0.0" + zod: "npm:^3.22.4" + zod-to-json-schema: "npm:^3.20.4" + peerDependencies: + "@google-cloud/cloud-sql-connector": ^1.4.0 + peerDependenciesMeta: + "@google-cloud/cloud-sql-connector": + optional: true + checksum: 10c0/65eccb6c089cebfec9721faac166717f0dc35679b21a3f84b0428f555c054d4d90ef43b10016a5933e60d574c39558905c0384f0b7566f93591249a5f386bded + languageName: node + linkType: hard + "@backstage/backend-defaults@npm:^0.17.3": version: 0.17.3 resolution: "@backstage/backend-defaults@npm:0.17.3" @@ -1962,7 +2323,7 @@ __metadata: languageName: node linkType: hard -"@backstage/backend-dev-utils@npm:^0.1.7": +"@backstage/backend-dev-utils@npm:^0.1.5, @backstage/backend-dev-utils@npm:^0.1.7": version: 0.1.7 resolution: "@backstage/backend-dev-utils@npm:0.1.7" checksum: 10c0/3a0f54a6303bf4815e8d2e1a7536d9f7ee8028a04dd796ca233261f3170f3c4343468841590a5b0faf60b0864eae028a6086bff4a674a8345e0de100b5550da2 @@ -1993,7 +2354,7 @@ __metadata: languageName: node linkType: hard -"@backstage/backend-plugin-api@npm:^1.9.2": +"@backstage/backend-plugin-api@npm:^1.5.0, @backstage/backend-plugin-api@npm:^1.6.2, @backstage/backend-plugin-api@npm:^1.9.2": version: 1.9.2 resolution: "@backstage/backend-plugin-api@npm:1.9.2" dependencies: @@ -2014,7 +2375,7 @@ __metadata: languageName: node linkType: hard -"@backstage/backend-test-utils@npm:^1.11.4": +"@backstage/backend-test-utils@npm:^1.10.0, @backstage/backend-test-utils@npm:^1.11.4": version: 1.11.4 resolution: "@backstage/backend-test-utils@npm:1.11.4" dependencies: @@ -2058,7 +2419,7 @@ __metadata: languageName: node linkType: hard -"@backstage/catalog-client@npm:^1.14.0, @backstage/catalog-client@npm:^1.15.0, @backstage/catalog-client@npm:^1.16.0": +"@backstage/catalog-client@npm:^1.12.1, @backstage/catalog-client@npm:^1.14.0, @backstage/catalog-client@npm:^1.15.0, @backstage/catalog-client@npm:^1.16.0, @backstage/catalog-client@npm:^1.9.1": version: 1.16.0 resolution: "@backstage/catalog-client@npm:1.16.0" dependencies: @@ -2073,7 +2434,7 @@ __metadata: languageName: node linkType: hard -"@backstage/catalog-model@npm:^1.7.7, @backstage/catalog-model@npm:^1.8.0, @backstage/catalog-model@npm:^1.9.0": +"@backstage/catalog-model@npm:^1.7.6, @backstage/catalog-model@npm:^1.7.7, @backstage/catalog-model@npm:^1.8.0, @backstage/catalog-model@npm:^1.9.0": version: 1.9.0 resolution: "@backstage/catalog-model@npm:1.9.0" dependencies: @@ -2087,6 +2448,18 @@ __metadata: languageName: node linkType: hard +"@backstage/cli-common@npm:^0.1.15, @backstage/cli-common@npm:^0.1.17": + version: 0.1.17 + resolution: "@backstage/cli-common@npm:0.1.17" + dependencies: + "@backstage/errors": "npm:^1.2.7" + cross-spawn: "npm:^7.0.3" + global-agent: "npm:^3.0.0" + undici: "npm:^7.2.3" + checksum: 10c0/85dc7c7ecfbd1dc47f83b6a320a09c83773f9a6357b4186bbf53541f1f58db6dc576ed7de84c1285e38fdbe9c02851b63f48dd4474845f36fe3f33dc4ecb28e9 + languageName: node + linkType: hard + "@backstage/cli-common@npm:^0.2.2": version: 0.2.2 resolution: "@backstage/cli-common@npm:0.2.2" @@ -2420,6 +2793,22 @@ __metadata: languageName: node linkType: hard +"@backstage/cli-node@npm:^0.2.15": + version: 0.2.17 + resolution: "@backstage/cli-node@npm:0.2.17" + dependencies: + "@backstage/cli-common": "npm:^0.1.17" + "@backstage/errors": "npm:^1.2.7" + "@backstage/types": "npm:^1.2.2" + "@manypkg/get-packages": "npm:^1.1.3" + "@yarnpkg/parsers": "npm:^3.0.0" + fs-extra: "npm:^11.2.0" + semver: "npm:^7.5.3" + zod: "npm:^3.25.76" + checksum: 10c0/0dc8dc104784a4a89695b02426330bfa1b25cca6327be48e4dccd5a38372209c804ff7b02862859ec0d3768fa440eba7baaa5d6f48c3d2cdad3878eaddad9f8a + languageName: node + linkType: hard + "@backstage/cli-node@npm:^0.3.3": version: 0.3.3 resolution: "@backstage/cli-node@npm:0.3.3" @@ -2451,6 +2840,147 @@ __metadata: languageName: node linkType: hard +"@backstage/cli@npm:^0.34.5": + version: 0.34.5 + resolution: "@backstage/cli@npm:0.34.5" + dependencies: + "@backstage/catalog-model": "npm:^1.7.6" + "@backstage/cli-common": "npm:^0.1.15" + "@backstage/cli-node": "npm:^0.2.15" + "@backstage/config": "npm:^1.3.6" + "@backstage/config-loader": "npm:^1.10.6" + "@backstage/errors": "npm:^1.2.7" + "@backstage/eslint-plugin": "npm:^0.2.0" + "@backstage/integration": "npm:^1.18.2" + "@backstage/release-manifests": "npm:^0.0.13" + "@backstage/types": "npm:^1.2.2" + "@manypkg/get-packages": "npm:^1.1.3" + "@module-federation/enhanced": "npm:^0.9.0" + "@octokit/request": "npm:^8.0.0" + "@rollup/plugin-commonjs": "npm:^26.0.0" + "@rollup/plugin-json": "npm:^6.0.0" + "@rollup/plugin-node-resolve": "npm:^15.0.0" + "@rollup/plugin-yaml": "npm:^4.0.0" + "@rspack/core": "npm:^1.4.11" + "@rspack/dev-server": "npm:^1.1.4" + "@rspack/plugin-react-refresh": "npm:^1.4.3" + "@spotify/eslint-config-base": "npm:^15.0.0" + "@spotify/eslint-config-react": "npm:^15.0.0" + "@spotify/eslint-config-typescript": "npm:^15.0.0" + "@swc/core": "npm:^1.3.46" + "@swc/helpers": "npm:^0.5.0" + "@swc/jest": "npm:^0.2.22" + "@types/jest": "npm:^29.5.11" + "@types/webpack-env": "npm:^1.15.2" + "@typescript-eslint/eslint-plugin": "npm:^8.17.0" + "@typescript-eslint/parser": "npm:^8.16.0" + "@yarnpkg/lockfile": "npm:^1.1.0" + "@yarnpkg/parsers": "npm:^3.0.0" + bfj: "npm:^8.0.0" + buffer: "npm:^6.0.3" + chalk: "npm:^4.0.0" + chokidar: "npm:^3.3.1" + commander: "npm:^12.0.0" + cross-fetch: "npm:^4.0.0" + cross-spawn: "npm:^7.0.3" + css-loader: "npm:^6.5.1" + ctrlc-windows: "npm:^2.1.0" + esbuild: "npm:^0.25.0" + eslint: "npm:^8.6.0" + eslint-config-prettier: "npm:^9.0.0" + eslint-formatter-friendly: "npm:^7.0.0" + eslint-plugin-deprecation: "npm:^3.0.0" + eslint-plugin-import: "npm:^2.31.0" + eslint-plugin-jest: "npm:^28.9.0" + eslint-plugin-jsx-a11y: "npm:^6.10.2" + eslint-plugin-react: "npm:^7.37.2" + eslint-plugin-react-hooks: "npm:^5.0.0" + eslint-plugin-unused-imports: "npm:^4.1.4" + eslint-rspack-plugin: "npm:^4.2.1" + express: "npm:^4.17.1" + fs-extra: "npm:^11.2.0" + git-url-parse: "npm:^15.0.0" + glob: "npm:^7.1.7" + global-agent: "npm:^3.0.0" + globby: "npm:^11.1.0" + handlebars: "npm:^4.7.3" + html-webpack-plugin: "npm:^5.6.3" + inquirer: "npm:^8.2.0" + jest: "npm:^29.7.0" + jest-cli: "npm:^29.7.0" + jest-css-modules: "npm:^2.1.0" + jest-environment-jsdom: "npm:^29.0.2" + jest-runtime: "npm:^29.0.2" + json-schema: "npm:^0.4.0" + lodash: "npm:^4.17.21" + minimatch: "npm:^9.0.0" + node-stdlib-browser: "npm:^1.3.1" + npm-packlist: "npm:^5.0.0" + ora: "npm:^5.3.0" + p-queue: "npm:^6.6.2" + pirates: "npm:^4.0.6" + postcss: "npm:^8.1.0" + process: "npm:^0.11.10" + raw-loader: "npm:^4.0.2" + react-dev-utils: "npm:^12.0.0-next.60" + react-refresh: "npm:^0.17.0" + recursive-readdir: "npm:^2.2.2" + replace-in-file: "npm:^7.1.0" + rollup: "npm:^4.27.3" + rollup-plugin-dts: "npm:^6.1.0" + rollup-plugin-esbuild: "npm:^6.1.1" + rollup-plugin-postcss: "npm:^4.0.0" + rollup-pluginutils: "npm:^2.8.2" + semver: "npm:^7.5.3" + style-loader: "npm:^3.3.1" + sucrase: "npm:^3.20.2" + swc-loader: "npm:^0.2.3" + tar: "npm:^6.1.12" + ts-checker-rspack-plugin: "npm:^1.1.5" + ts-morph: "npm:^24.0.0" + undici: "npm:^7.2.3" + util: "npm:^0.12.3" + yaml: "npm:^2.0.0" + yargs: "npm:^16.2.0" + yml-loader: "npm:^2.1.0" + yn: "npm:^4.0.0" + zod: "npm:^3.22.4" + zod-validation-error: "npm:^3.4.0" + peerDependencies: + "@module-federation/enhanced": ^0.9.0 + "@pmmmwh/react-refresh-webpack-plugin": ^0.5.7 + esbuild-loader: ^4.0.0 + eslint-webpack-plugin: ^4.2.0 + fork-ts-checker-webpack-plugin: ^9.0.0 + mini-css-extract-plugin: ^2.4.2 + terser-webpack-plugin: ^5.1.3 + webpack: ~5.96.0 + webpack-dev-server: ^5.0.0 + peerDependenciesMeta: + "@module-federation/enhanced": + optional: true + "@pmmmwh/react-refresh-webpack-plugin": + optional: true + esbuild-loader: + optional: true + eslint-webpack-plugin: + optional: true + fork-ts-checker-webpack-plugin: + optional: true + mini-css-extract-plugin: + optional: true + terser-webpack-plugin: + optional: true + webpack: + optional: true + webpack-dev-server: + optional: true + bin: + backstage-cli: bin/backstage-cli + checksum: 10c0/1ab82d24f1f09796f89c12056fd16b291c4be1304e58c564a368e5192c716afaaedf8b9cd1ec0752a4de385e2390f4cedb3701ed27f2755047e1b7743d67c91d + languageName: node + linkType: hard + "@backstage/cli@npm:^0.36.3": version: 0.36.3 resolution: "@backstage/cli@npm:0.36.3" @@ -2506,7 +3036,7 @@ __metadata: languageName: node linkType: hard -"@backstage/config-loader@npm:^1.10.12": +"@backstage/config-loader@npm:^1.10.12, @backstage/config-loader@npm:^1.10.6": version: 1.10.12 resolution: "@backstage/config-loader@npm:1.10.12" dependencies: @@ -2740,6 +3270,16 @@ __metadata: languageName: node linkType: hard +"@backstage/eslint-plugin@npm:^0.2.0": + version: 0.2.0 + resolution: "@backstage/eslint-plugin@npm:0.2.0" + dependencies: + "@manypkg/get-packages": "npm:^1.1.3" + minimatch: "npm:^9.0.0" + checksum: 10c0/7f57cd42629084b0363cf9adb37d33479fd540226a29705da623db9032890a6e67d1eb15b8076ea2fe3b502e36810ad819c93936406524e56e33801b561d6ff3 + languageName: node + linkType: hard + "@backstage/eslint-plugin@npm:^0.3.1": version: 0.3.1 resolution: "@backstage/eslint-plugin@npm:0.3.1" @@ -2832,6 +3372,21 @@ __metadata: languageName: node linkType: hard +"@backstage/integration-aws-node@npm:^0.1.19": + version: 0.1.19 + resolution: "@backstage/integration-aws-node@npm:0.1.19" + dependencies: + "@aws-sdk/client-sts": "npm:^3.350.0" + "@aws-sdk/credential-provider-node": "npm:^3.350.0" + "@aws-sdk/credential-providers": "npm:^3.350.0" + "@aws-sdk/types": "npm:^3.347.0" + "@aws-sdk/util-arn-parser": "npm:^3.310.0" + "@backstage/config": "npm:^1.3.6" + "@backstage/errors": "npm:^1.2.7" + checksum: 10c0/803ba256051c6a9f7e45ba199e6d219e99ce5fd0e6145ec3ad9ff18dc333c4b148aac7a8cc1a67ea48f0a5f7e461271949284d9c5101bd1b4f317043d5f3a87b + languageName: node + linkType: hard + "@backstage/integration-aws-node@npm:^0.2.0": version: 0.2.0 resolution: "@backstage/integration-aws-node@npm:0.2.0" @@ -2868,6 +3423,24 @@ __metadata: languageName: node linkType: hard +"@backstage/integration@npm:^1.18.2": + version: 1.19.2 + resolution: "@backstage/integration@npm:1.19.2" + dependencies: + "@azure/identity": "npm:^4.0.0" + "@azure/storage-blob": "npm:^12.5.0" + "@backstage/config": "npm:^1.3.6" + "@backstage/errors": "npm:^1.2.7" + "@octokit/auth-app": "npm:^4.0.0" + "@octokit/rest": "npm:^19.0.3" + cross-fetch: "npm:^4.0.0" + git-url-parse: "npm:^15.0.0" + lodash: "npm:^4.17.21" + luxon: "npm:^3.0.0" + checksum: 10c0/10c99c848368d6745dd38e906aaba1d5082aa35d53ef814ab97cf0a919f6a8be33e140dc7ee6365411d950e38b71913e8c008c1064ed4e5db9f01a004c8c6295 + languageName: node + linkType: hard + "@backstage/integration@npm:^2.0.3": version: 2.0.3 resolution: "@backstage/integration@npm:2.0.3" @@ -3058,6 +3631,29 @@ __metadata: languageName: node linkType: hard +"@backstage/plugin-auth-node@npm:^0.6.12, @backstage/plugin-auth-node@npm:^0.6.9": + version: 0.6.12 + resolution: "@backstage/plugin-auth-node@npm:0.6.12" + dependencies: + "@backstage/backend-plugin-api": "npm:^1.6.2" + "@backstage/catalog-client": "npm:^1.12.1" + "@backstage/catalog-model": "npm:^1.7.6" + "@backstage/config": "npm:^1.3.6" + "@backstage/errors": "npm:^1.2.7" + "@backstage/types": "npm:^1.2.2" + "@types/express": "npm:^4.17.6" + "@types/passport": "npm:^1.0.3" + express: "npm:^4.22.0" + jose: "npm:^5.0.0" + lodash: "npm:^4.17.21" + passport: "npm:^0.7.0" + zod: "npm:^3.25.76" + zod-to-json-schema: "npm:^3.25.1" + zod-validation-error: "npm:^4.0.2" + checksum: 10c0/8bc9b9e09dee366ff9805281ef57c381029a617e9cbe32c493076c8969727fc0c0887abd6aefac13e10d60deefc7b604b7e94821f184b1ddbb7cb32f6b5c21d0 + languageName: node + linkType: hard + "@backstage/plugin-auth-node@npm:^0.7.2": version: 0.7.2 resolution: "@backstage/plugin-auth-node@npm:0.7.2" @@ -3179,7 +3775,7 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-catalog-common@npm:^1.1.10, @backstage/plugin-catalog-common@npm:^1.1.8, @backstage/plugin-catalog-common@npm:^1.1.9": +"@backstage/plugin-catalog-common@npm:^1.1.10, @backstage/plugin-catalog-common@npm:^1.1.7, @backstage/plugin-catalog-common@npm:^1.1.8, @backstage/plugin-catalog-common@npm:^1.1.9": version: 1.1.10 resolution: "@backstage/plugin-catalog-common@npm:1.1.10" dependencies: @@ -3262,6 +3858,24 @@ __metadata: languageName: node linkType: hard +"@backstage/plugin-catalog-node@npm:^1.20.0": + version: 1.20.0 + resolution: "@backstage/plugin-catalog-node@npm:1.20.0" + dependencies: + "@backstage/backend-plugin-api": "npm:^1.5.0" + "@backstage/catalog-client": "npm:^1.12.1" + "@backstage/catalog-model": "npm:^1.7.6" + "@backstage/errors": "npm:^1.2.7" + "@backstage/plugin-catalog-common": "npm:^1.1.7" + "@backstage/plugin-permission-common": "npm:^0.9.3" + "@backstage/plugin-permission-node": "npm:^0.10.6" + "@backstage/types": "npm:^1.2.2" + lodash: "npm:^4.17.21" + yaml: "npm:^2.0.0" + checksum: 10c0/df33a1ecaf6de60109606030114e482b4c1b60c96cc2cfd11c9c7dabd47e8978c1b4c4df3f3cb492537bc0016ba55436c1cd69a40c7665c3c17b12e7aac5c007 + languageName: node + linkType: hard + "@backstage/plugin-catalog-node@npm:^2.2.2": version: 2.2.2 resolution: "@backstage/plugin-catalog-node@npm:2.2.2" @@ -3380,7 +3994,7 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-events-node@npm:^0.4.23": +"@backstage/plugin-events-node@npm:^0.4.17, @backstage/plugin-events-node@npm:^0.4.23": version: 0.4.23 resolution: "@backstage/plugin-events-node@npm:0.4.23" dependencies: @@ -3628,7 +4242,7 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-permission-common@npm:^0.9.7, @backstage/plugin-permission-common@npm:^0.9.8, @backstage/plugin-permission-common@npm:^0.9.9": +"@backstage/plugin-permission-common@npm:^0.9.3, @backstage/plugin-permission-common@npm:^0.9.5, @backstage/plugin-permission-common@npm:^0.9.7, @backstage/plugin-permission-common@npm:^0.9.8, @backstage/plugin-permission-common@npm:^0.9.9": version: 0.9.9 resolution: "@backstage/plugin-permission-common@npm:0.9.9" dependencies: @@ -3642,6 +4256,24 @@ __metadata: languageName: node linkType: hard +"@backstage/plugin-permission-node@npm:^0.10.6": + version: 0.10.9 + resolution: "@backstage/plugin-permission-node@npm:0.10.9" + dependencies: + "@backstage/backend-plugin-api": "npm:^1.6.2" + "@backstage/config": "npm:^1.3.6" + "@backstage/errors": "npm:^1.2.7" + "@backstage/plugin-auth-node": "npm:^0.6.12" + "@backstage/plugin-permission-common": "npm:^0.9.5" + "@types/express": "npm:^4.17.6" + express: "npm:^4.22.0" + express-promise-router: "npm:^4.1.0" + zod: "npm:^3.25.76" + zod-to-json-schema: "npm:^3.25.1" + checksum: 10c0/c1c0b8245c8877b2720849676c0dfeb3452caeb52ec2f9b1ef122013cf36f58dbce7ea249bb68204aea83aa757435b5f6d730c434e737478b11b0d38191ed20f + languageName: node + linkType: hard + "@backstage/plugin-permission-node@npm:^0.11.1": version: 0.11.1 resolution: "@backstage/plugin-permission-node@npm:0.11.1" @@ -4606,6 +5238,13 @@ __metadata: languageName: node linkType: hard +"@bcoe/v8-coverage@npm:^0.2.3": + version: 0.2.3 + resolution: "@bcoe/v8-coverage@npm:0.2.3" + checksum: 10c0/6b80ae4cb3db53f486da2dc63b6e190a74c8c3cca16bb2733f234a0b6a9382b09b146488ae08e2b22cf00f6c83e20f3e040a2f7894f05c045c946d6a090b1d52 + languageName: node + linkType: hard + "@braintree/sanitize-url@npm:^7.1.2": version: 7.1.2 resolution: "@braintree/sanitize-url@npm:7.1.2" @@ -5273,6 +5912,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/aix-ppc64@npm:0.25.1" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/aix-ppc64@npm:0.27.7" @@ -5280,6 +5926,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/android-arm64@npm:0.25.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/android-arm64@npm:0.27.7" @@ -5287,6 +5940,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/android-arm@npm:0.25.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/android-arm@npm:0.27.7" @@ -5294,6 +5954,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/android-x64@npm:0.25.1" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/android-x64@npm:0.27.7" @@ -5301,6 +5968,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/darwin-arm64@npm:0.25.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/darwin-arm64@npm:0.27.7" @@ -5308,6 +5982,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/darwin-x64@npm:0.25.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/darwin-x64@npm:0.27.7" @@ -5315,6 +5996,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/freebsd-arm64@npm:0.25.1" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/freebsd-arm64@npm:0.27.7" @@ -5322,6 +6010,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/freebsd-x64@npm:0.25.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/freebsd-x64@npm:0.27.7" @@ -5329,6 +6024,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/linux-arm64@npm:0.25.1" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/linux-arm64@npm:0.27.7" @@ -5336,6 +6038,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/linux-arm@npm:0.25.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/linux-arm@npm:0.27.7" @@ -5343,6 +6052,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/linux-ia32@npm:0.25.1" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/linux-ia32@npm:0.27.7" @@ -5350,6 +6066,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/linux-loong64@npm:0.25.1" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/linux-loong64@npm:0.27.7" @@ -5357,6 +6080,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/linux-mips64el@npm:0.25.1" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/linux-mips64el@npm:0.27.7" @@ -5364,6 +6094,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/linux-ppc64@npm:0.25.1" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/linux-ppc64@npm:0.27.7" @@ -5371,6 +6108,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/linux-riscv64@npm:0.25.1" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/linux-riscv64@npm:0.27.7" @@ -5378,6 +6122,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/linux-s390x@npm:0.25.1" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/linux-s390x@npm:0.27.7" @@ -5385,6 +6136,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/linux-x64@npm:0.25.1" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/linux-x64@npm:0.27.7" @@ -5392,6 +6150,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-arm64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/netbsd-arm64@npm:0.25.1" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/netbsd-arm64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/netbsd-arm64@npm:0.27.7" @@ -5399,6 +6164,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/netbsd-x64@npm:0.25.1" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/netbsd-x64@npm:0.27.7" @@ -5406,6 +6178,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-arm64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/openbsd-arm64@npm:0.25.1" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/openbsd-arm64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/openbsd-arm64@npm:0.27.7" @@ -5413,6 +6192,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/openbsd-x64@npm:0.25.1" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/openbsd-x64@npm:0.27.7" @@ -5427,6 +6213,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/sunos-x64@npm:0.25.1" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/sunos-x64@npm:0.27.7" @@ -5434,6 +6227,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/win32-arm64@npm:0.25.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/win32-arm64@npm:0.27.7" @@ -5441,6 +6241,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/win32-ia32@npm:0.25.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/win32-ia32@npm:0.27.7" @@ -5448,6 +6255,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.25.1": + version: 0.25.1 + resolution: "@esbuild/win32-x64@npm:0.25.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/win32-x64@npm:0.27.7" @@ -5497,6 +6311,13 @@ __metadata: languageName: node linkType: hard +"@fastify/busboy@npm:^2.0.0": + version: 2.1.1 + resolution: "@fastify/busboy@npm:2.1.1" + checksum: 10c0/6f8027a8cba7f8f7b736718b013f5a38c0476eea67034c94a0d3c375e2b114366ad4419e6a6fa7ffc2ef9c6d3e0435d76dd584a7a1cbac23962fda7650b579e3 + languageName: node + linkType: hard + "@floating-ui/core@npm:^1.7.3": version: 1.7.3 resolution: "@floating-ui/core@npm:1.7.3" @@ -5993,6 +6814,26 @@ __metadata: languageName: node linkType: hard +"@istanbuljs/load-nyc-config@npm:^1.0.0": + version: 1.1.0 + resolution: "@istanbuljs/load-nyc-config@npm:1.1.0" + dependencies: + camelcase: "npm:^5.3.1" + find-up: "npm:^4.1.0" + get-package-type: "npm:^0.1.0" + js-yaml: "npm:^3.13.1" + resolve-from: "npm:^5.0.0" + checksum: 10c0/dd2a8b094887da5a1a2339543a4933d06db2e63cbbc2e288eb6431bd832065df0c099d091b6a67436e71b7d6bf85f01ce7c15f9253b4cbebcc3b9a496165ba42 + languageName: node + linkType: hard + +"@istanbuljs/schema@npm:^0.1.2, @istanbuljs/schema@npm:^0.1.3": + version: 0.1.3 + resolution: "@istanbuljs/schema@npm:0.1.3" + checksum: 10c0/61c5286771676c9ca3eb2bd8a7310a9c063fb6e0e9712225c8471c582d157392c88f5353581c8c9adbe0dff98892317d2fdfc56c3499aa42e0194405206a963a + languageName: node + linkType: hard + "@jest-mock/express@npm:^2.0.1": version: 2.1.0 resolution: "@jest-mock/express@npm:2.1.0" @@ -6002,6 +6843,61 @@ __metadata: languageName: node linkType: hard +"@jest/console@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/console@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + slash: "npm:^3.0.0" + checksum: 10c0/7be408781d0a6f657e969cbec13b540c329671819c2f57acfad0dae9dbfe2c9be859f38fe99b35dba9ff1536937dc6ddc69fdcd2794812fa3c647a1619797f6c + languageName: node + linkType: hard + +"@jest/core@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/core@npm:29.7.0" + dependencies: + "@jest/console": "npm:^29.7.0" + "@jest/reporters": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + ansi-escapes: "npm:^4.2.1" + chalk: "npm:^4.0.0" + ci-info: "npm:^3.2.0" + exit: "npm:^0.1.2" + graceful-fs: "npm:^4.2.9" + jest-changed-files: "npm:^29.7.0" + jest-config: "npm:^29.7.0" + jest-haste-map: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-resolve-dependencies: "npm:^29.7.0" + jest-runner: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + jest-watcher: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + pretty-format: "npm:^29.7.0" + slash: "npm:^3.0.0" + strip-ansi: "npm:^6.0.0" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 10c0/934f7bf73190f029ac0f96662c85cd276ec460d407baf6b0dbaec2872e157db4d55a7ee0b1c43b18874602f662b37cb973dda469a4e6d88b4e4845b521adeeb2 + languageName: node + linkType: hard + "@jest/create-cache-key-function@npm:^30.0.0": version: 30.3.0 resolution: "@jest/create-cache-key-function@npm:30.3.0" @@ -6011,6 +6907,63 @@ __metadata: languageName: node linkType: hard +"@jest/environment@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/environment@npm:29.7.0" + dependencies: + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + jest-mock: "npm:^29.7.0" + checksum: 10c0/c7b1b40c618f8baf4d00609022d2afa086d9c6acc706f303a70bb4b67275868f620ad2e1a9efc5edd418906157337cce50589a627a6400bbdf117d351b91ef86 + languageName: node + linkType: hard + +"@jest/expect-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect-utils@npm:29.7.0" + dependencies: + jest-get-type: "npm:^29.6.3" + checksum: 10c0/60b79d23a5358dc50d9510d726443316253ecda3a7fb8072e1526b3e0d3b14f066ee112db95699b7a43ad3f0b61b750c72e28a5a1cac361d7a2bb34747fa938a + languageName: node + linkType: hard + +"@jest/expect@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect@npm:29.7.0" + dependencies: + expect: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + checksum: 10c0/b41f193fb697d3ced134349250aed6ccea075e48c4f803159db102b826a4e473397c68c31118259868fd69a5cba70e97e1c26d2c2ff716ca39dc73a2ccec037e + languageName: node + linkType: hard + +"@jest/fake-timers@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/fake-timers@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + "@sinonjs/fake-timers": "npm:^10.0.2" + "@types/node": "npm:*" + jest-message-util: "npm:^29.7.0" + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 10c0/cf0a8bcda801b28dc2e2b2ba36302200ee8104a45ad7a21e6c234148932f826cb3bc57c8df3b7b815aeea0861d7b6ca6f0d4778f93b9219398ef28749e03595c + languageName: node + linkType: hard + +"@jest/globals@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/globals@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/expect": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + jest-mock: "npm:^29.7.0" + checksum: 10c0/a385c99396878fe6e4460c43bd7bb0a5cc52befb462cc6e7f2a3810f9e7bcce7cdeb51908fd530391ee452dc856c98baa2c5f5fa8a5b30b071d31ef7f6955cea + languageName: node + linkType: hard + "@jest/pattern@npm:30.0.1": version: 30.0.1 resolution: "@jest/pattern@npm:30.0.1" @@ -6021,6 +6974,43 @@ __metadata: languageName: node linkType: hard +"@jest/reporters@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/reporters@npm:29.7.0" + dependencies: + "@bcoe/v8-coverage": "npm:^0.2.3" + "@jest/console": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@jridgewell/trace-mapping": "npm:^0.3.18" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + collect-v8-coverage: "npm:^1.0.0" + exit: "npm:^0.1.2" + glob: "npm:^7.1.3" + graceful-fs: "npm:^4.2.9" + istanbul-lib-coverage: "npm:^3.0.0" + istanbul-lib-instrument: "npm:^6.0.0" + istanbul-lib-report: "npm:^3.0.0" + istanbul-lib-source-maps: "npm:^4.0.0" + istanbul-reports: "npm:^3.1.3" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" + slash: "npm:^3.0.0" + string-length: "npm:^4.0.1" + strip-ansi: "npm:^6.0.0" + v8-to-istanbul: "npm:^9.0.1" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 10c0/a754402a799541c6e5aff2c8160562525e2a47e7d568f01ebfc4da66522de39cbb809bbb0a841c7052e4270d79214e70aec3c169e4eae42a03bc1a8a20cb9fa2 + languageName: node + linkType: hard + "@jest/schemas@npm:30.0.5": version: 30.0.5 resolution: "@jest/schemas@npm:30.0.5" @@ -6039,6 +7029,64 @@ __metadata: languageName: node linkType: hard +"@jest/source-map@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/source-map@npm:29.6.3" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.18" + callsites: "npm:^3.0.0" + graceful-fs: "npm:^4.2.9" + checksum: 10c0/a2f177081830a2e8ad3f2e29e20b63bd40bade294880b595acf2fc09ec74b6a9dd98f126a2baa2bf4941acd89b13a4ade5351b3885c224107083a0059b60a219 + languageName: node + linkType: hard + +"@jest/test-result@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-result@npm:29.7.0" + dependencies: + "@jest/console": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/istanbul-lib-coverage": "npm:^2.0.0" + collect-v8-coverage: "npm:^1.0.0" + checksum: 10c0/7de54090e54a674ca173470b55dc1afdee994f2d70d185c80236003efd3fa2b753fff51ffcdda8e2890244c411fd2267529d42c4a50a8303755041ee493e6a04 + languageName: node + linkType: hard + +"@jest/test-sequencer@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-sequencer@npm:29.7.0" + dependencies: + "@jest/test-result": "npm:^29.7.0" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" + slash: "npm:^3.0.0" + checksum: 10c0/593a8c4272797bb5628984486080cbf57aed09c7cfdc0a634e8c06c38c6bef329c46c0016e84555ee55d1cd1f381518cf1890990ff845524c1123720c8c1481b + languageName: node + linkType: hard + +"@jest/transform@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/transform@npm:29.7.0" + dependencies: + "@babel/core": "npm:^7.11.6" + "@jest/types": "npm:^29.6.3" + "@jridgewell/trace-mapping": "npm:^0.3.18" + babel-plugin-istanbul: "npm:^6.1.1" + chalk: "npm:^4.0.0" + convert-source-map: "npm:^2.0.0" + fast-json-stable-stringify: "npm:^2.1.0" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-util: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + pirates: "npm:^4.0.4" + slash: "npm:^3.0.0" + write-file-atomic: "npm:^4.0.2" + checksum: 10c0/7f4a7f73dcf45dfdf280c7aa283cbac7b6e5a904813c3a93ead7e55873761fc20d5c4f0191d2019004fac6f55f061c82eb3249c2901164ad80e362e7a7ede5a6 + languageName: node + linkType: hard + "@jest/types@npm:30.3.0": version: 30.3.0 resolution: "@jest/types@npm:30.3.0" @@ -6120,7 +7168,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" dependencies: @@ -6359,6 +7407,32 @@ __metadata: languageName: node linkType: hard +"@kubernetes/client-node@npm:^0.20.0": + version: 0.20.0 + resolution: "@kubernetes/client-node@npm:0.20.0" + dependencies: + "@types/js-yaml": "npm:^4.0.1" + "@types/node": "npm:^20.1.1" + "@types/request": "npm:^2.47.1" + "@types/ws": "npm:^8.5.3" + byline: "npm:^5.0.0" + isomorphic-ws: "npm:^5.0.0" + js-yaml: "npm:^4.1.0" + jsonpath-plus: "npm:^7.2.0" + openid-client: "npm:^5.3.0" + request: "npm:^2.88.0" + rfc4648: "npm:^1.3.0" + stream-buffers: "npm:^3.0.2" + tar: "npm:^6.1.11" + tslib: "npm:^2.4.1" + ws: "npm:^8.11.0" + dependenciesMeta: + openid-client: + optional: true + checksum: 10c0/d7c542fd67ae56946cf5ffa6ed7d255557ba53e90eb653b0109ecf0b91388dbe663aaeaa3b7ea33b3d942ab631afea2e470a31b3cfb81301f5836b37681ba608 + languageName: node + linkType: hard + "@kwsites/file-exists@npm:^1.1.1": version: 1.1.1 resolution: "@kwsites/file-exists@npm:1.1.1" @@ -6703,6 +7777,17 @@ __metadata: languageName: node linkType: hard +"@module-federation/bridge-react-webpack-plugin@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/bridge-react-webpack-plugin@npm:0.9.1" + dependencies: + "@module-federation/sdk": "npm:0.9.1" + "@types/semver": "npm:7.5.8" + semver: "npm:7.6.3" + checksum: 10c0/c930bb23b04c42de45d1973200e0e2133f4c234fad6ffa36e7cc48dcb52070b522bac202ff9e6bbe85e572b8077395b0526c4ce58681a7d2caf2c2ca98115a3d + languageName: node + linkType: hard + "@module-federation/bridge-react-webpack-plugin@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/bridge-react-webpack-plugin@npm:2.6.0" @@ -6728,6 +7813,50 @@ __metadata: languageName: node linkType: hard +"@module-federation/data-prefetch@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/data-prefetch@npm:0.9.1" + dependencies: + "@module-federation/runtime": "npm:0.9.1" + "@module-federation/sdk": "npm:0.9.1" + fs-extra: "npm:9.1.0" + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 10c0/5242b8583c4f5278c71f138e40695d0d54e0e6437f6b9fcb83e531bb26d6367ed814bb4ae734f3563a805948904d1e1b7aed037caf8ab65bcbcfd7aa9375a9b8 + languageName: node + linkType: hard + +"@module-federation/dts-plugin@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/dts-plugin@npm:0.9.1" + dependencies: + "@module-federation/error-codes": "npm:0.9.1" + "@module-federation/managers": "npm:0.9.1" + "@module-federation/sdk": "npm:0.9.1" + "@module-federation/third-party-dts-extractor": "npm:0.9.1" + adm-zip: "npm:^0.5.10" + ansi-colors: "npm:^4.1.3" + axios: "npm:^1.7.4" + chalk: "npm:3.0.0" + fs-extra: "npm:9.1.0" + isomorphic-ws: "npm:5.0.0" + koa: "npm:2.15.4" + lodash.clonedeepwith: "npm:4.5.0" + log4js: "npm:6.9.1" + node-schedule: "npm:2.1.1" + rambda: "npm:^9.1.0" + ws: "npm:8.18.0" + peerDependencies: + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: ">=1.0.24" + peerDependenciesMeta: + vue-tsc: + optional: true + checksum: 10c0/208d8e7176d486d7b146027b26b706eeb6d231ad0e4806adf2aa5293c9d5dfbace5c98eb52f6c151e29ff9cb789eb0344445239f1739c23a4d0102393be741c4 + languageName: node + linkType: hard + "@module-federation/dts-plugin@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/dts-plugin@npm:2.6.0" @@ -6752,6 +7881,37 @@ __metadata: languageName: node linkType: hard +"@module-federation/enhanced@npm:^0.9.0": + version: 0.9.1 + resolution: "@module-federation/enhanced@npm:0.9.1" + dependencies: + "@module-federation/bridge-react-webpack-plugin": "npm:0.9.1" + "@module-federation/data-prefetch": "npm:0.9.1" + "@module-federation/dts-plugin": "npm:0.9.1" + "@module-federation/error-codes": "npm:0.9.1" + "@module-federation/inject-external-runtime-core-plugin": "npm:0.9.1" + "@module-federation/managers": "npm:0.9.1" + "@module-federation/manifest": "npm:0.9.1" + "@module-federation/rspack": "npm:0.9.1" + "@module-federation/runtime-tools": "npm:0.9.1" + "@module-federation/sdk": "npm:0.9.1" + btoa: "npm:^1.2.1" + upath: "npm:2.0.1" + peerDependencies: + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: ">=1.0.24" + webpack: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + vue-tsc: + optional: true + webpack: + optional: true + checksum: 10c0/60f091b022a15f00796ffe32f8e771cfdd4e7381ab55056676ba71b2930365f3b3fe7c02f1cacf1df53b1693e122e6061f74c413485da1936aca53617c1a4072 + languageName: node + linkType: hard + "@module-federation/enhanced@npm:^2.3.3": version: 2.6.0 resolution: "@module-federation/enhanced@npm:2.6.0" @@ -6794,6 +7954,13 @@ __metadata: languageName: node linkType: hard +"@module-federation/error-codes@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/error-codes@npm:0.9.1" + checksum: 10c0/4134944357fafcf6cda301089b2cb97144bd3b5ddc06dbbdfe939a0290c002902a1094e7aab571d5439e9fe6d564766457948924e60c0d161d8f517318c0fa77 + languageName: node + linkType: hard + "@module-federation/error-codes@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/error-codes@npm:2.6.0" @@ -6801,6 +7968,15 @@ __metadata: languageName: node linkType: hard +"@module-federation/inject-external-runtime-core-plugin@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/inject-external-runtime-core-plugin@npm:0.9.1" + peerDependencies: + "@module-federation/runtime-tools": 0.9.1 + checksum: 10c0/c16129a7294ca9e0a62bd98784f5561ae8f7bceab5a1ba1c4ba912437849a2fe41b2d2af8631c675e688d854ce4d3155daab9752ac446e31ad453b522982ec95 + languageName: node + linkType: hard + "@module-federation/inject-external-runtime-core-plugin@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/inject-external-runtime-core-plugin@npm:2.6.0" @@ -6810,6 +7986,17 @@ __metadata: languageName: node linkType: hard +"@module-federation/managers@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/managers@npm:0.9.1" + dependencies: + "@module-federation/sdk": "npm:0.9.1" + find-pkg: "npm:2.0.0" + fs-extra: "npm:9.1.0" + checksum: 10c0/c13447fc1266245d52b73018fbf7d09b986b06b227019da4fbcb3304829314883688d114dd47e2cc97254be4ed361272134e76bfeaabc3d9220400d2b24050f3 + languageName: node + linkType: hard + "@module-federation/managers@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/managers@npm:2.6.0" @@ -6820,6 +8007,19 @@ __metadata: languageName: node linkType: hard +"@module-federation/manifest@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/manifest@npm:0.9.1" + dependencies: + "@module-federation/dts-plugin": "npm:0.9.1" + "@module-federation/managers": "npm:0.9.1" + "@module-federation/sdk": "npm:0.9.1" + chalk: "npm:3.0.0" + find-pkg: "npm:2.0.0" + checksum: 10c0/436905bcacc0d18448f667e55b18f59856c67970dc551055df715d9263e2e4a1a754449115e6c10f61dd9e2a687cd3cf4677390ac49574fce17f4f647302dbac + languageName: node + linkType: hard + "@module-federation/manifest@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/manifest@npm:2.6.0" @@ -6832,6 +8032,30 @@ __metadata: languageName: node linkType: hard +"@module-federation/rspack@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/rspack@npm:0.9.1" + dependencies: + "@module-federation/bridge-react-webpack-plugin": "npm:0.9.1" + "@module-federation/dts-plugin": "npm:0.9.1" + "@module-federation/inject-external-runtime-core-plugin": "npm:0.9.1" + "@module-federation/managers": "npm:0.9.1" + "@module-federation/manifest": "npm:0.9.1" + "@module-federation/runtime-tools": "npm:0.9.1" + "@module-federation/sdk": "npm:0.9.1" + peerDependencies: + "@rspack/core": ">=0.7" + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: ">=1.0.24" + peerDependenciesMeta: + typescript: + optional: true + vue-tsc: + optional: true + checksum: 10c0/e4db2534d5ce5823b64aeda15fbca1ca3dd268966167e60b51bd326c80b902c38fb2ba4b05500b5b602a4eca3736e5b1b38174649d94f01953d8858a02d71fd3 + languageName: node + linkType: hard + "@module-federation/rspack@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/rspack@npm:2.6.0" @@ -6866,6 +8090,16 @@ __metadata: languageName: node linkType: hard +"@module-federation/runtime-core@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/runtime-core@npm:0.9.1" + dependencies: + "@module-federation/error-codes": "npm:0.9.1" + "@module-federation/sdk": "npm:0.9.1" + checksum: 10c0/1b4174a74536c22757fb0ac0e6adb2d86c45857a36ec42bd4342fcb2fe124f59c5d323e0a69c78f2b50b3115390cf2ff4d3c8a8b21c610aa4ca40e8b2b28e5bf + languageName: node + linkType: hard + "@module-federation/runtime-core@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/runtime-core@npm:2.6.0" @@ -6886,6 +8120,16 @@ __metadata: languageName: node linkType: hard +"@module-federation/runtime-tools@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/runtime-tools@npm:0.9.1" + dependencies: + "@module-federation/runtime": "npm:0.9.1" + "@module-federation/webpack-bundler-runtime": "npm:0.9.1" + checksum: 10c0/41ca39964b27eda61d2db58b904d15f63c2e29fb83f06138f3628c055e5d7511015552b46cbce2a92a0ad9ecc8c0103243aaccc54c3bf620736e23dfe85b8689 + languageName: node + linkType: hard + "@module-federation/runtime-tools@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/runtime-tools@npm:2.6.0" @@ -6907,6 +8151,17 @@ __metadata: languageName: node linkType: hard +"@module-federation/runtime@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/runtime@npm:0.9.1" + dependencies: + "@module-federation/error-codes": "npm:0.9.1" + "@module-federation/runtime-core": "npm:0.9.1" + "@module-federation/sdk": "npm:0.9.1" + checksum: 10c0/c63f3f9ef23d14f3b1a84c9e04cb266fcfa041446841bfa8aff7170e84a40139d642532bd6c535389e1db0b29c7b0bfd2f7d0a0a65c9977d796b54dd90381884 + languageName: node + linkType: hard + "@module-federation/runtime@npm:2.6.0, @module-federation/runtime@npm:^2.3.3": version: 2.6.0 resolution: "@module-federation/runtime@npm:2.6.0" @@ -6925,6 +8180,13 @@ __metadata: languageName: node linkType: hard +"@module-federation/sdk@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/sdk@npm:0.9.1" + checksum: 10c0/2475c57386f2ecd0d9a9772861fdc946ce4eef6c112bef0526a2aacc38c3d48524c5fdb24dd6322d12845432abaef450cf5ba7e8138a9e152e7cae741e3692d3 + languageName: node + linkType: hard + "@module-federation/sdk@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/sdk@npm:2.6.0" @@ -6937,6 +8199,17 @@ __metadata: languageName: node linkType: hard +"@module-federation/third-party-dts-extractor@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/third-party-dts-extractor@npm:0.9.1" + dependencies: + find-pkg: "npm:2.0.0" + fs-extra: "npm:9.1.0" + resolve: "npm:1.22.8" + checksum: 10c0/907bf3ab96c8f767669388668992cbb2dfee331ec30234ddf068f13fdb238547c223d1cb0d64326333d111698a589f86dc932159aadba7ff439039f4b839fce6 + languageName: node + linkType: hard + "@module-federation/third-party-dts-extractor@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/third-party-dts-extractor@npm:2.6.0" @@ -6957,6 +8230,16 @@ __metadata: languageName: node linkType: hard +"@module-federation/webpack-bundler-runtime@npm:0.9.1": + version: 0.9.1 + resolution: "@module-federation/webpack-bundler-runtime@npm:0.9.1" + dependencies: + "@module-federation/runtime": "npm:0.9.1" + "@module-federation/sdk": "npm:0.9.1" + checksum: 10c0/9250ebb8721a64043ecc244acc308680b8a52cb95cebe92cd2d1099dd3e7ab0c3f53d893a5c7d3fbe5a86f133283bed97226c2232c316f281258de12e2239743 + languageName: node + linkType: hard + "@module-federation/webpack-bundler-runtime@npm:2.6.0": version: 2.6.0 resolution: "@module-federation/webpack-bundler-runtime@npm:2.6.0" @@ -9778,6 +11061,29 @@ __metadata: languageName: node linkType: hard +"@red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend@workspace:^, @red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend@workspace:plugins/kserve-kubeflow-connector-backend": + version: 0.0.0-use.local + resolution: "@red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend@workspace:plugins/kserve-kubeflow-connector-backend" + dependencies: + "@backstage/backend-defaults": "npm:^0.13.1" + "@backstage/backend-plugin-api": "npm:^1.5.0" + "@backstage/backend-test-utils": "npm:^1.10.0" + "@backstage/catalog-client": "npm:^1.9.1" + "@backstage/cli": "npm:^0.34.5" + "@backstage/errors": "npm:^1.2.7" + "@backstage/plugin-catalog-node": "npm:^1.20.0" + "@backstage/types": "npm:^1.2.2" + "@kubernetes/client-node": "npm:^0.20.0" + "@types/express": "npm:^4.17.6" + "@types/supertest": "npm:^2.0.12" + express: "npm:^4.17.1" + express-promise-router: "npm:^4.1.0" + supertest: "npm:^6.2.4" + undici: "npm:^6.19.0" + zod: "npm:^3.22.4" + languageName: unknown + linkType: soft + "@red-hat-developer-hub/backstage-plugin-theme@npm:^0.14.0": version: 0.14.7 resolution: "@red-hat-developer-hub/backstage-plugin-theme@npm:0.14.7" @@ -10502,6 +11808,24 @@ __metadata: languageName: node linkType: hard +"@sinonjs/commons@npm:^3.0.0": + version: 3.0.1 + resolution: "@sinonjs/commons@npm:3.0.1" + dependencies: + type-detect: "npm:4.0.8" + checksum: 10c0/1227a7b5bd6c6f9584274db996d7f8cee2c8c350534b9d0141fc662eaf1f292ea0ae3ed19e5e5271c8fd390d27e492ca2803acd31a1978be2cdc6be0da711403 + languageName: node + linkType: hard + +"@sinonjs/fake-timers@npm:^10.0.2": + version: 10.3.0 + resolution: "@sinonjs/fake-timers@npm:10.3.0" + dependencies: + "@sinonjs/commons": "npm:^3.0.0" + checksum: 10c0/2e2fb6cc57f227912814085b7b01fede050cd4746ea8d49a1e44d5a0e56a804663b0340ae2f11af7559ea9bf4d087a11f2f646197a660ea3cb04e19efc04aa63 + languageName: node + linkType: hard + "@smithy/abort-controller@npm:^3.1.9": version: 3.1.9 resolution: "@smithy/abort-controller@npm:3.1.9" @@ -12226,7 +13550,7 @@ __metadata: languageName: node linkType: hard -"@swc/core@npm:^1.15.6": +"@swc/core@npm:^1.15.6, @swc/core@npm:^1.3.46": version: 1.15.32 resolution: "@swc/core@npm:1.15.32" dependencies: @@ -12294,7 +13618,7 @@ __metadata: languageName: node linkType: hard -"@swc/jest@npm:^0.2.39": +"@swc/jest@npm:^0.2.22, @swc/jest@npm:^0.2.39": version: 0.2.39 resolution: "@swc/jest@npm:0.2.39" dependencies: @@ -12571,6 +13895,47 @@ __metadata: languageName: node linkType: hard +"@types/babel__core@npm:^7.1.14": + version: 7.20.5 + resolution: "@types/babel__core@npm:7.20.5" + dependencies: + "@babel/parser": "npm:^7.20.7" + "@babel/types": "npm:^7.20.7" + "@types/babel__generator": "npm:*" + "@types/babel__template": "npm:*" + "@types/babel__traverse": "npm:*" + checksum: 10c0/bdee3bb69951e833a4b811b8ee9356b69a61ed5b7a23e1a081ec9249769117fa83aaaf023bb06562a038eb5845155ff663e2d5c75dd95c1d5ccc91db012868ff + languageName: node + linkType: hard + +"@types/babel__generator@npm:*": + version: 7.6.8 + resolution: "@types/babel__generator@npm:7.6.8" + dependencies: + "@babel/types": "npm:^7.0.0" + checksum: 10c0/f0ba105e7d2296bf367d6e055bb22996886c114261e2cb70bf9359556d0076c7a57239d019dee42bb063f565bade5ccb46009bce2044b2952d964bf9a454d6d2 + languageName: node + linkType: hard + +"@types/babel__template@npm:*": + version: 7.4.4 + resolution: "@types/babel__template@npm:7.4.4" + dependencies: + "@babel/parser": "npm:^7.1.0" + "@babel/types": "npm:^7.0.0" + checksum: 10c0/cc84f6c6ab1eab1427e90dd2b76ccee65ce940b778a9a67be2c8c39e1994e6f5bbc8efa309f6cea8dc6754994524cd4d2896558df76d92e7a1f46ecffee7112b + languageName: node + linkType: hard + +"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": + version: 7.20.6 + resolution: "@types/babel__traverse@npm:7.20.6" + dependencies: + "@babel/types": "npm:^7.20.7" + checksum: 10c0/7ba7db61a53e28cac955aa99af280d2600f15a8c056619c05b6fc911cbe02c61aa4f2823299221b23ce0cce00b294c0e5f618ec772aa3f247523c2e48cf7b888 + languageName: node + linkType: hard + "@types/body-parser@npm:*": version: 1.19.5 resolution: "@types/body-parser@npm:1.19.5" @@ -12794,6 +14159,15 @@ __metadata: languageName: node linkType: hard +"@types/graceful-fs@npm:^4.1.3": + version: 4.1.9 + resolution: "@types/graceful-fs@npm:4.1.9" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/235d2fc69741448e853333b7c3d1180a966dd2b8972c8cbcd6b2a0c6cd7f8d582ab2b8e58219dbc62cce8f1b40aa317ff78ea2201cdd8249da5025adebed6f0b + languageName: node + linkType: hard + "@types/hast@npm:^2.0.0": version: 2.3.10 resolution: "@types/hast@npm:2.3.10" @@ -12861,7 +14235,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.6": +"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.6": version: 2.0.6 resolution: "@types/istanbul-lib-coverage@npm:2.0.6" checksum: 10c0/3948088654f3eeb45363f1db158354fb013b362dba2a5c2c18c559484d5eb9f6fd85b23d66c0a7c2fcfab7308d0a585b14dadaca6cc8bf89ebfdc7f8f5102fb7 @@ -12886,6 +14260,16 @@ __metadata: languageName: node linkType: hard +"@types/jest@npm:^29.5.11": + version: 29.5.14 + resolution: "@types/jest@npm:29.5.14" + dependencies: + expect: "npm:^29.0.0" + pretty-format: "npm:^29.0.0" + checksum: 10c0/18e0712d818890db8a8dab3d91e9ea9f7f19e3f83c2e50b312f557017dc81466207a71f3ed79cf4428e813ba939954fa26ffa0a9a7f153181ba174581b1c2aed + languageName: node + linkType: hard + "@types/js-cookie@npm:^2.2.6": version: 2.2.7 resolution: "@types/js-cookie@npm:2.2.7" @@ -12907,6 +14291,17 @@ __metadata: languageName: node linkType: hard +"@types/jsdom@npm:^20.0.0": + version: 20.0.1 + resolution: "@types/jsdom@npm:20.0.1" + dependencies: + "@types/node": "npm:*" + "@types/tough-cookie": "npm:*" + parse5: "npm:^7.0.0" + checksum: 10c0/3d4b2a3eab145674ee6da482607c5e48977869109f0f62560bf91ae1a792c9e847ac7c6aaf243ed2e97333cb3c51aef314ffa54a19ef174b8f9592dfcb836b25 + languageName: node + linkType: hard + "@types/json-schema@npm:*, @types/json-schema@npm:^7.0.11, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.7, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" @@ -13082,6 +14477,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^20.1.1": + version: 20.17.24 + resolution: "@types/node@npm:20.17.24" + dependencies: + undici-types: "npm:~6.19.2" + checksum: 10c0/2a39ce4c4cd4588a05b2a485cc0a1407cbea608dd1ab03e36add59d61712718d95c84b492ca5190753f0be2bce748aeeb0f2a1412e712775462befe3820b3ff9 + languageName: node + linkType: hard + "@types/parse-json@npm:^4.0.0": version: 4.0.2 resolution: "@types/parse-json@npm:4.0.2" @@ -13200,7 +14604,7 @@ __metadata: languageName: node linkType: hard -"@types/request@npm:^2.48.8": +"@types/request@npm:^2.47.1, @types/request@npm:^2.48.8": version: 2.48.12 resolution: "@types/request@npm:2.48.12" dependencies: @@ -13316,6 +14720,13 @@ __metadata: languageName: node linkType: hard +"@types/stack-utils@npm:^2.0.0": + version: 2.0.3 + resolution: "@types/stack-utils@npm:2.0.3" + checksum: 10c0/1f4658385ae936330581bcb8aa3a066df03867d90281cdf89cc356d404bd6579be0f11902304e1f775d92df22c6dd761d4451c804b0a4fba973e06211e9bd77c + languageName: node + linkType: hard + "@types/stream-buffers@npm:^3.0.3": version: 3.0.7 resolution: "@types/stream-buffers@npm:3.0.7" @@ -13427,7 +14838,7 @@ __metadata: languageName: node linkType: hard -"@types/ws@npm:*, @types/ws@npm:^8.5.10": +"@types/ws@npm:*, @types/ws@npm:^8.5.10, @types/ws@npm:^8.5.3": version: 8.18.0 resolution: "@types/ws@npm:8.18.0" dependencies: @@ -13958,6 +15369,13 @@ __metadata: languageName: node linkType: hard +"abab@npm:^2.0.6": + version: 2.0.6 + resolution: "abab@npm:2.0.6" + checksum: 10c0/0b245c3c3ea2598fe0025abf7cc7bb507b06949d51e8edae5d12c1b847a0a0c09639abcb94788332b4e2044ac4491c1e8f571b51c7826fd4b0bda1685ad4a278 + languageName: node + linkType: hard + "abbrev@npm:^1.0.0": version: 1.1.1 resolution: "abbrev@npm:1.1.1" @@ -13988,7 +15406,7 @@ __metadata: languageName: node linkType: hard -"accepts@npm:~1.3.4, accepts@npm:~1.3.8": +"accepts@npm:^1.3.5, accepts@npm:~1.3.4, accepts@npm:~1.3.8": version: 1.3.8 resolution: "accepts@npm:1.3.8" dependencies: @@ -13998,6 +15416,16 @@ __metadata: languageName: node linkType: hard +"acorn-globals@npm:^7.0.0": + version: 7.0.1 + resolution: "acorn-globals@npm:7.0.1" + dependencies: + acorn: "npm:^8.1.0" + acorn-walk: "npm:^8.0.2" + checksum: 10c0/7437f58e92d99292dbebd0e79531af27d706c9f272f31c675d793da6c82d897e75302a8744af13c7f7978a8399840f14a353b60cf21014647f71012982456d2b + languageName: node + linkType: hard + "acorn-import-phases@npm:^1.0.3": version: 1.0.4 resolution: "acorn-import-phases@npm:1.0.4" @@ -14016,7 +15444,7 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.1.1, acorn-walk@npm:^8.3.4": +"acorn-walk@npm:^8.0.2, acorn-walk@npm:^8.1.1, acorn-walk@npm:^8.3.4": version: 8.3.5 resolution: "acorn-walk@npm:8.3.5" dependencies: @@ -14025,7 +15453,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.16.0, acorn@npm:^8.4.1, acorn@npm:^8.9.0": +"acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.16.0, acorn@npm:^8.4.1, acorn@npm:^8.8.1, acorn@npm:^8.9.0": version: 8.16.0 resolution: "acorn@npm:8.16.0" bin: @@ -14048,6 +15476,13 @@ __metadata: languageName: node linkType: hard +"adm-zip@npm:^0.5.10": + version: 0.5.16 + resolution: "adm-zip@npm:0.5.16" + checksum: 10c0/6f10119d4570c7ba76dcf428abb8d3f69e63f92e51f700a542b43d4c0130373dd2ddfc8f85059f12d4a843703a90c3970cfd17876844b4f3f48bf042bfa6b49f + languageName: node + linkType: hard + "agent-base@npm:6, agent-base@npm:^6.0.2": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -14175,7 +15610,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.12.2, ajv@npm:^6.12.4, ajv@npm:^6.12.5": +"ajv@npm:^6.12.2, ajv@npm:^6.12.3, ajv@npm:^6.12.4, ajv@npm:^6.12.5": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -14300,7 +15735,7 @@ __metadata: languageName: node linkType: hard -"anymatch@npm:~3.1.2": +"anymatch@npm:^3.0.3, anymatch@npm:~3.1.2": version: 3.1.3 resolution: "anymatch@npm:3.1.3" dependencies: @@ -14637,7 +16072,7 @@ __metadata: languageName: node linkType: hard -"asn1@npm:^0.2.6": +"asn1@npm:^0.2.6, asn1@npm:~0.2.3": version: 0.2.6 resolution: "asn1@npm:0.2.6" dependencies: @@ -14657,6 +16092,13 @@ __metadata: languageName: node linkType: hard +"assert-plus@npm:1.0.0, assert-plus@npm:^1.0.0": + version: 1.0.0 + resolution: "assert-plus@npm:1.0.0" + checksum: 10c0/b194b9d50c3a8f872ee85ab110784911e696a4d49f7ee6fc5fb63216dedbefd2c55999c70cb2eaeb4cf4a0e0338b44e9ace3627117b5bf0d42460e9132f21b91 + languageName: node + linkType: hard + "assert@npm:^2.0.0": version: 2.1.0 resolution: "assert@npm:2.1.0" @@ -14790,6 +16232,13 @@ __metadata: languageName: node linkType: hard +"aws-sign2@npm:~0.7.0": + version: 0.7.0 + resolution: "aws-sign2@npm:0.7.0" + checksum: 10c0/021d2cc5547d4d9ef1633e0332e746a6f447997758b8b68d6fb33f290986872d2bff5f0c37d5832f41a7229361f093cd81c40898d96ed153493c0fb5cd8575d2 + languageName: node + linkType: hard + "aws-ssl-profiles@npm:^1.1.1": version: 1.1.2 resolution: "aws-ssl-profiles@npm:1.1.2" @@ -14797,6 +16246,13 @@ __metadata: languageName: node linkType: hard +"aws4@npm:^1.8.0": + version: 1.13.2 + resolution: "aws4@npm:1.13.2" + checksum: 10c0/c993d0d186d699f685d73113733695d648ec7d4b301aba2e2a559d0cd9c1c902308cc52f4095e1396b23fddbc35113644e7f0a6a32753636306e41e3ed6f1e79 + languageName: node + linkType: hard + "axe-core@npm:^4.10.0": version: 4.10.3 resolution: "axe-core@npm:4.10.3" @@ -14829,14 +16285,14 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.0.0, axios@npm:^1.12.2": - version: 1.15.2 - resolution: "axios@npm:1.15.2" +"axios@npm:^1.0.0, axios@npm:^1.12.2, axios@npm:^1.7.4": + version: 1.13.2 + resolution: "axios@npm:1.13.2" dependencies: - follow-redirects: "npm:^1.15.11" - form-data: "npm:^4.0.5" - proxy-from-env: "npm:^2.1.0" - checksum: 10c0/4eeae0feeaa7fdc1ef24f81f8b378fdadedf4aebdd6bf224484675160f8744cf17b9b0d1c215279979940f7e8ce463beffa2f713099612e428eac238515c81d5 + follow-redirects: "npm:^1.15.6" + form-data: "npm:^4.0.4" + proxy-from-env: "npm:^1.1.0" + checksum: 10c0/e8a42e37e5568ae9c7a28c348db0e8cf3e43d06fcbef73f0048669edfe4f71219664da7b6cc991b0c0f01c28a48f037c515263cb79be1f1ae8ff034cd813867b languageName: node linkType: hard @@ -14854,6 +16310,48 @@ __metadata: languageName: node linkType: hard +"babel-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "babel-jest@npm:29.7.0" + dependencies: + "@jest/transform": "npm:^29.7.0" + "@types/babel__core": "npm:^7.1.14" + babel-plugin-istanbul: "npm:^6.1.1" + babel-preset-jest: "npm:^29.6.3" + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + slash: "npm:^3.0.0" + peerDependencies: + "@babel/core": ^7.8.0 + checksum: 10c0/2eda9c1391e51936ca573dd1aedfee07b14c59b33dbe16ef347873ddd777bcf6e2fc739681e9e9661ab54ef84a3109a03725be2ac32cd2124c07ea4401cbe8c1 + languageName: node + linkType: hard + +"babel-plugin-istanbul@npm:^6.1.1": + version: 6.1.1 + resolution: "babel-plugin-istanbul@npm:6.1.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.0.0" + "@istanbuljs/load-nyc-config": "npm:^1.0.0" + "@istanbuljs/schema": "npm:^0.1.2" + istanbul-lib-instrument: "npm:^5.0.4" + test-exclude: "npm:^6.0.0" + checksum: 10c0/1075657feb705e00fd9463b329921856d3775d9867c5054b449317d39153f8fbcebd3e02ebf00432824e647faff3683a9ca0a941325ef1afe9b3c4dd51b24beb + languageName: node + linkType: hard + +"babel-plugin-jest-hoist@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-plugin-jest-hoist@npm:29.6.3" + dependencies: + "@babel/template": "npm:^7.3.3" + "@babel/types": "npm:^7.3.3" + "@types/babel__core": "npm:^7.1.14" + "@types/babel__traverse": "npm:^7.0.6" + checksum: 10c0/7e6451caaf7dce33d010b8aafb970e62f1b0c0b57f4978c37b0d457bbcf0874d75a395a102daf0bae0bd14eafb9f6e9a165ee5e899c0a4f1f3bb2e07b304ed2e + languageName: node + linkType: hard + "babel-plugin-macros@npm:^3.1.0": version: 3.1.0 resolution: "babel-plugin-macros@npm:3.1.0" @@ -14876,6 +16374,43 @@ __metadata: languageName: node linkType: hard +"babel-preset-current-node-syntax@npm:^1.0.0": + version: 1.1.0 + resolution: "babel-preset-current-node-syntax@npm:1.1.0" + dependencies: + "@babel/plugin-syntax-async-generators": "npm:^7.8.4" + "@babel/plugin-syntax-bigint": "npm:^7.8.3" + "@babel/plugin-syntax-class-properties": "npm:^7.12.13" + "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" + "@babel/plugin-syntax-import-attributes": "npm:^7.24.7" + "@babel/plugin-syntax-import-meta": "npm:^7.10.4" + "@babel/plugin-syntax-json-strings": "npm:^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" + "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" + "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" + "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" + "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" + "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/0b838d4412e3322cb4436f246e24e9c00bebcedfd8f00a2f51489db683bd35406bbd55a700759c28d26959c6e03f84dd6a1426f576f440267c1d7a73c5717281 + languageName: node + linkType: hard + +"babel-preset-jest@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-preset-jest@npm:29.6.3" + dependencies: + babel-plugin-jest-hoist: "npm:^29.6.3" + babel-preset-current-node-syntax: "npm:^1.0.0" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/ec5fd0276b5630b05f0c14bb97cc3815c6b31600c683ebb51372e54dcb776cff790bdeeabd5b8d01ede375a040337ccbf6a3ccd68d3a34219125945e167ad943 + languageName: node + linkType: hard + "babel-runtime@npm:^6.26.0": version: 6.26.0 resolution: "babel-runtime@npm:6.26.0" @@ -14920,6 +16455,7 @@ __metadata: "@red-hat-developer-hub/backstage-plugin-catalog-backend-module-catalog-backend-module-ai-resource-extensions": "workspace:^" "@red-hat-developer-hub/backstage-plugin-catalog-backend-module-model-catalog": "workspace:^" "@red-hat-developer-hub/backstage-plugin-catalog-techdoc-url-reader-backend": "workspace:^" + "@red-hat-developer-hub/backstage-plugin-kserve-kubeflow-connector-backend": "workspace:^" app: "link:../app" better-sqlite3: "npm:^12.0.0" node-gyp: "npm:^10.0.0" @@ -15057,7 +16593,7 @@ __metadata: languageName: node linkType: hard -"bcrypt-pbkdf@npm:^1.0.2": +"bcrypt-pbkdf@npm:^1.0.0, bcrypt-pbkdf@npm:^1.0.2": version: 1.0.2 resolution: "bcrypt-pbkdf@npm:1.0.2" dependencies: @@ -15093,6 +16629,19 @@ __metadata: languageName: node linkType: hard +"bfj@npm:^8.0.0": + version: 8.0.0 + resolution: "bfj@npm:8.0.0" + dependencies: + bluebird: "npm:^3.7.2" + check-types: "npm:^11.2.3" + hoopy: "npm:^0.1.4" + jsonpath: "npm:^1.1.1" + tryer: "npm:^1.0.1" + checksum: 10c0/380b702a8f58fa6690f7e2a3fa7befdd3d550cc6eaf75f626bd4e1bc9c1870deabcd3381b971519268a49083878d1f9e9e4aca871afe40f97e22a3482c9f39c7 + languageName: node + linkType: hard + "bfj@npm:^9.0.2": version: 9.1.3 resolution: "bfj@npm:9.1.3" @@ -15366,7 +16915,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.18.1, browserslist@npm:^4.21.4, browserslist@npm:^4.28.1": +"browserslist@npm:^4.0.0, browserslist@npm:^4.18.1, browserslist@npm:^4.21.4, browserslist@npm:^4.24.0, browserslist@npm:^4.28.1": version: 4.28.2 resolution: "browserslist@npm:4.28.2" dependencies: @@ -15381,6 +16930,15 @@ __metadata: languageName: node linkType: hard +"bser@npm:2.1.1": + version: 2.1.1 + resolution: "bser@npm:2.1.1" + dependencies: + node-int64: "npm:^0.4.0" + checksum: 10c0/24d8dfb7b6d457d73f32744e678a60cc553e4ec0e9e1a01cf614b44d85c3c87e188d3cc78ef0442ce5032ee6818de20a0162ba1074725c0d08908f62ea979227 + languageName: node + linkType: hard + "btoa-lite@npm:^1.0.0": version: 1.0.0 resolution: "btoa-lite@npm:1.0.0" @@ -15388,6 +16946,15 @@ __metadata: languageName: node linkType: hard +"btoa@npm:^1.2.1": + version: 1.2.1 + resolution: "btoa@npm:1.2.1" + bin: + btoa: bin/btoa.js + checksum: 10c0/557b9682e40a68ae057af1b377e28884e6ff756ba0f499fe0f8c7b725a5bfb5c0d891604ac09944dbe330c9d43fb3976fef734f9372608d0d8e78a30eda292ae + languageName: node + linkType: hard + "buffer-crc32@npm:^1.0.0": version: 1.0.0 resolution: "buffer-crc32@npm:1.0.0" @@ -15581,6 +17148,16 @@ __metadata: languageName: node linkType: hard +"cache-content-type@npm:^1.0.0": + version: 1.0.1 + resolution: "cache-content-type@npm:1.0.1" + dependencies: + mime-types: "npm:^2.1.18" + ylru: "npm:^1.2.0" + checksum: 10c0/59b50e29e64a24bb52a16e5d35b69ad27ef14313701acc5e462b0aeebf2f09ff87fb6538eb0c0f0de4de05c8a1eecaef47f455f5b4928079e68f607f816a0843 + languageName: node + linkType: hard + "cacheable-lookup@npm:^6.0.0": version: 6.1.0 resolution: "cacheable-lookup@npm:6.1.0" @@ -15651,6 +17228,20 @@ __metadata: languageName: node linkType: hard +"camelcase@npm:^5.3.1": + version: 5.3.1 + resolution: "camelcase@npm:5.3.1" + checksum: 10c0/92ff9b443bfe8abb15f2b1513ca182d16126359ad4f955ebc83dc4ddcc4ef3fdd2c078bc223f2673dc223488e75c99b16cc4d056624374b799e6a1555cf61b23 + languageName: node + linkType: hard + +"camelcase@npm:^6.2.0": + version: 6.3.0 + resolution: "camelcase@npm:6.3.0" + checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 + languageName: node + linkType: hard + "caniuse-api@npm:^3.0.0": version: 3.0.0 resolution: "caniuse-api@npm:3.0.0" @@ -15670,6 +17261,13 @@ __metadata: languageName: node linkType: hard +"caseless@npm:~0.12.0": + version: 0.12.0 + resolution: "caseless@npm:0.12.0" + checksum: 10c0/ccf64bcb6c0232cdc5b7bd91ddd06e23a4b541f138336d4725233ac538041fb2f29c2e86c3c4a7a61ef990b665348db23a047060b9414c3a6603e9fa61ad4626 + languageName: node + linkType: hard + "catharsis@npm:^0.9.0": version: 0.9.0 resolution: "catharsis@npm:0.9.0" @@ -15697,23 +17295,23 @@ __metadata: languageName: node linkType: hard -"chalk@npm:4.1.2, chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.1, chalk@npm:^4.1.2": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" +"chalk@npm:3.0.0, chalk@npm:^3.0.0": + version: 3.0.0 + resolution: "chalk@npm:3.0.0" dependencies: ansi-styles: "npm:^4.1.0" supports-color: "npm:^7.1.0" - checksum: 10c0/4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 + checksum: 10c0/ee650b0a065b3d7a6fda258e75d3a86fc8e4effa55871da730a9e42ccb035bf5fd203525e5a1ef45ec2582ecc4f65b47eb11357c526b84dd29a14fb162c414d2 languageName: node linkType: hard -"chalk@npm:^3.0.0": - version: 3.0.0 - resolution: "chalk@npm:3.0.0" +"chalk@npm:4.1.2, chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.1, chalk@npm:^4.1.2": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" dependencies: ansi-styles: "npm:^4.1.0" supports-color: "npm:^7.1.0" - checksum: 10c0/ee650b0a065b3d7a6fda258e75d3a86fc8e4effa55871da730a9e42ccb035bf5fd203525e5a1ef45ec2582ecc4f65b47eb11357c526b84dd29a14fb162c414d2 + checksum: 10c0/4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 languageName: node linkType: hard @@ -15869,6 +17467,13 @@ __metadata: languageName: node linkType: hard +"cjs-module-lexer@npm:^1.0.0": + version: 1.4.3 + resolution: "cjs-module-lexer@npm:1.4.3" + checksum: 10c0/076b3af85adc4d65dbdab1b5b240fe5b45d44fcf0ef9d429044dd94d19be5589376805c44fb2d4b3e684e5fe6a9b7cf3e426476a6507c45283c5fc6ff95240be + languageName: node + linkType: hard + "classnames@npm:^2.2.6, classnames@npm:^2.3.1, classnames@npm:^2.5.1": version: 2.5.1 resolution: "classnames@npm:2.5.1" @@ -16025,6 +17630,13 @@ __metadata: languageName: node linkType: hard +"co@npm:^4.6.0": + version: 4.6.0 + resolution: "co@npm:4.6.0" + checksum: 10c0/c0e85ea0ca8bf0a50cbdca82efc5af0301240ca88ebe3644a6ffb8ffe911f34d40f8fbcf8f1d52c5ddd66706abd4d3bfcd64259f1e8e2371d4f47573b0dc8c28 + languageName: node + linkType: hard + "code-block-writer@npm:^13.0.3": version: 13.0.3 resolution: "code-block-writer@npm:13.0.3" @@ -16080,6 +17692,13 @@ __metadata: languageName: node linkType: hard +"collect-v8-coverage@npm:^1.0.0": + version: 1.0.2 + resolution: "collect-v8-coverage@npm:1.0.2" + checksum: 10c0/ed7008e2e8b6852c5483b444a3ae6e976e088d4335a85aa0a9db2861c5f1d31bd2d7ff97a60469b3388deeba661a619753afbe201279fb159b4b9548ab8269a1 + languageName: node + linkType: hard + "color-convert@npm:^1.9.0, color-convert@npm:^1.9.3": version: 1.9.3 resolution: "color-convert@npm:1.9.3" @@ -16172,7 +17791,7 @@ __metadata: languageName: node linkType: hard -"combined-stream@npm:^1.0.8": +"combined-stream@npm:^1.0.6, combined-stream@npm:^1.0.8, combined-stream@npm:~1.0.6": version: 1.0.8 resolution: "combined-stream@npm:1.0.8" dependencies: @@ -16223,6 +17842,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^12.0.0": + version: 12.1.0 + resolution: "commander@npm:12.1.0" + checksum: 10c0/6e1996680c083b3b897bfc1cfe1c58dfbcd9842fd43e1aaf8a795fbc237f65efcc860a3ef457b318e73f29a4f4a28f6403c3d653d021d960e4632dd45bde54a9 + languageName: node + linkType: hard + "commander@npm:^14.0.3": version: 14.0.3 resolution: "commander@npm:14.0.3" @@ -16472,7 +18098,7 @@ __metadata: languageName: node linkType: hard -"content-disposition@npm:~0.5.4": +"content-disposition@npm:~0.5.2, content-disposition@npm:~0.5.4": version: 0.5.4 resolution: "content-disposition@npm:0.5.4" dependencies: @@ -16481,7 +18107,7 @@ __metadata: languageName: node linkType: hard -"content-type@npm:^1.0.5, content-type@npm:~1.0.4, content-type@npm:~1.0.5": +"content-type@npm:^1.0.4, content-type@npm:^1.0.5, content-type@npm:~1.0.4, content-type@npm:~1.0.5": version: 1.0.5 resolution: "content-type@npm:1.0.5" checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af @@ -16495,6 +18121,13 @@ __metadata: languageName: node linkType: hard +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 10c0/8f2f7a27a1a011cc6cc88cc4da2d7d0cfa5ee0369508baae3d98c260bb3ac520691464e5bbe4ae7cdf09860c1d69ecc6f70c63c6e7c7f7e3f18ec08484dc7d9b + languageName: node + linkType: hard + "cookie-parser@npm:^1.4.5": version: 1.4.7 resolution: "cookie-parser@npm:1.4.7" @@ -16540,6 +18173,16 @@ __metadata: languageName: node linkType: hard +"cookies@npm:~0.9.0": + version: 0.9.1 + resolution: "cookies@npm:0.9.1" + dependencies: + depd: "npm:~2.0.0" + keygrip: "npm:~1.1.0" + checksum: 10c0/3ffa1c0e992b62ee119adae4dd2ddd4a89166fa5434cd9bd9ff84ec4d2f14dfe2318a601280abfe32a4f64f884ec9345fb1912e488b002d188d2efa0d3919ba3 + languageName: node + linkType: hard + "copy-to-clipboard@npm:^3.2.0, copy-to-clipboard@npm:^3.3.1": version: 3.3.3 resolution: "copy-to-clipboard@npm:3.3.3" @@ -16570,6 +18213,13 @@ __metadata: languageName: node linkType: hard +"core-util-is@npm:1.0.2": + version: 1.0.2 + resolution: "core-util-is@npm:1.0.2" + checksum: 10c0/980a37a93956d0de8a828ce508f9b9e3317039d68922ca79995421944146700e4aaf490a6dbfebcb1c5292a7184600c7710b957d724be1e37b8254c6bc0fe246 + languageName: node + linkType: hard + "core-util-is@npm:~1.0.0": version: 1.0.3 resolution: "core-util-is@npm:1.0.3" @@ -16713,6 +18363,23 @@ __metadata: languageName: node linkType: hard +"create-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "create-jest@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + chalk: "npm:^4.0.0" + exit: "npm:^0.1.2" + graceful-fs: "npm:^4.2.9" + jest-config: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + prompts: "npm:^2.0.1" + bin: + create-jest: bin/create-jest.js + checksum: 10c0/e7e54c280692470d3398f62a6238fd396327e01c6a0757002833f06d00afc62dd7bfe04ff2b9cd145264460e6b4d1eb8386f2925b7e567f97939843b7b0e812f + languageName: node + linkType: hard + "create-require@npm:^1.1.0, create-require@npm:^1.1.1": version: 1.1.1 resolution: "create-require@npm:1.1.1" @@ -16993,6 +18660,29 @@ __metadata: languageName: node linkType: hard +"cssom@npm:^0.5.0": + version: 0.5.0 + resolution: "cssom@npm:0.5.0" + checksum: 10c0/8c4121c243baf0678c65dcac29b201ff0067dfecf978de9d5c83b2ff127a8fdefd2bfd54577f5ad8c80ed7d2c8b489ae01c82023545d010c4ecb87683fb403dd + languageName: node + linkType: hard + +"cssom@npm:~0.3.6": + version: 0.3.8 + resolution: "cssom@npm:0.3.8" + checksum: 10c0/d74017b209440822f9e24d8782d6d2e808a8fdd58fa626a783337222fe1c87a518ba944d4c88499031b4786e68772c99dfae616638d71906fe9f203aeaf14411 + languageName: node + linkType: hard + +"cssstyle@npm:^2.3.0": + version: 2.3.0 + resolution: "cssstyle@npm:2.3.0" + dependencies: + cssom: "npm:~0.3.6" + checksum: 10c0/863400da2a458f73272b9a55ba7ff05de40d850f22eb4f37311abebd7eff801cf1cd2fb04c4c92b8c3daed83fe766e52e4112afb7bc88d86c63a9c2256a7d178 + languageName: node + linkType: hard + "cssstyle@npm:^4.2.1": version: 4.3.0 resolution: "cssstyle@npm:4.3.0" @@ -17129,6 +18819,15 @@ __metadata: languageName: node linkType: hard +"dashdash@npm:^1.12.0": + version: 1.14.1 + resolution: "dashdash@npm:1.14.1" + dependencies: + assert-plus: "npm:^1.0.0" + checksum: 10c0/64589a15c5bd01fa41ff7007e0f2c6552c5ef2028075daa16b188a3721f4ba001841bf306dfc2eee6e2e6e7f76b38f5f17fb21fa847504192290ffa9e150118a + languageName: node + linkType: hard + "data-uri-to-buffer@npm:^6.0.2": version: 6.0.2 resolution: "data-uri-to-buffer@npm:6.0.2" @@ -17136,6 +18835,17 @@ __metadata: languageName: node linkType: hard +"data-urls@npm:^3.0.2": + version: 3.0.2 + resolution: "data-urls@npm:3.0.2" + dependencies: + abab: "npm:^2.0.6" + whatwg-mimetype: "npm:^3.0.0" + whatwg-url: "npm:^11.0.0" + checksum: 10c0/051c3aaaf3e961904f136aab095fcf6dff4db23a7fc759dd8ba7b3e6ba03fc07ef608086caad8ab910d864bd3b5e57d0d2f544725653d77c96a2c971567045f4 + languageName: node + linkType: hard + "data-urls@npm:^5.0.0": version: 5.0.0 resolution: "data-urls@npm:5.0.0" @@ -17265,7 +18975,7 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:^10.4.3": +"decimal.js@npm:^10.4.2, decimal.js@npm:^10.4.3": version: 10.5.0 resolution: "decimal.js@npm:10.5.0" checksum: 10c0/785c35279df32762143914668df35948920b6c1c259b933e0519a69b7003fc0a5ed2a766b1e1dda02574450c566b21738a45f15e274b47c2ac02072c0d1f3ac3 @@ -17290,6 +19000,18 @@ __metadata: languageName: node linkType: hard +"dedent@npm:^1.0.0": + version: 1.5.3 + resolution: "dedent@npm:1.5.3" + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + checksum: 10c0/d94bde6e6f780be4da4fd760288fcf755ec368872f4ac5218197200d86430aeb8d90a003a840bff1c20221188e3f23adced0119cb811c6873c70d0ac66d12832 + languageName: node + linkType: hard + "deep-equal@npm:^2.0.5": version: 2.2.3 resolution: "deep-equal@npm:2.2.3" @@ -17316,6 +19038,13 @@ __metadata: languageName: node linkType: hard +"deep-equal@npm:~1.0.1": + version: 1.0.1 + resolution: "deep-equal@npm:1.0.1" + checksum: 10c0/bef838ef9824e124d10335deb9c7540bfc9f2f0eab17ad1bb870d0eee83ee4e7e6f6f892e5eebc2bd82759a76676926ad5246180097e28e57752176ff7dae888 + languageName: node + linkType: hard + "deep-extend@npm:0.6.0, deep-extend@npm:^0.6.0": version: 0.6.0 resolution: "deep-extend@npm:0.6.0" @@ -17323,7 +19052,7 @@ __metadata: languageName: node linkType: hard -"deep-is@npm:^0.1.3": +"deep-is@npm:^0.1.3, deep-is@npm:~0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" checksum: 10c0/7f0ee496e0dff14a573dc6127f14c95061b448b87b995fc96c017ce0a1e66af1675e73f1d6064407975bc4ea6ab679497a29fff7b5b9c4e99cb10797c1ad0b4c @@ -17354,6 +19083,15 @@ __metadata: languageName: node linkType: hard +"default-user-agent@npm:^1.0.0": + version: 1.0.0 + resolution: "default-user-agent@npm:1.0.0" + dependencies: + os-name: "npm:~1.0.3" + checksum: 10c0/c7389e78cef67e7bd7706e71bbf3e3012815e4f9ecc814202353072877573529c5caefd54fa0cb7c53918471443794e6f5347428692048923ab931ff43bea5db + languageName: node + linkType: hard + "defaults@npm:^1.0.3": version: 1.0.4 resolution: "defaults@npm:1.0.4" @@ -17431,7 +19169,7 @@ __metadata: languageName: node linkType: hard -"depd@npm:2.0.0, depd@npm:~2.0.0": +"depd@npm:2.0.0, depd@npm:^2.0.0, depd@npm:~2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" checksum: 10c0/58bd06ec20e19529b06f7ad07ddab60e504d9e0faca4bd23079fac2d279c3594334d736508dc350e06e510aba5e22e4594483b3a6562ce7c17dd797f4cc4ad2c @@ -17506,6 +19244,13 @@ __metadata: languageName: node linkType: hard +"detect-newline@npm:^3.0.0": + version: 3.1.0 + resolution: "detect-newline@npm:3.1.0" + checksum: 10c0/c38cfc8eeb9fda09febb44bcd85e467c970d4e3bf526095394e5a4f18bc26dd0cf6b22c69c1fa9969261521c593836db335c2795218f6d781a512aea2fb8209d + languageName: node + linkType: hard + "detect-node-es@npm:^1.1.0": version: 1.1.0 resolution: "detect-node-es@npm:1.1.0" @@ -17543,6 +19288,13 @@ __metadata: languageName: node linkType: hard +"diff-sequences@npm:^29.6.3": + version: 29.6.3 + resolution: "diff-sequences@npm:29.6.3" + checksum: 10c0/32e27ac7dbffdf2fb0eb5a84efd98a9ad084fbabd5ac9abb8757c6770d5320d2acd172830b28c4add29bb873d59420601dfc805ac4064330ce59b1adfd0593b2 + languageName: node + linkType: hard + "diff3@npm:0.0.3": version: 0.0.3 resolution: "diff3@npm:0.0.3" @@ -17582,6 +19334,13 @@ __metadata: languageName: node linkType: hard +"digest-header@npm:^1.0.0": + version: 1.1.0 + resolution: "digest-header@npm:1.1.0" + checksum: 10c0/114839bec382561c0f64ad550a370cc3da7ef53f23973a08c70327c2f212d947e978ead8188fb13c49cdff33985dd546edf64e75fbbbb651b4d4d4a7ef635bcd + languageName: node + linkType: hard + "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -17719,6 +19478,15 @@ __metadata: languageName: node linkType: hard +"domexception@npm:^4.0.0": + version: 4.0.0 + resolution: "domexception@npm:4.0.0" + dependencies: + webidl-conversions: "npm:^7.0.0" + checksum: 10c0/774277cd9d4df033f852196e3c0077a34dbd15a96baa4d166e0e47138a80f4c0bdf0d94e4703e6ff5883cec56bb821a6fff84402d8a498e31de7c87eb932a294 + languageName: node + linkType: hard + "domhandler@npm:^4.0.0, domhandler@npm:^4.2.0, domhandler@npm:^4.3.1": version: 4.3.1 resolution: "domhandler@npm:4.3.1" @@ -17863,6 +19631,16 @@ __metadata: languageName: node linkType: hard +"ecc-jsbn@npm:~0.1.1": + version: 0.1.2 + resolution: "ecc-jsbn@npm:0.1.2" + dependencies: + jsbn: "npm:~0.1.0" + safer-buffer: "npm:^2.1.0" + checksum: 10c0/6cf168bae1e2dad2e46561d9af9cbabfbf5ff592176ad4e9f0f41eaaf5fe5e10bb58147fe0a804de62b1ee9dad42c28810c88d652b21b6013c47ba8efa274ca1 + languageName: node + linkType: hard + "ecdsa-sig-formatter@npm:1.0.11, ecdsa-sig-formatter@npm:^1.0.11": version: 1.0.11 resolution: "ecdsa-sig-formatter@npm:1.0.11" @@ -17901,6 +19679,13 @@ __metadata: languageName: node linkType: hard +"emittery@npm:^0.13.1": + version: 0.13.1 + resolution: "emittery@npm:0.13.1" + checksum: 10c0/1573d0ae29ab34661b6c63251ff8f5facd24ccf6a823f19417ae8ba8c88ea450325788c67f16c99edec8de4b52ce93a10fe441ece389fd156e88ee7dab9bfa35 + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -17936,7 +19721,7 @@ __metadata: languageName: node linkType: hard -"encodeurl@npm:~1.0.2": +"encodeurl@npm:^1.0.2, encodeurl@npm:~1.0.2": version: 1.0.2 resolution: "encodeurl@npm:1.0.2" checksum: 10c0/f6c2387379a9e7c1156c1c3d4f9cb7bb11cf16dd4c1682e1f6746512564b053df5781029b6061296832b59fb22f459dbe250386d217c2f6e203601abb2ee0bec @@ -18247,6 +20032,92 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.25.0": + version: 0.25.1 + resolution: "esbuild@npm:0.25.1" + dependencies: + "@esbuild/aix-ppc64": "npm:0.25.1" + "@esbuild/android-arm": "npm:0.25.1" + "@esbuild/android-arm64": "npm:0.25.1" + "@esbuild/android-x64": "npm:0.25.1" + "@esbuild/darwin-arm64": "npm:0.25.1" + "@esbuild/darwin-x64": "npm:0.25.1" + "@esbuild/freebsd-arm64": "npm:0.25.1" + "@esbuild/freebsd-x64": "npm:0.25.1" + "@esbuild/linux-arm": "npm:0.25.1" + "@esbuild/linux-arm64": "npm:0.25.1" + "@esbuild/linux-ia32": "npm:0.25.1" + "@esbuild/linux-loong64": "npm:0.25.1" + "@esbuild/linux-mips64el": "npm:0.25.1" + "@esbuild/linux-ppc64": "npm:0.25.1" + "@esbuild/linux-riscv64": "npm:0.25.1" + "@esbuild/linux-s390x": "npm:0.25.1" + "@esbuild/linux-x64": "npm:0.25.1" + "@esbuild/netbsd-arm64": "npm:0.25.1" + "@esbuild/netbsd-x64": "npm:0.25.1" + "@esbuild/openbsd-arm64": "npm:0.25.1" + "@esbuild/openbsd-x64": "npm:0.25.1" + "@esbuild/sunos-x64": "npm:0.25.1" + "@esbuild/win32-arm64": "npm:0.25.1" + "@esbuild/win32-ia32": "npm:0.25.1" + "@esbuild/win32-x64": "npm:0.25.1" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/80fca30dd0f21aec23fdfab34f0a8d5f55df5097dd7f475f2ab561d45662c32ee306f5649071cd1a0ba0614b164c48ca3dc3ee1551a4daf204b8af90e4d893f5 + languageName: node + linkType: hard + "esbuild@npm:^0.27.1": version: 0.27.7 resolution: "esbuild@npm:0.27.7" @@ -18343,7 +20214,7 @@ __metadata: languageName: node linkType: hard -"escape-html@npm:~1.0.3": +"escape-html@npm:^1.0.3, escape-html@npm:~1.0.3": version: 1.0.3 resolution: "escape-html@npm:1.0.3" checksum: 10c0/524c739d776b36c3d29fa08a22e03e8824e3b2fd57500e5e44ecf3cc4707c34c60f9ca0781c0e33d191f2991161504c295e98f68c78fe7baa6e57081ec6ac0a3 @@ -18378,7 +20249,26 @@ __metadata: languageName: node linkType: hard -"escodegen@npm:^2.1.0": +"escodegen@npm:^1.8.1": + version: 1.14.3 + resolution: "escodegen@npm:1.14.3" + dependencies: + esprima: "npm:^4.0.1" + estraverse: "npm:^4.2.0" + esutils: "npm:^2.0.2" + optionator: "npm:^0.8.1" + source-map: "npm:~0.6.1" + dependenciesMeta: + source-map: + optional: true + bin: + escodegen: bin/escodegen.js + esgenerate: bin/esgenerate.js + checksum: 10c0/30d337803e8f44308c90267bf6192399e4b44792497c77a7506b68ab802ba6a48ebbe1ce77b219aba13dfd2de5f5e1c267e35be1ed87b2a9c3315e8b283e302a + languageName: node + linkType: hard + +"escodegen@npm:^2.0.0, escodegen@npm:^2.1.0": version: 2.1.0 resolution: "escodegen@npm:2.1.0" dependencies: @@ -18710,6 +20600,16 @@ __metadata: languageName: node linkType: hard +"esprima@npm:1.2.2": + version: 1.2.2 + resolution: "esprima@npm:1.2.2" + bin: + esparse: ./bin/esparse.js + esvalidate: ./bin/esvalidate.js + checksum: 10c0/a5a8fd359651dd8228736d7352eb7636c7765e1ec6ff8fff3f6641622039a9f51fa501969a1a4777ba4187cf9942a8d7e0367dccaff768b782bdb1a71d046abf + languageName: node + linkType: hard + "esprima@npm:^4.0.0, esprima@npm:^4.0.1": version: 4.0.1 resolution: "esprima@npm:4.0.1" @@ -18738,7 +20638,7 @@ __metadata: languageName: node linkType: hard -"estraverse@npm:^4.1.1": +"estraverse@npm:^4.1.1, estraverse@npm:^4.2.0": version: 4.3.0 resolution: "estraverse@npm:4.3.0" checksum: 10c0/9cb46463ef8a8a4905d3708a652d60122a0c20bb58dec7e0e12ab0e7235123d74214fc0141d743c381813e1b992767e2708194f6f6e0f9fd00c1b4e0887b8b6d @@ -18819,6 +20719,30 @@ __metadata: languageName: node linkType: hard +"execa@npm:^5.0.0": + version: 5.1.1 + resolution: "execa@npm:5.1.1" + dependencies: + cross-spawn: "npm:^7.0.3" + get-stream: "npm:^6.0.0" + human-signals: "npm:^2.1.0" + is-stream: "npm:^2.0.0" + merge-stream: "npm:^2.0.0" + npm-run-path: "npm:^4.0.1" + onetime: "npm:^5.1.2" + signal-exit: "npm:^3.0.3" + strip-final-newline: "npm:^2.0.0" + checksum: 10c0/c8e615235e8de4c5addf2fa4c3da3e3aa59ce975a3e83533b4f6a71750fb816a2e79610dc5f1799b6e28976c9ae86747a36a606655bf8cb414a74d8d507b304f + languageName: node + linkType: hard + +"exit@npm:^0.1.2": + version: 0.1.2 + resolution: "exit@npm:0.1.2" + checksum: 10c0/71d2ad9b36bc25bb8b104b17e830b40a08989be7f7d100b13269aaae7c3784c3e6e1e88a797e9e87523993a25ba27c8958959a554535370672cfb4d824af8989 + languageName: node + linkType: hard + "expand-template@npm:^2.0.3": version: 2.0.3 resolution: "expand-template@npm:2.0.3" @@ -18835,6 +20759,19 @@ __metadata: languageName: node linkType: hard +"expect@npm:^29.0.0, expect@npm:^29.7.0": + version: 29.7.0 + resolution: "expect@npm:29.7.0" + dependencies: + "@jest/expect-utils": "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 10c0/2eddeace66e68b8d8ee5f7be57f3014b19770caaf6815c7a08d131821da527fb8c8cb7b3dcd7c883d2d3d8d184206a4268984618032d1e4b16dc8d6596475d41 + languageName: node + linkType: hard + "exponential-backoff@npm:^3.1.1": version: 3.1.2 resolution: "exponential-backoff@npm:3.1.2" @@ -18883,6 +20820,15 @@ __metadata: languageName: node linkType: hard +"express-rate-limit@npm:^7.5.0": + version: 7.5.1 + resolution: "express-rate-limit@npm:7.5.1" + peerDependencies: + express: ">= 4.11" + checksum: 10c0/b07de84d700a2c07c4bf2f040e7558ed5a1f660f03ed5f30bf8ff7b51e98ba7a85215640e70fc48cbbb9151066ea51239d9a1b41febc9b84d98c7915b0186161 + languageName: node + linkType: hard + "express-rate-limit@npm:^8.2.2": version: 8.4.1 resolution: "express-rate-limit@npm:8.4.1" @@ -18949,7 +20895,7 @@ __metadata: languageName: node linkType: hard -"extend@npm:3.0.2, extend@npm:^3.0.0, extend@npm:^3.0.2": +"extend@npm:3.0.2, extend@npm:^3.0.0, extend@npm:^3.0.2, extend@npm:~3.0.2": version: 3.0.2 resolution: "extend@npm:3.0.2" checksum: 10c0/73bf6e27406e80aa3e85b0d1c4fd987261e628064e170ca781125c0b635a3dabad5e05adbf07595ea0cf1e6c5396cacb214af933da7cbaf24fe75ff14818e8f9 @@ -18974,6 +20920,20 @@ __metadata: languageName: node linkType: hard +"extsprintf@npm:1.3.0": + version: 1.3.0 + resolution: "extsprintf@npm:1.3.0" + checksum: 10c0/f75114a8388f0cbce68e277b6495dc3930db4dde1611072e4a140c24e204affd77320d004b947a132e9a3b97b8253017b2b62dce661975fb0adced707abf1ab5 + languageName: node + linkType: hard + +"extsprintf@npm:^1.2.0": + version: 1.4.1 + resolution: "extsprintf@npm:1.4.1" + checksum: 10c0/e10e2769985d0e9b6c7199b053a9957589d02e84de42832c295798cb422a025e6d4a92e0259c1fb4d07090f5bfde6b55fd9f880ac5855bd61d775f8ab75a7ab0 + languageName: node + linkType: hard + "fast-copy@npm:^3.0.2": version: 3.0.2 resolution: "fast-copy@npm:3.0.2" @@ -19029,7 +20989,7 @@ __metadata: languageName: node linkType: hard -"fast-levenshtein@npm:^2.0.6": +"fast-levenshtein@npm:^2.0.6, fast-levenshtein@npm:~2.0.6": version: 2.0.6 resolution: "fast-levenshtein@npm:2.0.6" checksum: 10c0/111972b37338bcb88f7d9e2c5907862c280ebf4234433b95bc611e518d192ccb2d38119c4ac86e26b668d75f7f3894f4ff5c4982899afced7ca78633b08287c4 @@ -19157,6 +21117,15 @@ __metadata: languageName: node linkType: hard +"fb-watchman@npm:^2.0.0": + version: 2.0.2 + resolution: "fb-watchman@npm:2.0.2" + dependencies: + bser: "npm:2.1.1" + checksum: 10c0/feae89ac148adb8f6ae8ccd87632e62b13563e6fb114cacb5265c51f585b17e2e268084519fb2edd133872f1d47a18e6bfd7e5e08625c0d41b93149694187581 + languageName: node + linkType: hard + "fdir@npm:^6.4.3": version: 6.4.3 resolution: "fdir@npm:6.4.3" @@ -19292,7 +21261,7 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^4.1.0": +"find-up@npm:^4.0.0, find-up@npm:^4.1.0": version: 4.1.0 resolution: "find-up@npm:4.1.0" dependencies: @@ -19344,13 +21313,13 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.11, follow-redirects@npm:^1.15.6": - version: 1.16.0 - resolution: "follow-redirects@npm:1.16.0" +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.6": + version: 1.15.9 + resolution: "follow-redirects@npm:1.15.9" peerDependenciesMeta: debug: optional: true - checksum: 10c0/a1e2900163e6f1b4d1ed5c221b607f41decbab65534c63fe7e287e40a5d552a6496e7d9d7d976fa4ba77b4c51c11e5e9f683f10b43011ea11e442ff128d0e181 + checksum: 10c0/5829165bd112c3c0e82be6c15b1a58fa9dcfaede3b3c54697a82fe4a62dd5ae5e8222956b448d2f98e331525f05d00404aba7d696de9e761ef6e42fdc780244f languageName: node linkType: hard @@ -19380,6 +21349,13 @@ __metadata: languageName: node linkType: hard +"forever-agent@npm:~0.6.1": + version: 0.6.1 + resolution: "forever-agent@npm:0.6.1" + checksum: 10c0/364f7f5f7d93ab661455351ce116a67877b66f59aca199559a999bd39e3cfadbfbfacc10415a915255e2210b30c23febe9aec3ca16bf2d1ff11c935a1000e24c + languageName: node + linkType: hard + "fork-ts-checker-webpack-plugin@npm:^6.5.0": version: 6.5.3 resolution: "fork-ts-checker-webpack-plugin@npm:6.5.3" @@ -19434,6 +21410,13 @@ __metadata: languageName: node linkType: hard +"form-data-encoder@npm:^1.7.2": + version: 1.9.0 + resolution: "form-data-encoder@npm:1.9.0" + checksum: 10c0/e162be1203abd5a8a8855cbdef2d92ee259416690687fec68d59b77b674b0c553fdbaf2a1128953a842c1f446b5a811deed996c473f5558fd0ec36bcb505f011 + languageName: node + linkType: hard + "form-data@npm:^2.5.0": version: 2.5.3 resolution: "form-data@npm:2.5.3" @@ -19460,6 +21443,17 @@ __metadata: languageName: node linkType: hard +"form-data@npm:~2.3.2": + version: 2.3.3 + resolution: "form-data@npm:2.3.3" + dependencies: + asynckit: "npm:^0.4.0" + combined-stream: "npm:^1.0.6" + mime-types: "npm:^2.1.12" + checksum: 10c0/706ef1e5649286b6a61e5bb87993a9842807fd8f149cd2548ee807ea4fb882247bdf7f6e64ac4720029c0cd5c80343de0e22eee1dc9e9882e12db9cc7bc016a4 + languageName: node + linkType: hard + "format@npm:^0.2.0": version: 0.2.2 resolution: "format@npm:0.2.2" @@ -19467,6 +21461,16 @@ __metadata: languageName: node linkType: hard +"formdata-node@npm:^4.3.3": + version: 4.4.1 + resolution: "formdata-node@npm:4.4.1" + dependencies: + node-domexception: "npm:1.0.0" + web-streams-polyfill: "npm:4.0.0-beta.3" + checksum: 10c0/74151e7b228ffb33b565cec69182694ad07cc3fdd9126a8240468bb70a8ba66e97e097072b60bcb08729b24c7ce3fd3e0bd7f1f80df6f9f662b9656786e76f6a + languageName: node + linkType: hard + "formidable@npm:^2.1.2": version: 2.1.2 resolution: "formidable@npm:2.1.2" @@ -19479,7 +21483,7 @@ __metadata: languageName: node linkType: hard -"formstream@npm:^1.5.2": +"formstream@npm:^1.1.1, formstream@npm:^1.5.2": version: 1.5.2 resolution: "formstream@npm:1.5.2" dependencies: @@ -19553,6 +21557,18 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:9.1.0, fs-extra@npm:^9.0.0": + version: 9.1.0 + resolution: "fs-extra@npm:9.1.0" + dependencies: + at-least-node: "npm:^1.0.0" + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 10c0/9b808bd884beff5cb940773018179a6b94a966381d005479f00adda6b44e5e3d4abf765135773d849cc27efe68c349e4a7b86acd7d3306d5932c14f3a4b17a92 + languageName: node + linkType: hard + "fs-extra@npm:^10.0.0": version: 10.1.0 resolution: "fs-extra@npm:10.1.0" @@ -19586,18 +21602,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^9.0.0": - version: 9.1.0 - resolution: "fs-extra@npm:9.1.0" - dependencies: - at-least-node: "npm:^1.0.0" - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: 10c0/9b808bd884beff5cb940773018179a6b94a966381d005479f00adda6b44e5e3d4abf765135773d849cc27efe68c349e4a7b86acd7d3306d5932c14f3a4b17a92 - languageName: node - linkType: hard - "fs-minipass@npm:^2.0.0, fs-minipass@npm:^2.1.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" @@ -19647,7 +21651,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:~2.3.2": +"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2": version: 2.3.3 resolution: "fsevents@npm:2.3.3" dependencies: @@ -19666,7 +21670,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": +"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" dependencies: @@ -19775,6 +21779,13 @@ __metadata: languageName: node linkType: hard +"gensync@npm:^1.0.0-beta.2": + version: 1.0.0-beta.2 + resolution: "gensync@npm:1.0.0-beta.2" + checksum: 10c0/782aba6cba65b1bb5af3b095d96249d20edbe8df32dbf4696fd49be2583faf676173bf4809386588828e4dd76a3354fcbeb577bab1c833ccd9fc4577f26103f8 + languageName: node + linkType: hard + "get-caller-file@npm:^2.0.5": version: 2.0.5 resolution: "get-caller-file@npm:2.0.5" @@ -19838,6 +21849,13 @@ __metadata: languageName: node linkType: hard +"get-stream@npm:^6.0.0": + version: 6.0.1 + resolution: "get-stream@npm:6.0.1" + checksum: 10c0/49825d57d3fd6964228e6200a58169464b8e8970489b3acdc24906c782fb7f01f9f56f8e6653c4a50713771d6658f7cfe051e5eb8c12e334138c9c918b296341 + languageName: node + linkType: hard + "get-symbol-description@npm:^1.1.0": version: 1.1.0 resolution: "get-symbol-description@npm:1.1.0" @@ -19885,6 +21903,15 @@ __metadata: languageName: node linkType: hard +"getpass@npm:^0.1.1": + version: 0.1.7 + resolution: "getpass@npm:0.1.7" + dependencies: + assert-plus: "npm:^1.0.0" + checksum: 10c0/c13f8530ecf16fc509f3fa5cd8dd2129ffa5d0c7ccdf5728b6022d52954c2d24be3706b4cdf15333eec52f1fbb43feb70a01dabc639d1d10071e371da8aaa52f + languageName: node + linkType: hard + "git-up@npm:^7.0.0": version: 7.0.0 resolution: "git-up@npm:7.0.0" @@ -20307,6 +22334,23 @@ __metadata: languageName: node linkType: hard +"har-schema@npm:^2.0.0": + version: 2.0.0 + resolution: "har-schema@npm:2.0.0" + checksum: 10c0/3856cb76152658e0002b9c2b45b4360bb26b3e832c823caed8fcf39a01096030bf09fa5685c0f7b0f2cb3ecba6e9dce17edaf28b64a423d6201092e6be56e592 + languageName: node + linkType: hard + +"har-validator@npm:~5.1.3": + version: 5.1.5 + resolution: "har-validator@npm:5.1.5" + dependencies: + ajv: "npm:^6.12.3" + har-schema: "npm:^2.0.0" + checksum: 10c0/f1d606eb1021839e3a905be5ef7cca81c2256a6be0748efb8fefc14312214f9e6c15d7f2eaf37514104071207d84f627b68bb9f6178703da4e06fbd1a0649a5e + languageName: node + linkType: hard + "harmony-reflect@npm:^1.4.6": version: 1.6.2 resolution: "harmony-reflect@npm:1.6.2" @@ -20659,6 +22703,15 @@ __metadata: languageName: node linkType: hard +"html-encoding-sniffer@npm:^3.0.0": + version: 3.0.0 + resolution: "html-encoding-sniffer@npm:3.0.0" + dependencies: + whatwg-encoding: "npm:^2.0.0" + checksum: 10c0/b17b3b0fb5d061d8eb15121c3b0b536376c3e295ecaf09ba48dd69c6b6c957839db124fe1e2b3f11329753a4ee01aa7dedf63b7677999e86da17fbbdd82c5386 + languageName: node + linkType: hard + "html-encoding-sniffer@npm:^4.0.0": version: 4.0.0 resolution: "html-encoding-sniffer@npm:4.0.0" @@ -20675,6 +22728,13 @@ __metadata: languageName: node linkType: hard +"html-escaper@npm:^2.0.0": + version: 2.0.2 + resolution: "html-escaper@npm:2.0.2" + checksum: 10c0/208e8a12de1a6569edbb14544f4567e6ce8ecc30b9394fcaa4e7bb1e60c12a7c9a1ed27e31290817157e8626f3a4f29e76c8747030822eb84a6abb15c255f0a0 + languageName: node + linkType: hard + "html-minifier-terser@npm:^6.0.2": version: 6.1.0 resolution: "html-minifier-terser@npm:6.1.0" @@ -20732,6 +22792,16 @@ __metadata: languageName: node linkType: hard +"http-assert@npm:^1.3.0": + version: 1.5.0 + resolution: "http-assert@npm:1.5.0" + dependencies: + deep-equal: "npm:~1.0.1" + http-errors: "npm:~1.8.0" + checksum: 10c0/7b4e631114a1a77654f9ba3feb96da305ddbdeb42112fe384b7b3249c7141e460d7177970155bea6e54e655a04850415b744b452c1fe5052eba6f4186d16b095 + languageName: node + linkType: hard + "http-cache-semantics@npm:^4.1.0, http-cache-semantics@npm:^4.1.1": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" @@ -20757,6 +22827,19 @@ __metadata: languageName: node linkType: hard +"http-errors@npm:^1.6.3, http-errors@npm:~1.8.0": + version: 1.8.1 + resolution: "http-errors@npm:1.8.1" + dependencies: + depd: "npm:~1.1.2" + inherits: "npm:2.0.4" + setprototypeof: "npm:1.2.0" + statuses: "npm:>= 1.5.0 < 2" + toidentifier: "npm:1.0.1" + checksum: 10c0/f01aeecd76260a6fe7f08e192fcbe9b2f39ed20fc717b852669a69930167053b01790998275c6297d44f435cf0e30edd50c05223d1bec9bc484e6cf35b2d6f43 + languageName: node + linkType: hard + "http-errors@npm:~1.6.2": version: 1.6.3 resolution: "http-errors@npm:1.6.3" @@ -20853,6 +22936,17 @@ __metadata: languageName: node linkType: hard +"http-signature@npm:~1.2.0": + version: 1.2.0 + resolution: "http-signature@npm:1.2.0" + dependencies: + assert-plus: "npm:^1.0.0" + jsprim: "npm:^1.2.2" + sshpk: "npm:^1.7.0" + checksum: 10c0/582f7af7f354429e1fb19b3bbb9d35520843c69bb30a25b88ca3c5c2c10715f20ae7924e20cffbed220b1d3a726ef4fe8ccc48568d5744db87be9a79887d6733 + languageName: node + linkType: hard + "http2-wrapper@npm:^2.2.1": version: 2.2.1 resolution: "http2-wrapper@npm:2.2.1" @@ -20899,6 +22993,13 @@ __metadata: languageName: node linkType: hard +"human-signals@npm:^2.1.0": + version: 2.1.0 + resolution: "human-signals@npm:2.1.0" + checksum: 10c0/695edb3edfcfe9c8b52a76926cd31b36978782062c0ed9b1192b36bebc75c4c87c82e178dfcb0ed0fc27ca59d434198aac0bd0be18f5781ded775604db22304a + languageName: node + linkType: hard + "humanize-duration@npm:^3.25.1": version: 3.32.1 resolution: "humanize-duration@npm:3.32.1" @@ -21069,6 +23170,18 @@ __metadata: languageName: node linkType: hard +"import-local@npm:^3.0.2": + version: 3.2.0 + resolution: "import-local@npm:3.2.0" + dependencies: + pkg-dir: "npm:^4.2.0" + resolve-cwd: "npm:^3.0.0" + bin: + import-local-fixture: fixtures/cli.js + checksum: 10c0/94cd6367a672b7e0cb026970c85b76902d2710a64896fa6de93bd5c571dd03b228c5759308959de205083e3b1c61e799f019c9e36ee8e9c523b993e1057f0433 + languageName: node + linkType: hard + "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -21090,6 +23203,19 @@ __metadata: languageName: node linkType: hard +"infinispan@npm:^0.12.0": + version: 0.12.0 + resolution: "infinispan@npm:0.12.0" + dependencies: + buffer-xor: "npm:^2.0.2" + log4js: "npm:^6.4.6" + protobufjs: "npm:^7.0.0" + underscore: "npm:^1.13.3" + urllib: "npm:^3.23.0" + checksum: 10c0/afca2490bff7aa2e0767f8afe3d0ece2f7df8f63fc476b7e3d45ba01c15cd637d89074eec44efc3bba5085f5ebfe579c2330bde3f5ff5de05ffc957653ad2256 + languageName: node + linkType: hard + "infinispan@npm:^0.13.0": version: 0.13.0 resolution: "infinispan@npm:0.13.0" @@ -21114,7 +23240,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -21486,6 +23612,13 @@ __metadata: languageName: node linkType: hard +"is-generator-fn@npm:^2.0.0": + version: 2.1.0 + resolution: "is-generator-fn@npm:2.1.0" + checksum: 10c0/2957cab387997a466cd0bf5c1b6047bd21ecb32bdcfd8996b15747aa01002c1c88731802f1b3d34ac99f4f6874b626418bd118658cf39380fe5fff32a3af9c4d + languageName: node + linkType: hard + "is-generator-function@npm:^1.0.10, is-generator-function@npm:^1.0.7": version: 1.1.0 resolution: "is-generator-function@npm:1.1.0" @@ -21772,6 +23905,13 @@ __metadata: languageName: node linkType: hard +"is-typedarray@npm:~1.0.0": + version: 1.0.0 + resolution: "is-typedarray@npm:1.0.0" + checksum: 10c0/4c096275ba041a17a13cca33ac21c16bc4fd2d7d7eb94525e7cd2c2f2c1a3ab956e37622290642501ff4310601e413b675cf399ad6db49855527d2163b3eeeec + languageName: node + linkType: hard + "is-unicode-supported@npm:^0.1.0": version: 0.1.0 resolution: "is-unicode-supported@npm:0.1.0" @@ -21955,6 +24095,78 @@ __metadata: languageName: node linkType: hard +"isstream@npm:~0.1.2": + version: 0.1.2 + resolution: "isstream@npm:0.1.2" + checksum: 10c0/a6686a878735ca0a48e0d674dd6d8ad31aedfaf70f07920da16ceadc7577b46d67179a60b313f2e6860cb097a2c2eb3cbd0b89e921ae89199a59a17c3273d66f + languageName: node + linkType: hard + +"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": + version: 3.2.2 + resolution: "istanbul-lib-coverage@npm:3.2.2" + checksum: 10c0/6c7ff2106769e5f592ded1fb418f9f73b4411fd5a084387a5410538332b6567cd1763ff6b6cadca9b9eb2c443cce2f7ea7d7f1b8d315f9ce58539793b1e0922b + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^5.0.4": + version: 5.2.1 + resolution: "istanbul-lib-instrument@npm:5.2.1" + dependencies: + "@babel/core": "npm:^7.12.3" + "@babel/parser": "npm:^7.14.7" + "@istanbuljs/schema": "npm:^0.1.2" + istanbul-lib-coverage: "npm:^3.2.0" + semver: "npm:^6.3.0" + checksum: 10c0/8a1bdf3e377dcc0d33ec32fe2b6ecacdb1e4358fd0eb923d4326bb11c67622c0ceb99600a680f3dad5d29c66fc1991306081e339b4d43d0b8a2ab2e1d910a6ee + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^6.0.0": + version: 6.0.3 + resolution: "istanbul-lib-instrument@npm:6.0.3" + dependencies: + "@babel/core": "npm:^7.23.9" + "@babel/parser": "npm:^7.23.9" + "@istanbuljs/schema": "npm:^0.1.3" + istanbul-lib-coverage: "npm:^3.2.0" + semver: "npm:^7.5.4" + checksum: 10c0/a1894e060dd2a3b9f046ffdc87b44c00a35516f5e6b7baf4910369acca79e506fc5323a816f811ae23d82334b38e3ddeb8b3b331bd2c860540793b59a8689128 + languageName: node + linkType: hard + +"istanbul-lib-report@npm:^3.0.0": + version: 3.0.1 + resolution: "istanbul-lib-report@npm:3.0.1" + dependencies: + istanbul-lib-coverage: "npm:^3.0.0" + make-dir: "npm:^4.0.0" + supports-color: "npm:^7.1.0" + checksum: 10c0/84323afb14392de8b6a5714bd7e9af845cfbd56cfe71ed276cda2f5f1201aea673c7111901227ee33e68e4364e288d73861eb2ed48f6679d1e69a43b6d9b3ba7 + languageName: node + linkType: hard + +"istanbul-lib-source-maps@npm:^4.0.0": + version: 4.0.1 + resolution: "istanbul-lib-source-maps@npm:4.0.1" + dependencies: + debug: "npm:^4.1.1" + istanbul-lib-coverage: "npm:^3.0.0" + source-map: "npm:^0.6.1" + checksum: 10c0/19e4cc405016f2c906dff271a76715b3e881fa9faeb3f09a86cb99b8512b3a5ed19cadfe0b54c17ca0e54c1142c9c6de9330d65506e35873994e06634eebeb66 + languageName: node + linkType: hard + +"istanbul-reports@npm:^3.1.3": + version: 3.1.7 + resolution: "istanbul-reports@npm:3.1.7" + dependencies: + html-escaper: "npm:^2.0.0" + istanbul-lib-report: "npm:^3.0.0" + checksum: 10c0/a379fadf9cf8dc5dfe25568115721d4a7eb82fbd50b005a6672aff9c6989b20cc9312d7865814e0859cd8df58cbf664482e1d3604be0afde1f7fc3ccc1394a51 + languageName: node + linkType: hard + "iterall@npm:^1.2.1, iterall@npm:^1.3.0": version: 1.3.0 resolution: "iterall@npm:1.3.0" @@ -21996,6 +24208,109 @@ __metadata: languageName: node linkType: hard +"jest-changed-files@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-changed-files@npm:29.7.0" + dependencies: + execa: "npm:^5.0.0" + jest-util: "npm:^29.7.0" + p-limit: "npm:^3.1.0" + checksum: 10c0/e071384d9e2f6bb462231ac53f29bff86f0e12394c1b49ccafbad225ce2ab7da226279a8a94f421949920bef9be7ef574fd86aee22e8adfa149be73554ab828b + languageName: node + linkType: hard + +"jest-circus@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-circus@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/expect": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + co: "npm:^4.6.0" + dedent: "npm:^1.0.0" + is-generator-fn: "npm:^2.0.0" + jest-each: "npm:^29.7.0" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + p-limit: "npm:^3.1.0" + pretty-format: "npm:^29.7.0" + pure-rand: "npm:^6.0.0" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.3" + checksum: 10c0/8d15344cf7a9f14e926f0deed64ed190c7a4fa1ed1acfcd81e4cc094d3cc5bf7902ebb7b874edc98ada4185688f90c91e1747e0dfd7ac12463b097968ae74b5e + languageName: node + linkType: hard + +"jest-cli@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-cli@npm:29.7.0" + dependencies: + "@jest/core": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + chalk: "npm:^4.0.0" + create-jest: "npm:^29.7.0" + exit: "npm:^0.1.2" + import-local: "npm:^3.0.2" + jest-config: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + yargs: "npm:^17.3.1" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 10c0/a658fd55050d4075d65c1066364595962ead7661711495cfa1dfeecf3d6d0a8ffec532f3dbd8afbb3e172dd5fd2fb2e813c5e10256e7cf2fea766314942fb43a + languageName: node + linkType: hard + +"jest-config@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-config@npm:29.7.0" + dependencies: + "@babel/core": "npm:^7.11.6" + "@jest/test-sequencer": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + babel-jest: "npm:^29.7.0" + chalk: "npm:^4.0.0" + ci-info: "npm:^3.2.0" + deepmerge: "npm:^4.2.2" + glob: "npm:^7.1.3" + graceful-fs: "npm:^4.2.9" + jest-circus: "npm:^29.7.0" + jest-environment-node: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-runner: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + parse-json: "npm:^5.2.0" + pretty-format: "npm:^29.7.0" + slash: "npm:^3.0.0" + strip-json-comments: "npm:^3.1.1" + peerDependencies: + "@types/node": "*" + ts-node: ">=9.0.0" + peerDependenciesMeta: + "@types/node": + optional: true + ts-node: + optional: true + checksum: 10c0/bab23c2eda1fff06e0d104b00d6adfb1d1aabb7128441899c9bff2247bd26710b050a5364281ce8d52b46b499153bf7e3ee88b19831a8f3451f1477a0246a0f1 + languageName: node + linkType: hard + "jest-css-modules@npm:^2.1.0": version: 2.1.0 resolution: "jest-css-modules@npm:2.1.0" @@ -22005,6 +24320,167 @@ __metadata: languageName: node linkType: hard +"jest-diff@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-diff@npm:29.7.0" + dependencies: + chalk: "npm:^4.0.0" + diff-sequences: "npm:^29.6.3" + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: 10c0/89a4a7f182590f56f526443dde69acefb1f2f0c9e59253c61d319569856c4931eae66b8a3790c443f529267a0ddba5ba80431c585deed81827032b2b2a1fc999 + languageName: node + linkType: hard + +"jest-docblock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-docblock@npm:29.7.0" + dependencies: + detect-newline: "npm:^3.0.0" + checksum: 10c0/d932a8272345cf6b6142bb70a2bb63e0856cc0093f082821577ea5bdf4643916a98744dfc992189d2b1417c38a11fa42466f6111526bc1fb81366f56410f3be9 + languageName: node + linkType: hard + +"jest-each@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-each@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + chalk: "npm:^4.0.0" + jest-get-type: "npm:^29.6.3" + jest-util: "npm:^29.7.0" + pretty-format: "npm:^29.7.0" + checksum: 10c0/f7f9a90ebee80cc688e825feceb2613627826ac41ea76a366fa58e669c3b2403d364c7c0a74d862d469b103c843154f8456d3b1c02b487509a12afa8b59edbb4 + languageName: node + linkType: hard + +"jest-environment-jsdom@npm:^29.0.2": + version: 29.7.0 + resolution: "jest-environment-jsdom@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/jsdom": "npm:^20.0.0" + "@types/node": "npm:*" + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jsdom: "npm:^20.0.0" + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 10c0/139b94e2c8ec1bb5a46ce17df5211da65ce867354b3fd4e00fa6a0d1da95902df4cf7881273fc6ea937e5c325d39d6773f0d41b6c469363334de9d489d2c321f + languageName: node + linkType: hard + +"jest-environment-node@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-environment-node@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 10c0/61f04fec077f8b1b5c1a633e3612fc0c9aa79a0ab7b05600683428f1e01a4d35346c474bde6f439f9fcc1a4aa9a2861ff852d079a43ab64b02105d1004b2592b + languageName: node + linkType: hard + +"jest-get-type@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-get-type@npm:29.6.3" + checksum: 10c0/552e7a97a983d3c2d4e412a44eb7de0430ff773dd99f7500962c268d6dfbfa431d7d08f919c9d960530e5f7f78eb47f267ad9b318265e5092b3ff9ede0db7c2b + languageName: node + linkType: hard + +"jest-haste-map@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-haste-map@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + "@types/graceful-fs": "npm:^4.1.3" + "@types/node": "npm:*" + anymatch: "npm:^3.0.3" + fb-watchman: "npm:^2.0.0" + fsevents: "npm:^2.3.2" + graceful-fs: "npm:^4.2.9" + jest-regex-util: "npm:^29.6.3" + jest-util: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + walker: "npm:^1.0.8" + dependenciesMeta: + fsevents: + optional: true + checksum: 10c0/2683a8f29793c75a4728787662972fedd9267704c8f7ef9d84f2beed9a977f1cf5e998c07b6f36ba5603f53cb010c911fe8cd0ac9886e073fe28ca66beefd30c + languageName: node + linkType: hard + +"jest-leak-detector@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-leak-detector@npm:29.7.0" + dependencies: + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: 10c0/71bb9f77fc489acb842a5c7be030f2b9acb18574dc9fb98b3100fc57d422b1abc55f08040884bd6e6dbf455047a62f7eaff12aa4058f7cbdc11558718ca6a395 + languageName: node + linkType: hard + +"jest-matcher-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-matcher-utils@npm:29.7.0" + dependencies: + chalk: "npm:^4.0.0" + jest-diff: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: 10c0/0d0e70b28fa5c7d4dce701dc1f46ae0922102aadc24ed45d594dd9b7ae0a8a6ef8b216718d1ab79e451291217e05d4d49a82666e1a3cc2b428b75cd9c933244e + languageName: node + linkType: hard + +"jest-message-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-message-util@npm:29.7.0" + dependencies: + "@babel/code-frame": "npm:^7.12.13" + "@jest/types": "npm:^29.6.3" + "@types/stack-utils": "npm:^2.0.0" + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + micromatch: "npm:^4.0.4" + pretty-format: "npm:^29.7.0" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.3" + checksum: 10c0/850ae35477f59f3e6f27efac5215f706296e2104af39232bb14e5403e067992afb5c015e87a9243ec4d9df38525ef1ca663af9f2f4766aa116f127247008bd22 + languageName: node + linkType: hard + +"jest-mock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-mock@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + jest-util: "npm:^29.7.0" + checksum: 10c0/7b9f8349ee87695a309fe15c46a74ab04c853369e5c40952d68061d9dc3159a0f0ed73e215f81b07ee97a9faaf10aebe5877a9d6255068a0977eae6a9ff1d5ac + languageName: node + linkType: hard + +"jest-pnp-resolver@npm:^1.2.2": + version: 1.2.3 + resolution: "jest-pnp-resolver@npm:1.2.3" + peerDependencies: + jest-resolve: "*" + peerDependenciesMeta: + jest-resolve: + optional: true + checksum: 10c0/86eec0c78449a2de733a6d3e316d49461af6a858070e113c97f75fb742a48c2396ea94150cbca44159ffd4a959f743a47a8b37a792ef6fdad2cf0a5cba973fac + languageName: node + linkType: hard + "jest-regex-util@npm:30.0.1": version: 30.0.1 resolution: "jest-regex-util@npm:30.0.1" @@ -22012,6 +24488,127 @@ __metadata: languageName: node linkType: hard +"jest-regex-util@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-regex-util@npm:29.6.3" + checksum: 10c0/4e33fb16c4f42111159cafe26397118dcfc4cf08bc178a67149fb05f45546a91928b820894572679d62559839d0992e21080a1527faad65daaae8743a5705a3b + languageName: node + linkType: hard + +"jest-resolve-dependencies@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve-dependencies@npm:29.7.0" + dependencies: + jest-regex-util: "npm:^29.6.3" + jest-snapshot: "npm:^29.7.0" + checksum: 10c0/b6e9ad8ae5b6049474118ea6441dfddd385b6d1fc471db0136f7c8fbcfe97137a9665e4f837a9f49f15a29a1deb95a14439b7aec812f3f99d08f228464930f0d + languageName: node + linkType: hard + +"jest-resolve@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve@npm:29.7.0" + dependencies: + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" + jest-pnp-resolver: "npm:^1.2.2" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + resolve: "npm:^1.20.0" + resolve.exports: "npm:^2.0.0" + slash: "npm:^3.0.0" + checksum: 10c0/59da5c9c5b50563e959a45e09e2eace783d7f9ac0b5dcc6375dea4c0db938d2ebda97124c8161310082760e8ebbeff9f6b177c15ca2f57fb424f637a5d2adb47 + languageName: node + linkType: hard + +"jest-runner@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runner@npm:29.7.0" + dependencies: + "@jest/console": "npm:^29.7.0" + "@jest/environment": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + emittery: "npm:^0.13.1" + graceful-fs: "npm:^4.2.9" + jest-docblock: "npm:^29.7.0" + jest-environment-node: "npm:^29.7.0" + jest-haste-map: "npm:^29.7.0" + jest-leak-detector: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-resolve: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-watcher: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" + p-limit: "npm:^3.1.0" + source-map-support: "npm:0.5.13" + checksum: 10c0/2194b4531068d939f14c8d3274fe5938b77fa73126aedf9c09ec9dec57d13f22c72a3b5af01ac04f5c1cf2e28d0ac0b4a54212a61b05f10b5d6b47f2a1097bb4 + languageName: node + linkType: hard + +"jest-runtime@npm:^29.0.2, jest-runtime@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runtime@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/globals": "npm:^29.7.0" + "@jest/source-map": "npm:^29.6.3" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + cjs-module-lexer: "npm:^1.0.0" + collect-v8-coverage: "npm:^1.0.0" + glob: "npm:^7.1.3" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-mock: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + slash: "npm:^3.0.0" + strip-bom: "npm:^4.0.0" + checksum: 10c0/7cd89a1deda0bda7d0941835434e44f9d6b7bd50b5c5d9b0fc9a6c990b2d4d2cab59685ab3cb2850ed4cc37059f6de903af5a50565d7f7f1192a77d3fd6dd2a6 + languageName: node + linkType: hard + +"jest-snapshot@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-snapshot@npm:29.7.0" + dependencies: + "@babel/core": "npm:^7.11.6" + "@babel/generator": "npm:^7.7.2" + "@babel/plugin-syntax-jsx": "npm:^7.7.2" + "@babel/plugin-syntax-typescript": "npm:^7.7.2" + "@babel/types": "npm:^7.3.3" + "@jest/expect-utils": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + babel-preset-current-node-syntax: "npm:^1.0.0" + chalk: "npm:^4.0.0" + expect: "npm:^29.7.0" + graceful-fs: "npm:^4.2.9" + jest-diff: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + natural-compare: "npm:^1.4.0" + pretty-format: "npm:^29.7.0" + semver: "npm:^7.5.3" + checksum: 10c0/6e9003c94ec58172b4a62864a91c0146513207bedf4e0a06e1e2ac70a4484088a2683e3a0538d8ea913bcfd53dc54a9b98a98cdfa562e7fe1d1339aeae1da570 + languageName: node + linkType: hard + "jest-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-util@npm:29.7.0" @@ -22026,6 +24623,36 @@ __metadata: languageName: node linkType: hard +"jest-validate@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-validate@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + camelcase: "npm:^6.2.0" + chalk: "npm:^4.0.0" + jest-get-type: "npm:^29.6.3" + leven: "npm:^3.1.0" + pretty-format: "npm:^29.7.0" + checksum: 10c0/a20b930480c1ed68778c739f4739dce39423131bc070cd2505ddede762a5570a256212e9c2401b7ae9ba4d7b7c0803f03c5b8f1561c62348213aba18d9dbece2 + languageName: node + linkType: hard + +"jest-watcher@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-watcher@npm:29.7.0" + dependencies: + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + ansi-escapes: "npm:^4.2.1" + chalk: "npm:^4.0.0" + emittery: "npm:^0.13.1" + jest-util: "npm:^29.7.0" + string-length: "npm:^4.0.1" + checksum: 10c0/ec6c75030562fc8f8c727cb8f3b94e75d831fc718785abfc196e1f2a2ebc9a2e38744a15147170039628a853d77a3b695561ce850375ede3a4ee6037a2574567 + languageName: node + linkType: hard + "jest-worker@npm:^27.4.5": version: 27.5.1 resolution: "jest-worker@npm:27.5.1" @@ -22049,6 +24676,25 @@ __metadata: languageName: node linkType: hard +"jest@npm:^29.7.0": + version: 29.7.0 + resolution: "jest@npm:29.7.0" + dependencies: + "@jest/core": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + import-local: "npm:^3.0.2" + jest-cli: "npm:^29.7.0" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 10c0/f40eb8171cf147c617cc6ada49d062fbb03b4da666cb8d39cdbfb739a7d75eea4c3ca150fb072d0d273dce0c753db4d0467d54906ad0293f59c54f9db4a09d8b + languageName: node + linkType: hard + "jiti@npm:2.4.2, jiti@npm:^2.4.2": version: 2.4.2 resolution: "jiti@npm:2.4.2" @@ -22072,6 +24718,13 @@ __metadata: languageName: node linkType: hard +"jose@npm:^4.15.9": + version: 4.15.9 + resolution: "jose@npm:4.15.9" + checksum: 10c0/4ed4ddf4a029db04bd167f2215f65d7245e4dc5f36d7ac3c0126aab38d66309a9e692f52df88975d99429e357e5fd8bab340ff20baab544d17684dd1d940a0f4 + languageName: node + linkType: hard + "jose@npm:^5.0.0": version: 5.10.0 resolution: "jose@npm:5.10.0" @@ -22171,6 +24824,13 @@ __metadata: languageName: node linkType: hard +"jsbn@npm:~0.1.0": + version: 0.1.1 + resolution: "jsbn@npm:0.1.1" + checksum: 10c0/e046e05c59ff880ee4ef68902dbdcb6d2f3c5d60c357d4d68647dc23add556c31c0e5f41bdb7e69e793dd63468bd9e085da3636341048ef577b18f5b713877c0 + languageName: node + linkType: hard + "jsdoc@npm:^4.0.2": version: 4.0.5 resolution: "jsdoc@npm:4.0.5" @@ -22196,6 +24856,45 @@ __metadata: languageName: node linkType: hard +"jsdom@npm:^20.0.0": + version: 20.0.3 + resolution: "jsdom@npm:20.0.3" + dependencies: + abab: "npm:^2.0.6" + acorn: "npm:^8.8.1" + acorn-globals: "npm:^7.0.0" + cssom: "npm:^0.5.0" + cssstyle: "npm:^2.3.0" + data-urls: "npm:^3.0.2" + decimal.js: "npm:^10.4.2" + domexception: "npm:^4.0.0" + escodegen: "npm:^2.0.0" + form-data: "npm:^4.0.0" + html-encoding-sniffer: "npm:^3.0.0" + http-proxy-agent: "npm:^5.0.0" + https-proxy-agent: "npm:^5.0.1" + is-potential-custom-element-name: "npm:^1.0.1" + nwsapi: "npm:^2.2.2" + parse5: "npm:^7.1.1" + saxes: "npm:^6.0.0" + symbol-tree: "npm:^3.2.4" + tough-cookie: "npm:^4.1.2" + w3c-xmlserializer: "npm:^4.0.0" + webidl-conversions: "npm:^7.0.0" + whatwg-encoding: "npm:^2.0.0" + whatwg-mimetype: "npm:^3.0.0" + whatwg-url: "npm:^11.0.0" + ws: "npm:^8.11.0" + xml-name-validator: "npm:^4.0.0" + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 10c0/b109073bb826a966db7828f46cb1d7371abecd30f182b143c52be5fe1ed84513bbbe995eb3d157241681fcd18331381e61e3dc004d4949f3a63bca02f6214902 + languageName: node + linkType: hard + "jsdom@npm:^26.0.0": version: 26.0.0 resolution: "jsdom@npm:26.0.0" @@ -22337,6 +25036,13 @@ __metadata: languageName: node linkType: hard +"json-schema@npm:0.4.0, json-schema@npm:^0.4.0": + version: 0.4.0 + resolution: "json-schema@npm:0.4.0" + checksum: 10c0/d4a637ec1d83544857c1c163232f3da46912e971d5bf054ba44fdb88f07d8d359a462b4aec46f2745efbc57053365608d88bc1d7b1729f7b4fc3369765639ed3 + languageName: node + linkType: hard + "json-stable-stringify-without-jsonify@npm:^1.0.1": version: 1.0.1 resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" @@ -22357,7 +25063,7 @@ __metadata: languageName: node linkType: hard -"json-stringify-safe@npm:^5.0.1": +"json-stringify-safe@npm:^5.0.1, json-stringify-safe@npm:~5.0.1": version: 5.0.1 resolution: "json-stringify-safe@npm:5.0.1" checksum: 10c0/7dbf35cd0411d1d648dceb6d59ce5857ec939e52e4afc37601aa3da611f0987d5cee5b38d58329ceddf3ed48bd7215229c8d52059ab01f2444a338bf24ed0f37 @@ -22375,7 +25081,7 @@ __metadata: languageName: node linkType: hard -"json5@npm:^2.1.2, json5@npm:^2.1.3": +"json5@npm:^2.1.2, json5@npm:^2.1.3, json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" bin: @@ -22444,6 +25150,24 @@ __metadata: languageName: node linkType: hard +"jsonpath-plus@npm:^7.2.0": + version: 7.2.0 + resolution: "jsonpath-plus@npm:7.2.0" + checksum: 10c0/b4fbb8387b80721a47e8098f390dbaa5c74ff4e778832d9f662bcf4ab6038ded26944b8dd433f0474b51fb3e0d7e960990c03af89f4f922a6dc0905102ed86b2 + languageName: node + linkType: hard + +"jsonpath@npm:^1.1.1": + version: 1.1.1 + resolution: "jsonpath@npm:1.1.1" + dependencies: + esprima: "npm:1.2.2" + static-eval: "npm:2.0.2" + underscore: "npm:1.12.1" + checksum: 10c0/4fea3f83bcb4df08c32090ba8a0d1a6d26244f6d19c4296f9b58caa01eeb7de0f8347eba40077ceee2f95acc69d032b0b48226d350339063ba580e87983f6dec + languageName: node + linkType: hard + "jsonpointer@npm:^5.0.0, jsonpointer@npm:^5.0.1": version: 5.0.1 resolution: "jsonpointer@npm:5.0.1" @@ -22476,6 +25200,18 @@ __metadata: languageName: node linkType: hard +"jsprim@npm:^1.2.2": + version: 1.4.2 + resolution: "jsprim@npm:1.4.2" + dependencies: + assert-plus: "npm:1.0.0" + extsprintf: "npm:1.3.0" + json-schema: "npm:0.4.0" + verror: "npm:1.10.0" + checksum: 10c0/5e4bca99e90727c2040eb4c2190d0ef1fe51798ed5714e87b841d304526190d960f9772acc7108fa1416b61e1122bcd60e4460c91793dce0835df5852aab55af + languageName: node + linkType: hard + "jss-plugin-camel-case@npm:^10.10.0, jss-plugin-camel-case@npm:^10.5.1": version: 10.10.0 resolution: "jss-plugin-camel-case@npm:10.10.0" @@ -22635,6 +25371,15 @@ __metadata: languageName: node linkType: hard +"keygrip@npm:~1.1.0": + version: 1.1.0 + resolution: "keygrip@npm:1.1.0" + dependencies: + tsscmp: "npm:1.0.6" + checksum: 10c0/2aceec1a1e642a0caf938044056ed67b1909cfe67a93a59b32aae2863e0f35a1a53782ecc8f9cd0e3bdb60863fa0f401ccbd257cd7dfae61915f78445139edea + languageName: node + linkType: hard + "keytar@npm:^7.9.0": version: 7.9.0 resolution: "keytar@npm:7.9.0" @@ -22773,6 +25518,54 @@ __metadata: languageName: node linkType: hard +"koa-compose@npm:^4.1.0": + version: 4.1.0 + resolution: "koa-compose@npm:4.1.0" + checksum: 10c0/f1f786f994a691931148e7f38f443865bf2702af4a61610d1eea04dab79c04b1232285b59d82a0cf61c830516dd92f10ab0d009b024fcecd4098e7d296ab771a + languageName: node + linkType: hard + +"koa-convert@npm:^2.0.0": + version: 2.0.0 + resolution: "koa-convert@npm:2.0.0" + dependencies: + co: "npm:^4.6.0" + koa-compose: "npm:^4.1.0" + checksum: 10c0/d3e243ceccd11524d5f4942f6ccd828a9b18a1a967c4375192aa9eedf844f790563632839f006732ce8ca720275737c65a3bab344e13b25f41fb2be451ea102c + languageName: node + linkType: hard + +"koa@npm:2.15.4": + version: 2.15.4 + resolution: "koa@npm:2.15.4" + dependencies: + accepts: "npm:^1.3.5" + cache-content-type: "npm:^1.0.0" + content-disposition: "npm:~0.5.2" + content-type: "npm:^1.0.4" + cookies: "npm:~0.9.0" + debug: "npm:^4.3.2" + delegates: "npm:^1.0.0" + depd: "npm:^2.0.0" + destroy: "npm:^1.0.4" + encodeurl: "npm:^1.0.2" + escape-html: "npm:^1.0.3" + fresh: "npm:~0.5.2" + http-assert: "npm:^1.3.0" + http-errors: "npm:^1.6.3" + is-generator-function: "npm:^1.0.7" + koa-compose: "npm:^4.1.0" + koa-convert: "npm:^2.0.0" + on-finished: "npm:^2.3.0" + only: "npm:~0.0.2" + parseurl: "npm:^1.3.2" + statuses: "npm:^1.5.0" + type-is: "npm:^1.6.16" + vary: "npm:^1.1.2" + checksum: 10c0/fd2171b4dba706d35244fe60403a61671717a167453349813757999dad280049ddd0dcdba23cda197a5a3538f4c034cf0fd1f9caeb849be1ca1eecaa78db2f99 + languageName: node + linkType: hard + "kubernetes-models@npm:^4.3.1": version: 4.4.2 resolution: "kubernetes-models@npm:4.4.2" @@ -22851,6 +25644,16 @@ __metadata: languageName: node linkType: hard +"levn@npm:~0.3.0": + version: 0.3.0 + resolution: "levn@npm:0.3.0" + dependencies: + prelude-ls: "npm:~1.1.2" + type-check: "npm:~0.3.2" + checksum: 10c0/e440df9de4233da0b389cd55bd61f0f6aaff766400bebbccd1231b81801f6dbc1d816c676ebe8d70566394b749fa624b1ed1c68070e9c94999f0bdecc64cb676 + languageName: node + linkType: hard + "libsodium-wrappers@npm:^0.8.0": version: 0.8.4 resolution: "libsodium-wrappers@npm:0.8.4" @@ -23001,6 +25804,13 @@ __metadata: languageName: node linkType: hard +"lodash.clonedeepwith@npm:4.5.0": + version: 4.5.0 + resolution: "lodash.clonedeepwith@npm:4.5.0" + checksum: 10c0/a7de84be9ad796811e8084deb79ef07f8f87122d87adffcd52ce4e6fa528fbe917f3dc6cc1d556362dc5dfadef68405e54f4b4d3ae72056e32ec5e84492a3fc2 + languageName: node + linkType: hard + "lodash.debounce@npm:^4": version: 4.0.8 resolution: "lodash.debounce@npm:4.0.8" @@ -23165,7 +25975,7 @@ __metadata: languageName: node linkType: hard -"log4js@npm:^6.4.6": +"log4js@npm:6.9.1, log4js@npm:^6.4.6": version: 6.9.1 resolution: "log4js@npm:6.9.1" dependencies: @@ -23273,6 +26083,15 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^6.0.0": + version: 6.0.0 + resolution: "lru-cache@npm:6.0.0" + dependencies: + yallist: "npm:^4.0.0" + checksum: 10c0/cb53e582785c48187d7a188d3379c181b5ca2a9c78d2bce3e7dee36f32761d1c42983da3fe12b55cb74e1779fa94cdc2e5367c028a9b35317184ede0c07a30a9 + languageName: node + linkType: hard + "lru-cache@npm:^7.14.0, lru-cache@npm:^7.14.1, lru-cache@npm:^7.7.1": version: 7.18.3 resolution: "lru-cache@npm:7.18.3" @@ -23326,6 +26145,15 @@ __metadata: languageName: node linkType: hard +"make-dir@npm:^4.0.0": + version: 4.0.0 + resolution: "make-dir@npm:4.0.0" + dependencies: + semver: "npm:^7.5.3" + checksum: 10c0/69b98a6c0b8e5c4fe9acb61608a9fbcfca1756d910f51e5dbe7a9e5cfb74fca9b8a0c8a0ffdf1294a740826c1ab4871d5bf3f62f72a3049e5eac6541ddffed68 + languageName: node + linkType: hard + "make-error@npm:^1.1.1": version: 1.3.6 resolution: "make-error@npm:1.3.6" @@ -23403,6 +26231,15 @@ __metadata: languageName: node linkType: hard +"makeerror@npm:1.0.12": + version: 1.0.12 + resolution: "makeerror@npm:1.0.12" + dependencies: + tmpl: "npm:1.0.5" + checksum: 10c0/b0e6e599780ce6bab49cc413eba822f7d1f0dfebd1c103eaa3785c59e43e22c59018323cf9e1708f0ef5329e94a745d163fcbb6bff8e4c6742f9be9e86f3500c + languageName: node + linkType: hard + "markdown-escape@npm:^2.0.0": version: 2.0.0 resolution: "markdown-escape@npm:2.0.0" @@ -24140,7 +26977,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.2, micromatch@npm:^4.0.5, micromatch@npm:^4.0.8": +"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" dependencies: @@ -24176,7 +27013,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:^2.1.31, mime-types@npm:^2.1.35, mime-types@npm:~2.1.17, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.18, mime-types@npm:^2.1.27, mime-types@npm:^2.1.31, mime-types@npm:^2.1.35, mime-types@npm:~2.1.17, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -24331,7 +27168,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": +"minimatch@npm:^9.0.0, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": version: 9.0.5 resolution: "minimatch@npm:9.0.5" dependencies: @@ -24340,7 +27177,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.8": +"minimist@npm:^1.1.0, minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.8": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 @@ -24932,7 +27769,7 @@ __metadata: languageName: node linkType: hard -"node-domexception@npm:^1.0.0": +"node-domexception@npm:1.0.0, node-domexception@npm:^1.0.0": version: 1.0.0 resolution: "node-domexception@npm:1.0.0" checksum: 10c0/5e5d63cda29856402df9472335af4bb13875e1927ad3be861dc5ebde38917aecbf9ae337923777af52a48c426b70148815e890a5d72760f1b4d758cc671b1a2b @@ -24989,10 +27826,10 @@ __metadata: languageName: node linkType: hard -"node-forge@npm:^1, node-forge@npm:^1.2.1, node-forge@npm:^1.3.2": - version: 1.4.0 - resolution: "node-forge@npm:1.4.0" - checksum: 10c0/67330a5f1f95257a4c8a93b7d555abe87b5f15e350123aa396c97a21a8ca94f9c6549008eb2c73668a91e0d7e3a905785acbd8f8bd0751c29401292011f8f8e1 +"node-forge@npm:^1, node-forge@npm:^1.2.1, node-forge@npm:^1.3.1, node-forge@npm:^1.3.2": + version: 1.3.3 + resolution: "node-forge@npm:1.3.3" + checksum: 10c0/9c6f53b0ebb34865872cf62a35b0aef8fb337e2efc766626c2e3a0040f4c02933bf29a62ba999eb44a2aca73bd512c4eda22705a47b94654b9fb8ed53db9a1db languageName: node linkType: hard @@ -25075,6 +27912,13 @@ __metadata: languageName: node linkType: hard +"node-int64@npm:^0.4.0": + version: 0.4.0 + resolution: "node-int64@npm:0.4.0" + checksum: 10c0/a6a4d8369e2f2720e9c645255ffde909c0fbd41c92ea92a5607fc17055955daac99c1ff589d421eee12a0d24e99f7bfc2aabfeb1a4c14742f6c099a51863f31a + languageName: node + linkType: hard + "node-machine-id@npm:^1.1.12": version: 1.1.12 resolution: "node-machine-id@npm:1.1.12" @@ -25235,6 +28079,15 @@ __metadata: languageName: node linkType: hard +"npm-run-path@npm:^4.0.1": + version: 4.0.1 + resolution: "npm-run-path@npm:4.0.1" + dependencies: + path-key: "npm:^3.0.0" + checksum: 10c0/6f9353a95288f8455cf64cbeb707b28826a7f29690244c1e4bb61ec573256e021b6ad6651b394eb1ccfd00d6ec50147253aba2c5fe58a57ceb111fad62c519ac + languageName: node + linkType: hard + "npmlog@npm:^6.0.0": version: 6.0.2 resolution: "npmlog@npm:6.0.2" @@ -25281,13 +28134,20 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.16": +"nwsapi@npm:^2.2.16, nwsapi@npm:^2.2.2": version: 2.2.19 resolution: "nwsapi@npm:2.2.19" checksum: 10c0/5bd9da260b2b24a775103c835a93c79584a870307eb59270b43c6970b7ae9c0af3cfffd9df5292c24d2ca2c67f49672b4c9be9824c347d6083b90e002a12779a languageName: node linkType: hard +"oauth-sign@npm:~0.9.0": + version: 0.9.0 + resolution: "oauth-sign@npm:0.9.0" + checksum: 10c0/fc92a516f6ddbb2699089a2748b04f55c47b6ead55a77cd3a2cbbce5f7af86164cb9425f9ae19acfd066f1ad7d3a96a67b8928c6ea946426f6d6c29e448497c2 + languageName: node + linkType: hard + "oauth4webapi@npm:^3.8.1": version: 3.8.1 resolution: "oauth4webapi@npm:3.8.1" @@ -25309,6 +28169,13 @@ __metadata: languageName: node linkType: hard +"object-hash@npm:^2.2.0": + version: 2.2.0 + resolution: "object-hash@npm:2.2.0" + checksum: 10c0/1527de843926c5442ed61f8bdddfc7dc181b6497f725b0e89fcf50a55d9c803088763ed447cac85a5aa65345f1e99c2469ba679a54349ef3c4c0aeaa396a3eb9 + languageName: node + linkType: hard + "object-hash@npm:^3.0.0": version: 3.0.0 resolution: "object-hash@npm:3.0.0" @@ -25435,7 +28302,14 @@ __metadata: languageName: node linkType: hard -"on-finished@npm:^2.4.1, on-finished@npm:~2.4.1": +"oidc-token-hash@npm:^5.0.3": + version: 5.1.0 + resolution: "oidc-token-hash@npm:5.1.0" + checksum: 10c0/9b6bd90928eabc69e4a56cb7cf6e18c8e202912b7db52efffbfd6c37866760605e90a3da58442d70bf1ca9f68c06efe0e97095fceb244c934abe3c204378f1d6 + languageName: node + linkType: hard + +"on-finished@npm:^2.3.0, on-finished@npm:^2.4.1, on-finished@npm:~2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" dependencies: @@ -25485,7 +28359,7 @@ __metadata: languageName: node linkType: hard -"onetime@npm:^5.1.0": +"onetime@npm:^5.1.0, onetime@npm:^5.1.2": version: 5.1.2 resolution: "onetime@npm:5.1.2" dependencies: @@ -25494,6 +28368,13 @@ __metadata: languageName: node linkType: hard +"only@npm:~0.0.2": + version: 0.0.2 + resolution: "only@npm:0.0.2" + checksum: 10c0/d26b1347835a5a9b17afbd889ed60de3d3ae14cdeca5ba008d86e6bf055466a431adc731b82e1e8ab24a3b8be5b5c2cdbc16e652d231d18cc1a5752320aaf0a0 + languageName: node + linkType: hard + "ono@npm:^7.1.3": version: 7.1.3 resolution: "ono@npm:7.1.3" @@ -25582,6 +28463,18 @@ __metadata: languageName: node linkType: hard +"openid-client@npm:^5.3.0": + version: 5.7.1 + resolution: "openid-client@npm:5.7.1" + dependencies: + jose: "npm:^4.15.9" + lru-cache: "npm:^6.0.0" + object-hash: "npm:^2.2.0" + oidc-token-hash: "npm:^5.0.3" + checksum: 10c0/6aae649758562002eace7574b6eda02be7eddbb0df61eef497ae98b7a4a0ae4c6b09f3f0c1b9b6cb7fcc0c70bbde2576691bf31b870db1f19ab634c1def10bc7 + languageName: node + linkType: hard + "openid-client@npm:^6.1.3": version: 6.8.0 resolution: "openid-client@npm:6.8.0" @@ -25601,6 +28494,20 @@ __metadata: languageName: node linkType: hard +"optionator@npm:^0.8.1": + version: 0.8.3 + resolution: "optionator@npm:0.8.3" + dependencies: + deep-is: "npm:~0.1.3" + fast-levenshtein: "npm:~2.0.6" + levn: "npm:~0.3.0" + prelude-ls: "npm:~1.1.2" + type-check: "npm:~0.3.2" + word-wrap: "npm:~1.2.3" + checksum: 10c0/ad7000ea661792b3ec5f8f86aac28895850988926f483b5f308f59f4607dfbe24c05df2d049532ee227c040081f39401a268cf7bbf3301512f74c4d760dc6dd8 + languageName: node + linkType: hard + "optionator@npm:^0.9.3": version: 0.9.4 resolution: "optionator@npm:0.9.4" @@ -25639,6 +28546,18 @@ __metadata: languageName: node linkType: hard +"os-name@npm:~1.0.3": + version: 1.0.3 + resolution: "os-name@npm:1.0.3" + dependencies: + osx-release: "npm:^1.0.0" + win-release: "npm:^1.0.0" + bin: + os-name: cli.js + checksum: 10c0/9c1d8cc3eceae5717597be994b0a1b39cda8d11fd6bd5917b029fdac7c4675c8fd5fd5f0e4b95005e49ddee1f3ffda22ed76b12a636efc291a61cc5b8352861c + languageName: node + linkType: hard + "os-tmpdir@npm:~1.0.2": version: 1.0.2 resolution: "os-tmpdir@npm:1.0.2" @@ -25646,6 +28565,17 @@ __metadata: languageName: node linkType: hard +"osx-release@npm:^1.0.0": + version: 1.1.0 + resolution: "osx-release@npm:1.1.0" + dependencies: + minimist: "npm:^1.1.0" + bin: + osx-release: cli.js + checksum: 10c0/eb8486e2e467bf39a17301128e42fec5d1cf4b902ba93b8ea4b4b048d0a10daff01cf06c60a6e2733d0a894e85ff2d6bf02540949ab226b43b086dfabad0c9da + languageName: node + linkType: hard + "outdent@npm:^0.5.0": version: 0.5.0 resolution: "outdent@npm:0.5.0" @@ -25984,7 +28914,7 @@ __metadata: languageName: node linkType: hard -"parse5@npm:^7.2.1": +"parse5@npm:^7.0.0, parse5@npm:^7.1.1, parse5@npm:^7.2.1": version: 7.2.1 resolution: "parse5@npm:7.2.1" dependencies: @@ -25993,7 +28923,7 @@ __metadata: languageName: node linkType: hard -"parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": +"parseurl@npm:^1.3.2, parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" checksum: 10c0/90dd4760d6f6174adb9f20cf0965ae12e23879b5f5464f38e92fce8073354341e4b3b76fa3d878351efe7d01e617121955284cfd002ab087fba1a0726ec0b4f5 @@ -26092,7 +29022,7 @@ __metadata: languageName: node linkType: hard -"path-key@npm:^3.1.0": +"path-key@npm:^3.0.0, path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c @@ -26411,13 +29341,22 @@ __metadata: languageName: node linkType: hard -"pirates@npm:^4.0.1, pirates@npm:^4.0.6": +"pirates@npm:^4.0.1, pirates@npm:^4.0.4, pirates@npm:^4.0.6": version: 4.0.6 resolution: "pirates@npm:4.0.6" checksum: 10c0/00d5fa51f8dded94d7429700fb91a0c1ead00ae2c7fd27089f0c5b63e6eca36197fe46384631872690a66f390c5e27198e99006ab77ae472692ab9c2ca903f36 languageName: node linkType: hard +"pkg-dir@npm:^4.2.0": + version: 4.2.0 + resolution: "pkg-dir@npm:4.2.0" + dependencies: + find-up: "npm:^4.0.0" + checksum: 10c0/c56bda7769e04907a88423feb320babaed0711af8c436ce3e56763ab1021ba107c7b0cafb11cde7529f669cfc22bffcaebffb573645cbd63842ea9fb17cd7728 + languageName: node + linkType: hard + "pkg-dir@npm:^5.0.0": version: 5.0.0 resolution: "pkg-dir@npm:5.0.0" @@ -27019,6 +29958,13 @@ __metadata: languageName: node linkType: hard +"prelude-ls@npm:~1.1.2": + version: 1.1.2 + resolution: "prelude-ls@npm:1.1.2" + checksum: 10c0/7284270064f74e0bb7f04eb9bff7be677e4146417e599ccc9c1200f0f640f8b11e592d94eb1b18f7aa9518031913bb42bea9c86af07ba69902864e61005d6f18 + languageName: node + linkType: hard + "prettier@npm:^2.3.2, prettier@npm:^2.7.1": version: 2.8.8 resolution: "prettier@npm:2.8.8" @@ -27049,6 +29995,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" + dependencies: + "@jest/schemas": "npm:^29.6.3" + ansi-styles: "npm:^5.0.0" + react-is: "npm:^18.0.0" + checksum: 10c0/edc5ff89f51916f036c62ed433506b55446ff739358de77207e63e88a28ca2894caac6e73dcb68166a606e51c8087d32d400473e6a9fdd2dbe743f46c9c0276f + languageName: node + linkType: hard + "pretty-ms@npm:^9.0.0": version: 9.2.0 resolution: "pretty-ms@npm:9.2.0" @@ -27134,7 +30091,7 @@ __metadata: languageName: node linkType: hard -"prompts@npm:^2.4.2": +"prompts@npm:^2.0.1, prompts@npm:^2.4.2": version: 2.4.2 resolution: "prompts@npm:2.4.2" dependencies: @@ -27275,10 +30232,12 @@ __metadata: languageName: node linkType: hard -"proxy-from-env@npm:^2.1.0": - version: 2.1.0 - resolution: "proxy-from-env@npm:2.1.0" - checksum: 10c0/ed01729fd4d094eab619cd7e17ce3698b3413b31eb102c4904f9875e677cd207392795d5b4adee9cec359dfd31c44d5ad7595a3a3ad51c40250e141512281c58 +"psl@npm:^1.1.28, psl@npm:^1.1.33": + version: 1.15.0 + resolution: "psl@npm:1.15.0" + dependencies: + punycode: "npm:^2.3.1" + checksum: 10c0/d8d45a99e4ca62ca12ac3c373e63d80d2368d38892daa40cfddaa1eb908be98cd549ac059783ef3a56cfd96d57ae8e2fd9ae53d1378d90d42bc661ff924e102a languageName: node linkType: hard @@ -27327,6 +30286,13 @@ __metadata: languageName: node linkType: hard +"pure-rand@npm:^6.0.0": + version: 6.1.0 + resolution: "pure-rand@npm:6.1.0" + checksum: 10c0/1abe217897bf74dcb3a0c9aba3555fe975023147b48db540aa2faf507aee91c03bf54f6aef0eb2bf59cc259a16d06b28eca37f0dc426d94f4692aeff02fb0e65 + languageName: node + linkType: hard + "pvtsutils@npm:^1.3.6": version: 1.3.6 resolution: "pvtsutils@npm:1.3.6" @@ -27343,7 +30309,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.11.0, qs@npm:^6.12.3, qs@npm:^6.14.0, qs@npm:^6.15.0, qs@npm:^6.15.2, qs@npm:^6.9.4, qs@npm:~6.15.1": +"qs@npm:^6.11.0, qs@npm:^6.11.2, qs@npm:^6.12.3, qs@npm:^6.14.0, qs@npm:^6.15.0, qs@npm:^6.15.2, qs@npm:^6.9.4, qs@npm:~6.15.1": version: 6.15.3 resolution: "qs@npm:6.15.3" dependencies: @@ -27362,6 +30328,13 @@ __metadata: languageName: node linkType: hard +"qs@npm:~6.5.2": + version: 6.5.3 + resolution: "qs@npm:6.5.3" + checksum: 10c0/6631d4f2fa9d315e480662646745a4aa3a708817fbffe2cbdacec8ab9be130f92740c66191770fe9b704bc5fa9c1cc1f6596f55ad132fef7bd3ad1582f199eb0 + languageName: node + linkType: hard + "quansync@npm:^0.2.7": version: 0.2.10 resolution: "quansync@npm:0.2.10" @@ -27418,6 +30391,13 @@ __metadata: languageName: node linkType: hard +"rambda@npm:^9.1.0": + version: 9.4.2 + resolution: "rambda@npm:9.4.2" + checksum: 10c0/ee32773c7ef7a281782cf2e09cd0f2dbb67facf59924042e861ef42f166eb081c92e55ed6bd1a7c5c1a937831227bea16b9c11680bc9d57b4b8cb29ca78241ac + languageName: node + linkType: hard + "ramda-adjunct@npm:^5.0.0, ramda-adjunct@npm:^5.1.0": version: 5.1.0 resolution: "ramda-adjunct@npm:5.1.0" @@ -27993,6 +30973,13 @@ __metadata: languageName: node linkType: hard +"react-refresh@npm:^0.17.0": + version: 0.17.0 + resolution: "react-refresh@npm:0.17.0" + checksum: 10c0/002cba940384c9930008c0bce26cac97a9d5682bc623112c2268ba0c155127d9c178a9a5cc2212d560088d60dfd503edd808669a25f9b377f316a32361d0b23c + languageName: node + linkType: hard + "react-refresh@npm:^0.18.0": version: 0.18.0 resolution: "react-refresh@npm:0.18.0" @@ -28642,6 +31629,34 @@ __metadata: languageName: node linkType: hard +"request@npm:^2.88.0": + version: 2.88.2 + resolution: "request@npm:2.88.2" + dependencies: + aws-sign2: "npm:~0.7.0" + aws4: "npm:^1.8.0" + caseless: "npm:~0.12.0" + combined-stream: "npm:~1.0.6" + extend: "npm:~3.0.2" + forever-agent: "npm:~0.6.1" + form-data: "npm:~2.3.2" + har-validator: "npm:~5.1.3" + http-signature: "npm:~1.2.0" + is-typedarray: "npm:~1.0.0" + isstream: "npm:~0.1.2" + json-stringify-safe: "npm:~5.0.1" + mime-types: "npm:~2.1.19" + oauth-sign: "npm:~0.9.0" + performance-now: "npm:^2.1.0" + qs: "npm:~6.5.2" + safe-buffer: "npm:^5.1.2" + tough-cookie: "npm:~2.5.0" + tunnel-agent: "npm:^0.6.0" + uuid: "npm:^3.3.2" + checksum: 10c0/0ec66e7af1391e51ad231de3b1c6c6aef3ebd0a238aa50d4191c7a792dcdb14920eea8d570c702dc5682f276fe569d176f9b8ebc6031a3cf4a630a691a431a63 + languageName: node + linkType: hard + "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -28693,6 +31708,15 @@ __metadata: languageName: node linkType: hard +"resolve-cwd@npm:^3.0.0": + version: 3.0.0 + resolution: "resolve-cwd@npm:3.0.0" + dependencies: + resolve-from: "npm:^5.0.0" + checksum: 10c0/e608a3ebd15356264653c32d7ecbc8fd702f94c6703ea4ac2fb81d9c359180cba0ae2e6b71faa446631ed6145454d5a56b227efc33a2d40638ac13f8beb20ee4 + languageName: node + linkType: hard + "resolve-dir@npm:^1.0.0, resolve-dir@npm:^1.0.1": version: 1.0.1 resolution: "resolve-dir@npm:1.0.1" @@ -28724,6 +31748,13 @@ __metadata: languageName: node linkType: hard +"resolve.exports@npm:^2.0.0": + version: 2.0.3 + resolution: "resolve.exports@npm:2.0.3" + checksum: 10c0/1ade1493f4642a6267d0a5e68faeac20b3d220f18c28b140343feb83694d8fed7a286852aef43689d16042c61e2ddb270be6578ad4a13990769e12065191200d + languageName: node + linkType: hard + "resolve@npm:1.22.8": version: 1.22.8 resolution: "resolve@npm:1.22.8" @@ -28983,7 +32014,7 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^4.59.0": +"rollup@npm:^4.27.3, rollup@npm:^4.59.0": version: 4.60.2 resolution: "rollup@npm:4.60.2" dependencies: @@ -29215,7 +32246,7 @@ __metadata: languageName: node linkType: hard -"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:~2.1.0": +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.0.2, safer-buffer@npm:^2.1.0, safer-buffer@npm:~2.1.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 @@ -29359,7 +32390,16 @@ __metadata: languageName: node linkType: hard -"semver@npm:^6.3.1": +"semver@npm:^5.0.1": + version: 5.7.2 + resolution: "semver@npm:5.7.2" + bin: + semver: bin/semver + checksum: 10c0/e4cf10f86f168db772ae95d86ba65b3fd6c5967c94d97c708ccb463b778c2ee53b914cd7167620950fc07faf5a564e6efe903836639e512a1aa15fbc9667fa25 + languageName: node + linkType: hard + +"semver@npm:^6.3.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" bin: @@ -29633,7 +32673,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.7": +"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: 10c0/25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 @@ -29805,6 +32845,16 @@ __metadata: languageName: node linkType: hard +"source-map-support@npm:0.5.13": + version: 0.5.13 + resolution: "source-map-support@npm:0.5.13" + dependencies: + buffer-from: "npm:^1.0.0" + source-map: "npm:^0.6.0" + checksum: 10c0/137539f8c453fa0f496ea42049ab5da4569f96781f6ac8e5bfda26937be9494f4e8891f523c5f98f0e85f71b35d74127a00c46f83f6a4f54672b58d53202565e + languageName: node + linkType: hard + "source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" @@ -29972,6 +33022,27 @@ __metadata: languageName: node linkType: hard +"sshpk@npm:^1.7.0": + version: 1.18.0 + resolution: "sshpk@npm:1.18.0" + dependencies: + asn1: "npm:~0.2.3" + assert-plus: "npm:^1.0.0" + bcrypt-pbkdf: "npm:^1.0.0" + dashdash: "npm:^1.12.0" + ecc-jsbn: "npm:~0.1.1" + getpass: "npm:^0.1.1" + jsbn: "npm:~0.1.0" + safer-buffer: "npm:^2.0.2" + tweetnacl: "npm:~0.14.0" + bin: + sshpk-conv: bin/sshpk-conv + sshpk-sign: bin/sshpk-sign + sshpk-verify: bin/sshpk-verify + checksum: 10c0/e516e34fa981cfceef45fd2e947772cc70dbd57523e5c608e2cd73752ba7f8a99a04df7c3ed751588e8d91956b6f16531590b35d3489980d1c54c38bebcd41b1 + languageName: node + linkType: hard + "ssri@npm:^10.0.0": version: 10.0.6 resolution: "ssri@npm:10.0.6" @@ -30022,6 +33093,15 @@ __metadata: languageName: node linkType: hard +"stack-utils@npm:^2.0.3": + version: 2.0.6 + resolution: "stack-utils@npm:2.0.6" + dependencies: + escape-string-regexp: "npm:^2.0.0" + checksum: 10c0/651c9f87667e077584bbe848acaecc6049bc71979f1e9a46c7b920cad4431c388df0f51b8ad7cfd6eed3db97a2878d0fc8b3122979439ea8bac29c61c95eec8a + languageName: node + linkType: hard + "stackframe@npm:^1.3.4": version: 1.3.4 resolution: "stackframe@npm:1.3.4" @@ -30057,7 +33137,16 @@ __metadata: languageName: node linkType: hard -"statuses@npm:>= 1.4.0 < 2, statuses@npm:~1.5.0": +"static-eval@npm:2.0.2": + version: 2.0.2 + resolution: "static-eval@npm:2.0.2" + dependencies: + escodegen: "npm:^1.8.1" + checksum: 10c0/9bc1114ea5ba2a6978664907c4dd3fde6f58767274f6cb4fbfb11ba3a73cb6e74dc11e89ec4a7bf1472a587c1f976fcd4ab8fe9aae1651f5e576f097745d48ff + languageName: node + linkType: hard + +"statuses@npm:>= 1.4.0 < 2, statuses@npm:>= 1.5.0 < 2, statuses@npm:^1.5.0, statuses@npm:~1.5.0": version: 1.5.0 resolution: "statuses@npm:1.5.0" checksum: 10c0/e433900956357b3efd79b1c547da4d291799ac836960c016d10a98f6a810b1b5c0dcc13b5a7aa609a58239b5190e1ea176ad9221c2157d2fd1c747393e6b2940 @@ -30204,6 +33293,16 @@ __metadata: languageName: node linkType: hard +"string-length@npm:^4.0.1": + version: 4.0.2 + resolution: "string-length@npm:4.0.2" + dependencies: + char-regex: "npm:^1.0.2" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/1cd77409c3d7db7bc59406f6bcc9ef0783671dcbabb23597a1177c166906ef2ee7c8290f78cae73a8aec858768f189d2cb417797df5e15ec4eb5e16b3346340c + languageName: node + linkType: hard + "string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": version: 4.2.3 resolution: "string-width@npm:4.2.3" @@ -30358,6 +33457,20 @@ __metadata: languageName: node linkType: hard +"strip-bom@npm:^4.0.0": + version: 4.0.0 + resolution: "strip-bom@npm:4.0.0" + checksum: 10c0/26abad1172d6bc48985ab9a5f96c21e440f6e7e476686de49be813b5a59b3566dccb5c525b831ec54fe348283b47f3ffb8e080bc3f965fde12e84df23f6bb7ef + languageName: node + linkType: hard + +"strip-final-newline@npm:^2.0.0": + version: 2.0.0 + resolution: "strip-final-newline@npm:2.0.0" + checksum: 10c0/bddf8ccd47acd85c0e09ad7375409d81653f645fda13227a9d459642277c253d877b68f2e5e4d819fe75733b0e626bac7e954c04f3236f6d196f79c94fa4a96f + languageName: node + linkType: hard + "strip-indent@npm:^3.0.0": version: 3.0.0 resolution: "strip-indent@npm:3.0.0" @@ -30784,7 +33897,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.1.11, tar@npm:^6.1.2, tar@npm:^6.2.1": +"tar@npm:^6.1.11, tar@npm:^6.1.12, tar@npm:^6.1.2, tar@npm:^6.2.1": version: 6.2.1 resolution: "tar@npm:6.2.1" dependencies: @@ -30889,6 +34002,17 @@ __metadata: languageName: node linkType: hard +"test-exclude@npm:^6.0.0": + version: 6.0.0 + resolution: "test-exclude@npm:6.0.0" + dependencies: + "@istanbuljs/schema": "npm:^0.1.2" + glob: "npm:^7.1.4" + minimatch: "npm:^3.0.4" + checksum: 10c0/019d33d81adff3f9f1bfcff18125fb2d3c65564f437d9be539270ee74b994986abb8260c7c2ce90e8f30162178b09dbbce33c6389273afac4f36069c48521f57 + languageName: node + linkType: hard + "testcontainers@npm:^11.9.0": version: 11.14.0 resolution: "testcontainers@npm:11.14.0" @@ -31073,6 +34197,13 @@ __metadata: languageName: node linkType: hard +"tmpl@npm:1.0.5": + version: 1.0.5 + resolution: "tmpl@npm:1.0.5" + checksum: 10c0/f935537799c2d1922cb5d6d3805f594388f75338fe7a4a9dac41504dd539704ca4db45b883b52e7b0aa5b2fd5ddadb1452bf95cd23a69da2f793a843f9451cc9 + languageName: node + linkType: hard + "to-buffer@npm:^1.2.0": version: 1.2.2 resolution: "to-buffer@npm:1.2.2" @@ -31100,7 +34231,7 @@ __metadata: languageName: node linkType: hard -"toidentifier@npm:~1.0.1": +"toidentifier@npm:1.0.1, toidentifier@npm:~1.0.1": version: 1.0.1 resolution: "toidentifier@npm:1.0.1" checksum: 10c0/93937279934bd66cc3270016dd8d0afec14fb7c94a05c72dc57321f8bd1fa97e5bea6d1f7c89e728d077ca31ea125b78320a616a6c6cd0e6b9cb94cb864381c1 @@ -31131,6 +34262,18 @@ __metadata: languageName: node linkType: hard +"tough-cookie@npm:^4.1.2": + version: 4.1.4 + resolution: "tough-cookie@npm:4.1.4" + dependencies: + psl: "npm:^1.1.33" + punycode: "npm:^2.1.1" + universalify: "npm:^0.2.0" + url-parse: "npm:^1.5.3" + checksum: 10c0/aca7ff96054f367d53d1e813e62ceb7dd2eda25d7752058a74d64b7266fd07be75908f3753a32ccf866a2f997604b414cfb1916d6e7f69bc64d9d9939b0d6c45 + languageName: node + linkType: hard + "tough-cookie@npm:^5.0.0": version: 5.1.2 resolution: "tough-cookie@npm:5.1.2" @@ -31140,6 +34283,25 @@ __metadata: languageName: node linkType: hard +"tough-cookie@npm:~2.5.0": + version: 2.5.0 + resolution: "tough-cookie@npm:2.5.0" + dependencies: + psl: "npm:^1.1.28" + punycode: "npm:^2.1.1" + checksum: 10c0/e1cadfb24d40d64ca16de05fa8192bc097b66aeeb2704199b055ff12f450e4f30c927ce250f53d01f39baad18e1c11d66f65e545c5c6269de4c366fafa4c0543 + languageName: node + linkType: hard + +"tr46@npm:^3.0.0": + version: 3.0.0 + resolution: "tr46@npm:3.0.0" + dependencies: + punycode: "npm:^2.1.1" + checksum: 10c0/cdc47cad3a9d0b6cb293e39ccb1066695ae6fdd39b9e4f351b010835a1f8b4f3a6dc3a55e896b421371187f22b48d7dac1b693de4f6551bdef7b6ab6735dfe3b + languageName: node + linkType: hard + "tr46@npm:^5.1.0": version: 5.1.0 resolution: "tr46@npm:5.1.0" @@ -31390,7 +34552,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.8.1, tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.0, tslib@npm:^2.6.2, tslib@npm:^2.8.0, tslib@npm:^2.8.1": +"tslib@npm:2.8.1, tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.4.1, tslib@npm:^2.5.0, tslib@npm:^2.6.0, tslib@npm:^2.6.2, tslib@npm:^2.8.0, tslib@npm:^2.8.1": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 @@ -31404,6 +34566,13 @@ __metadata: languageName: node linkType: hard +"tsscmp@npm:1.0.6": + version: 1.0.6 + resolution: "tsscmp@npm:1.0.6" + checksum: 10c0/2f79a9455e7e3e8071995f98cdf3487ccfc91b760bec21a9abb4d90519557eafaa37246e87c92fa8bf3fef8fd30cfd0cc3c4212bb929baa9fb62494bfa4d24b2 + languageName: node + linkType: hard + "tsyringe@npm:^4.10.0": version: 4.10.0 resolution: "tsyringe@npm:4.10.0" @@ -31429,7 +34598,7 @@ __metadata: languageName: node linkType: hard -"tweetnacl@npm:^0.14.3": +"tweetnacl@npm:^0.14.3, tweetnacl@npm:~0.14.0": version: 0.14.5 resolution: "tweetnacl@npm:0.14.5" checksum: 10c0/4612772653512c7bc19e61923fbf42903f5e0389ec76a4a1f17195859d114671ea4aa3b734c2029ce7e1fa7e5cc8b80580f67b071ecf0b46b5636d030a0102a2 @@ -31445,6 +34614,22 @@ __metadata: languageName: node linkType: hard +"type-check@npm:~0.3.2": + version: 0.3.2 + resolution: "type-check@npm:0.3.2" + dependencies: + prelude-ls: "npm:~1.1.2" + checksum: 10c0/776217116b2b4e50e368c7ee0c22c0a85e982881c16965b90d52f216bc296d6a52ef74f9202d22158caacc092a7645b0b8d5fe529a96e3fe35d0fb393966c875 + languageName: node + linkType: hard + +"type-detect@npm:4.0.8": + version: 4.0.8 + resolution: "type-detect@npm:4.0.8" + checksum: 10c0/8fb9a51d3f365a7de84ab7f73b653534b61b622aa6800aecdb0f1095a4a646d3f5eb295322127b6573db7982afcd40ab492d038cf825a42093a58b1e1353e0bd + languageName: node + linkType: hard + "type-fest@npm:^0.13.1": version: 0.13.1 resolution: "type-fest@npm:0.13.1" @@ -31473,7 +34658,7 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^4.41.0": +"type-fest@npm:^4.3.1, type-fest@npm:^4.41.0": version: 4.41.0 resolution: "type-fest@npm:4.41.0" checksum: 10c0/f5ca697797ed5e88d33ac8f1fec21921839871f808dc59345c9cf67345bfb958ce41bd821165dbf3ae591cedec2bf6fe8882098dfdd8dc54320b859711a2c1e4 @@ -31487,7 +34672,7 @@ __metadata: languageName: node linkType: hard -"type-is@npm:^1.6.18, type-is@npm:~1.6.18": +"type-is@npm:^1.6.16, type-is@npm:^1.6.18, type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" dependencies: @@ -31705,6 +34890,13 @@ __metadata: languageName: node linkType: hard +"underscore@npm:1.12.1": + version: 1.12.1 + resolution: "underscore@npm:1.12.1" + checksum: 10c0/00f392357e363353ac485e7c156b749505087e31ff4fdad22e04ebd2f94a56fbc554cd41a6722e3895a818466cf298b1cae93ff6211d102d373a9b50db63bfd0 + languageName: node + linkType: hard + "underscore@npm:^1.13.3, underscore@npm:~1.13.2": version: 1.13.8 resolution: "underscore@npm:1.13.8" @@ -31719,6 +34911,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~6.19.2": + version: 6.19.8 + resolution: "undici-types@npm:6.19.8" + checksum: 10c0/078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344 + languageName: node + linkType: hard + "undici-types@npm:~7.16.0": version: 7.16.0 resolution: "undici-types@npm:7.16.0" @@ -31726,13 +34925,29 @@ __metadata: languageName: node linkType: hard -"undici@npm:7.28.0, undici@npm:^7.24.0, undici@npm:^7.24.5": +"undici@npm:7.28.0, undici@npm:^7.2.3, undici@npm:^7.24.0, undici@npm:^7.24.5": version: 7.28.0 resolution: "undici@npm:7.28.0" checksum: 10c0/fe781983a26098795e99bb1f64906cbb7d0bcaa029a26baade007b53ea67f2631d189b8f9671a31f4c8d0cb3773b7559608628ba54452fef51fec90e7c78bb0d languageName: node linkType: hard +"undici@npm:^5.28.2": + version: 5.29.0 + resolution: "undici@npm:5.29.0" + dependencies: + "@fastify/busboy": "npm:^2.0.0" + checksum: 10c0/e4e4d631ca54ee0ad82d2e90e7798fa00a106e27e6c880687e445cc2f13b4bc87c5eba2a88c266c3eecffb18f26e227b778412da74a23acc374fca7caccec49b + languageName: node + linkType: hard + +"undici@npm:^6.19.0": + version: 6.23.0 + resolution: "undici@npm:6.23.0" + checksum: 10c0/d846b3fdfd05aa6081ba1eab5db6bbc21b283042c7a43722b86d1ee2bf749d7c990ceac0c809f9a07ffd88b1b0f4c0f548a8362c035088cb1997d63abdda499c + languageName: node + linkType: hard + "unicode-emoji-modifier-base@npm:^1.0.0": version: 1.0.0 resolution: "unicode-emoji-modifier-base@npm:1.0.0" @@ -31888,6 +35103,13 @@ __metadata: languageName: node linkType: hard +"universalify@npm:^0.2.0": + version: 0.2.0 + resolution: "universalify@npm:0.2.0" + checksum: 10c0/cedbe4d4ca3967edf24c0800cfc161c5a15e240dac28e3ce575c689abc11f2c81ccc6532c8752af3b40f9120fb5e454abecd359e164f4f6aa44c29cd37e194fe + languageName: node + linkType: hard + "universalify@npm:^2.0.0": version: 2.0.1 resolution: "universalify@npm:2.0.1" @@ -31972,7 +35194,7 @@ __metadata: languageName: node linkType: hard -"url-parse@npm:^1.5.10": +"url-parse@npm:^1.5.10, url-parse@npm:^1.5.3": version: 1.5.10 resolution: "url-parse@npm:1.5.10" dependencies: @@ -31992,6 +35214,25 @@ __metadata: languageName: node linkType: hard +"urllib@npm:^3.23.0": + version: 3.27.3 + resolution: "urllib@npm:3.27.3" + dependencies: + default-user-agent: "npm:^1.0.0" + digest-header: "npm:^1.0.0" + form-data-encoder: "npm:^1.7.2" + formdata-node: "npm:^4.3.3" + formstream: "npm:^1.1.1" + mime-types: "npm:^2.1.35" + pump: "npm:^3.0.0" + qs: "npm:^6.11.2" + type-fest: "npm:^4.3.1" + undici: "npm:^5.28.2" + ylru: "npm:^1.3.2" + checksum: 10c0/639a845ced56e619e05081cecbbaa79506e34339cfb3408831f1ebdd998c1ee776995072365dc8b818b0d61c33122c92237d32eb81cce4f8e5f304f12bd63f7a + languageName: node + linkType: hard + "urllib@npm:^4.9.0": version: 4.9.1 resolution: "urllib@npm:4.9.1" @@ -32135,7 +35376,16 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^3.4.0": +"uuid@npm:^11.0.0": + version: 11.1.0 + resolution: "uuid@npm:11.1.0" + bin: + uuid: dist/esm/bin/uuid + checksum: 10c0/34aa51b9874ae398c2b799c88a127701408cd581ee89ec3baa53509dd8728cbb25826f2a038f9465f8b7be446f0fbf11558862965b18d21c993684297628d4d3 + languageName: node + linkType: hard + +"uuid@npm:^3.3.2, uuid@npm:^3.4.0": version: 3.4.0 resolution: "uuid@npm:3.4.0" bin: @@ -32183,6 +35433,17 @@ __metadata: languageName: node linkType: hard +"v8-to-istanbul@npm:^9.0.1": + version: 9.3.0 + resolution: "v8-to-istanbul@npm:9.3.0" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.12" + "@types/istanbul-lib-coverage": "npm:^2.0.1" + convert-source-map: "npm:^2.0.0" + checksum: 10c0/968bcf1c7c88c04df1ffb463c179558a2ec17aa49e49376120504958239d9e9dad5281aa05f2a78542b8557f2be0b0b4c325710262f3b838b40d703d5ed30c23 + languageName: node + linkType: hard + "valid-url@npm:^1.0.9": version: 1.0.9 resolution: "valid-url@npm:1.0.9" @@ -32237,13 +35498,24 @@ __metadata: languageName: node linkType: hard -"vary@npm:^1, vary@npm:~1.1.2": +"vary@npm:^1, vary@npm:^1.1.2, vary@npm:~1.1.2": version: 1.1.2 resolution: "vary@npm:1.1.2" checksum: 10c0/f15d588d79f3675135ba783c91a4083dcd290a2a5be9fcb6514220a1634e23df116847b1cc51f66bfb0644cf9353b2abb7815ae499bab06e46dd33c1a6bf1f4f languageName: node linkType: hard +"verror@npm:1.10.0": + version: 1.10.0 + resolution: "verror@npm:1.10.0" + dependencies: + assert-plus: "npm:^1.0.0" + core-util-is: "npm:1.0.2" + extsprintf: "npm:^1.2.0" + checksum: 10c0/37ccdf8542b5863c525128908ac80f2b476eed36a32cb944de930ca1e2e78584cc435c4b9b4c68d0fc13a47b45ff364b4be43aa74f8804f9050140f660fb660d + languageName: node + linkType: hard + "vfile-location@npm:^4.0.0": version: 4.1.0 resolution: "vfile-location@npm:4.1.0" @@ -32309,6 +35581,15 @@ __metadata: languageName: node linkType: hard +"w3c-xmlserializer@npm:^4.0.0": + version: 4.0.0 + resolution: "w3c-xmlserializer@npm:4.0.0" + dependencies: + xml-name-validator: "npm:^4.0.0" + checksum: 10c0/02cc66d6efc590bd630086cd88252444120f5feec5c4043932b0d0f74f8b060512f79dc77eb093a7ad04b4f02f39da79ce4af47ceb600f2bf9eacdc83204b1a8 + languageName: node + linkType: hard + "w3c-xmlserializer@npm:^5.0.0": version: 5.0.0 resolution: "w3c-xmlserializer@npm:5.0.0" @@ -32318,6 +35599,15 @@ __metadata: languageName: node linkType: hard +"walker@npm:^1.0.8": + version: 1.0.8 + resolution: "walker@npm:1.0.8" + dependencies: + makeerror: "npm:1.0.12" + checksum: 10c0/a17e037bccd3ca8a25a80cb850903facdfed0de4864bd8728f1782370715d679fa72e0a0f5da7c1c1379365159901e5935f35be531229da53bbfc0efdabdb48e + languageName: node + linkType: hard + "watchpack@npm:^2.5.1": version: 2.5.1 resolution: "watchpack@npm:2.5.1" @@ -32366,6 +35656,13 @@ __metadata: languageName: node linkType: hard +"web-streams-polyfill@npm:4.0.0-beta.3": + version: 4.0.0-beta.3 + resolution: "web-streams-polyfill@npm:4.0.0-beta.3" + checksum: 10c0/a9596779db2766990117ed3a158e0b0e9f69b887a6d6ba0779940259e95f99dc3922e534acc3e5a117b5f5905300f527d6fbf8a9f0957faf1d8e585ce3452e8e + languageName: node + linkType: hard + "web-streams-polyfill@npm:^3.0.3": version: 3.3.3 resolution: "web-streams-polyfill@npm:3.3.3" @@ -32566,6 +35863,15 @@ __metadata: languageName: node linkType: hard +"whatwg-encoding@npm:^2.0.0": + version: 2.0.0 + resolution: "whatwg-encoding@npm:2.0.0" + dependencies: + iconv-lite: "npm:0.6.3" + checksum: 10c0/91b90a49f312dc751496fd23a7e68981e62f33afe938b97281ad766235c4872fc4e66319f925c5e9001502b3040dd25a33b02a9c693b73a4cbbfdc4ad10c3e3e + languageName: node + linkType: hard + "whatwg-encoding@npm:^3.1.1": version: 3.1.1 resolution: "whatwg-encoding@npm:3.1.1" @@ -32575,6 +35881,13 @@ __metadata: languageName: node linkType: hard +"whatwg-mimetype@npm:^3.0.0": + version: 3.0.0 + resolution: "whatwg-mimetype@npm:3.0.0" + checksum: 10c0/323895a1cda29a5fb0b9ca82831d2c316309fede0365047c4c323073e3239067a304a09a1f4b123b9532641ab604203f33a1403b5ca6a62ef405bcd7a204080f + languageName: node + linkType: hard + "whatwg-mimetype@npm:^4.0.0": version: 4.0.0 resolution: "whatwg-mimetype@npm:4.0.0" @@ -32582,6 +35895,16 @@ __metadata: languageName: node linkType: hard +"whatwg-url@npm:^11.0.0": + version: 11.0.0 + resolution: "whatwg-url@npm:11.0.0" + dependencies: + tr46: "npm:^3.0.0" + webidl-conversions: "npm:^7.0.0" + checksum: 10c0/f7ec264976d7c725e0696fcaf9ebe056e14422eacbf92fdbb4462034609cba7d0c85ffa1aab05e9309d42969bcf04632ba5ed3f3882c516d7b093053315bf4c1 + languageName: node + linkType: hard + "whatwg-url@npm:^14.0.0, whatwg-url@npm:^14.1.0": version: 14.2.0 resolution: "whatwg-url@npm:14.2.0" @@ -32716,6 +36039,15 @@ __metadata: languageName: node linkType: hard +"win-release@npm:^1.0.0": + version: 1.1.1 + resolution: "win-release@npm:1.1.1" + dependencies: + semver: "npm:^5.0.1" + checksum: 10c0/a4e845c186450092f28ad6a86c9d81fc187138754a59c4ef18641c41844ce9d0a3a496e86d8ec5fa81544a96361e483379ebaf9bdcb85a1ff48a1441cc00ec91 + languageName: node + linkType: hard + "winston-transport@npm:^4.5.0, winston-transport@npm:^4.7.0, winston-transport@npm:^4.9.0": version: 4.9.0 resolution: "winston-transport@npm:4.9.0" @@ -32746,7 +36078,7 @@ __metadata: languageName: node linkType: hard -"word-wrap@npm:^1.2.5": +"word-wrap@npm:^1.2.5, word-wrap@npm:~1.2.3": version: 1.2.5 resolution: "word-wrap@npm:1.2.5" checksum: 10c0/e0e4a1ca27599c92a6ca4c32260e8a92e8a44f4ef6ef93f803f8ed823f486e0889fc0b93be4db59c8d51b3064951d25e43d434e95dc8c960cc3a63d65d00ba20 @@ -32800,7 +36132,17 @@ __metadata: languageName: node linkType: hard -"ws@npm:*, ws@npm:8.21.0, ws@npm:^8.18.0, ws@npm:^8.18.2, ws@npm:^8.8.0": +"write-file-atomic@npm:^4.0.2": + version: 4.0.2 + resolution: "write-file-atomic@npm:4.0.2" + dependencies: + imurmurhash: "npm:^0.1.4" + signal-exit: "npm:^3.0.7" + checksum: 10c0/a2c282c95ef5d8e1c27b335ae897b5eca00e85590d92a3fd69a437919b7b93ff36a69ea04145da55829d2164e724bc62202cdb5f4b208b425aba0807889375c7 + languageName: node + linkType: hard + +"ws@npm:*, ws@npm:8.21.0, ws@npm:^8.11.0, ws@npm:^8.18.0, ws@npm:^8.18.2, ws@npm:^8.8.0": version: 8.21.0 resolution: "ws@npm:8.21.0" peerDependencies: @@ -32815,6 +36157,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:8.18.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10c0/25eb33aff17edcb90721ed6b0eb250976328533ad3cd1a28a274bd263682e7296a6591ff1436d6cbc50fa67463158b062f9d1122013b361cec99a05f84680e06 + languageName: node + linkType: hard + "xml-but-prettier@npm:^1.0.1": version: 1.0.1 resolution: "xml-but-prettier@npm:1.0.1" @@ -32824,6 +36181,13 @@ __metadata: languageName: node linkType: hard +"xml-name-validator@npm:^4.0.0": + version: 4.0.0 + resolution: "xml-name-validator@npm:4.0.0" + checksum: 10c0/c1bfa219d64e56fee265b2bd31b2fcecefc063ee802da1e73bad1f21d7afd89b943c9e2c97af2942f60b1ad46f915a4c81e00039c7d398b53cf410e29d3c30bd + languageName: node + linkType: hard + "xml-name-validator@npm:^5.0.0": version: 5.0.0 resolution: "xml-name-validator@npm:5.0.0" @@ -32986,7 +36350,7 @@ __metadata: languageName: node linkType: hard -"yauzl@npm:^3.2.1": +"yauzl@npm:^3.0.0, yauzl@npm:^3.2.1": version: 3.3.0 resolution: "yauzl@npm:3.3.0" dependencies: @@ -32996,6 +36360,13 @@ __metadata: languageName: node linkType: hard +"ylru@npm:^1.2.0, ylru@npm:^1.3.2": + version: 1.4.0 + resolution: "ylru@npm:1.4.0" + checksum: 10c0/eaadc38ed6d78d4fda49abed45cfdaf149bd334df761dbeadd3cff62936d25ffa94571f84c25b64a9a4b5efd8f489ee6fee3eaaf8e7b2886418a3bcb9ec84b84 + languageName: node + linkType: hard + "ylru@npm:^2.0.0": version: 2.0.0 resolution: "ylru@npm:2.0.0" @@ -33074,7 +36445,7 @@ __metadata: languageName: node linkType: hard -"zod-to-json-schema@npm:^3.25.1": +"zod-to-json-schema@npm:^3.20.4, zod-to-json-schema@npm:^3.25.1": version: 3.25.2 resolution: "zod-to-json-schema@npm:3.25.2" peerDependencies: @@ -33083,7 +36454,7 @@ __metadata: languageName: node linkType: hard -"zod-validation-error@npm:^3.0.3": +"zod-validation-error@npm:^3.0.3, zod-validation-error@npm:^3.4.0": version: 3.4.0 resolution: "zod-validation-error@npm:3.4.0" peerDependencies: