diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2f756b1d6..7710bea49 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -43,7 +43,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: Replace values shell: bash env: @@ -79,7 +79,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: Replace values shell: bash env: diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..a45fd52cc --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24 diff --git a/Dockerfile b/Dockerfile index 376594a5a..807bd912e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:iron-bookworm AS builder +FROM node:24-bookworm AS builder ARG PKG_VERSION # ARG GITHUB_TOKEN @@ -23,7 +23,7 @@ RUN npm version $PKG_VERSION --allow-same-version --no-git-tag-version RUN npm pack -FROM registry.access.redhat.com/ubi9/nodejs-20-minimal:latest +FROM registry.access.redhat.com/ubi9/nodejs-24-minimal:latest USER root # Install dependencies for logging and development diff --git a/docs/swagger.yaml b/docs/swagger.yaml index ca2398f60..86d383d26 100755 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,6 +1,6 @@ openapi : "3.0.0" info: - version: 3.6.0 + version: 3.7.0 title: Datasance PoT Controller paths: /status: @@ -1772,6 +1772,37 @@ paths: description: Not Authorized "500": description: Internal Server Error + post: + tags: + - Microservices + summary: Creates a new microservice + operationId: createMicroservice + security: + - authToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/NewMicroserviceRequest" + responses: + "201": + description: Created + content: + application/json: + schema: + type: object + properties: + uuid: + type: string + name: + type: string + "400": + description: Bad Request + "401": + description: Not Authorized + "500": + description: Internal Server Error /microservices/yaml: post: tags: @@ -1787,7 +1818,7 @@ paths: schema: type: object properties: - microsoervice: + microservice: type: string format: binary responses: @@ -1906,68 +1937,6 @@ paths: description: Invalid Registry Id "500": description: Internal Server Error - /microservices/pub/{tag}: - get: - tags: - - Microservices - summary: Get list of microservices with filtered pub tag - operationId: listMicroserviceInfoByPubTag - parameters: - - in: path - name: tag - description: Microservice Pub Tags - required: true - schema: - type: string - security: - - authToken: [] - responses: - "200": - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - $ref: "#/components/schemas/GetMicroservicesResponse" - "401": - description: Not Authorized - "500": - description: Internal Server Error - /microservices/sub/{tag}: - get: - tags: - - Microservices - summary: Get list of microservices with filtered sub tag - operationId: listMicroserviceInfoBySubTag - parameters: - - in: path - name: tag - description: Microservice Pub Tags - required: true - schema: - type: string - security: - - authToken: [] - responses: - "200": - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - $ref: "#/components/schemas/GetMicroservicesResponse" - "401": - description: Not Authorized - "500": - description: Internal Server Error /microservices/system: get: tags: @@ -3434,167 +3403,6 @@ paths: description: Not Authorized "500": description: Internal Server Error - /routes: - get: - tags: - - Routing - summary: Get routes - operationId: getRoutes - security: - - authToken: [] - responses: - "200": - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - $ref: "#/components/schemas/RouteListResponse" - "401": - description: Not Authorized - "500": - description: Internal Server Error - post: - tags: - - Routing - summary: Creates a new route - operationId: createRoute - security: - - authToken: [] - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/NewRouteRequest" - description: Route Info - required: true - responses: - "201": - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - id: - type: string - "400": - description: Bad Request - "401": - description: Not Authorized - "409": - description: Duplicate Name - "500": - description: Internal Server Error - "/routes/{name}": - get: - tags: - - Routing - summary: Gets a route info - operationId: getRoute - parameters: - - in: path - name: name - description: Route name - required: true - schema: - type: string - security: - - authToken: [] - responses: - "200": - description: Route Info - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - $ref: "#/components/schemas/RouteResponse" - "401": - description: Not Authorized - "404": - description: Invalid Route Id - "500": - description: Internal Server Error - patch: - tags: - - Routing - summary: Updates a route - operationId: updateRoute - parameters: - - in: path - name: name - description: Route name - required: true - schema: - type: string - security: - - authToken: [] - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/UpdateRouteRequest" - description: Route Info - required: true - responses: - "204": - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - "400": - description: Bad Request - "401": - description: Not Authorized - "404": - description: Invalid Route Id - "409": - description: Duplicate Name - "500": - description: Internal Server Error - delete: - tags: - - Routing - summary: Deletes a route - operationId: deleteRoute - parameters: - - in: path - name: name - description: Route name - required: true - schema: - type: string - security: - - authToken: [] - responses: - "204": - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - "401": - description: Not Authorized - "404": - description: Invalid Route Id - "500": - description: Internal Server Error /edgeResources: get: tags: @@ -5697,6 +5505,13 @@ paths: - ServiceAccounts summary: Lists all service accounts operationId: listServiceAccounts + parameters: + - in: query + name: applicationName + description: Filter by application name + required: false + schema: + type: string security: - authToken: [] responses: @@ -5753,6 +5568,16 @@ paths: tags: - ServiceAccounts summary: Create a service account from YAML file + description: | + The YAML file must include metadata.applicationName (application name this service account belongs to), + metadata.name (service account name), and roleRef with a name. Example: + kind: ServiceAccount + metadata: + name: my-sa + applicationName: my-app + roleRef: + kind: Role + name: microservice operationId: createServiceAccountFromYAML security: - authToken: [] @@ -5786,13 +5611,19 @@ paths: description: ServiceAccount Already Exists "500": description: Internal Server Error - "/serviceaccounts/{name}": + "/serviceaccounts/{appName}/{name}": get: tags: - ServiceAccounts - summary: Gets a service account by name + summary: Gets a service account by application name and service account name operationId: getServiceAccount parameters: + - in: path + name: appName + description: Application name + required: true + schema: + type: string - in: path name: name description: ServiceAccount name @@ -5825,6 +5656,12 @@ paths: summary: Updates an existing service account operationId: updateServiceAccount parameters: + - in: path + name: appName + description: Application name + required: true + schema: + type: string - in: path name: name description: ServiceAccount name @@ -5865,6 +5702,12 @@ paths: summary: Deletes a service account operationId: deleteServiceAccount parameters: + - in: path + name: appName + description: Application name + required: true + schema: + type: string - in: path name: name description: ServiceAccount name @@ -5885,15 +5728,23 @@ paths: description: Not Authorized "404": description: ServiceAccount Not Found + "409": + description: Conflict - ServiceAccount is referenced by a microservice "500": description: Internal Server Error - "/serviceaccounts/yaml/{name}": + "/serviceaccounts/yaml/{appName}/{name}": patch: tags: - ServiceAccounts summary: Updates an existing service account using YAML operationId: updateServiceAccountFromYAML parameters: + - in: path + name: appName + description: Application name + required: true + schema: + type: string - in: path name: name description: ServiceAccount name @@ -5932,691 +5783,1743 @@ paths: description: ServiceAccount Not Found "500": description: Internal Server Error -tags: - - name: Controller - description: Manage your controller - - name: ioFog - description: Manage your agents - - name: Application - description: Manage your applications - - name: Application Template - description: Manage your application templates - - name: Catalog - description: Manage your catalog - - name: Registries - description: Manage your registries - - name: Microservices - description: Manage your microservices - - name: Routing - description: Manage your routes - - name: Edge Resource - description: Manage your Edge Resources - - name: Diagnostics - description: Diagnostic your microservices - - name: Tunnel - description: Manage ssh tunnels - - name: Agent - description: Used by your agents to communicate with your controller - - name: User - description: Manage your users - - name: Secrets - description: Manage your secrets - - name: Certificates - description: Manage your certificates - - name: Services - description: Manage your services - - name: VolumeMounts - description: Manage your volume mounts - - name: ConfigMap - description: Manage your config maps - - name: Events - description: Manage audit events - - name: Roles - description: Manage RBAC roles - - name: RoleBindings - description: Manage RBAC role bindings - - name: ServiceAccounts - description: Manage RBAC service accounts -servers: - - url: http://localhost:51121/api/v3 -components: - securitySchemes: - authToken: - type: http - scheme: bearer - bearerFormat: JWT - requestBodies: - UpdateIOFogNodeRequestBody: - content: - application/json: + /nats/operator: + get: + tags: + - NATS + summary: Gets current NATS operator metadata + operationId: getNatsOperator + security: + - authToken: [] + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsOperatorResponse" + "401": + description: Not Authorized + /nats/operator/rotate: + post: + tags: + - NATS + summary: Rotates NATS operator keys and JWT + description: Schedules account/user re-sign and resolver reconciliation in background after operator rotation is accepted. + operationId: rotateNatsOperator + security: + - authToken: [] + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsOperatorResponse" + "401": + description: Not Authorized + /nats/bootstrap: + get: + tags: + - NATS + summary: Returns NATS operator and hub system user bootstrap data for K8s installer + operationId: getNatsBootstrap + security: + - authToken: [] + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsBootstrapResponse" + "401": + description: Not Authorized + "403": + description: Forbidden (only available when Controller runs on Kubernetes control plane) + "404": + description: Not Found (bootstrap data or secrets missing) + /nats/hub: + get: + tags: + - NATS + summary: Gets default NATS hub configuration + operationId: getNatsHub + security: + - authToken: [] + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsHubResponse" + "401": + description: Not Authorized + "404": + description: Not Found + put: + tags: + - NATS + summary: Creates or updates default NATS hub + operationId: upsertNatsHub + security: + - authToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/NatsHubRequest" + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsHubResponse" + "400": + description: Bad Request + "401": + description: Not Authorized + /nats/users: + get: + tags: + - NATS + summary: Lists all NATS users across accounts + operationId: listAllNatsUsers + security: + - authToken: [] + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsAllUsersListResponse" + "401": + description: Not Authorized + /nats/accounts: + get: + tags: + - NATS + summary: Lists NATS accounts + operationId: listNatsAccounts + security: + - authToken: [] + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsAccountsListResponse" + "401": + description: Not Authorized + /nats/accounts/{appName}: + get: + tags: + - NATS + summary: Gets NATS account for application + operationId: getNatsAccountByApp + parameters: + - in: path + name: appName + required: true schema: - $ref: "#/components/schemas/UpdateIOFogNodeRequestBody" - required: true - CreateUpdateCatalogItemRequestBody: - content: - application/json: + type: string + security: + - authToken: [] + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsAccountResponse" + "401": + description: Not Authorized + "404": + description: Not Found + post: + tags: + - NATS + summary: Ensures NATS account for application + operationId: ensureNatsAccountByApp + parameters: + - in: path + name: appName + required: true schema: - $ref: "#/components/schemas/CreateUpdateCatalogItemRequestBody" - description: Microservice Catalog Item Info - required: true - HalInfo: - content: - application/json: + type: string + security: + - authToken: [] + requestBody: + required: false + content: + application/json: + schema: + $ref: "#/components/schemas/NatsAccountEnsureRequest" + responses: + "201": + description: Created + content: + application/json: + schema: + $ref: "#/components/schemas/NatsAccountResponse" + "400": + description: Bad Request (e.g. application already has NATS enabled or unknown rule name) + "401": + description: Not Authorized + "404": + description: Not Found + /nats/accounts/{appName}/users: + get: + tags: + - NATS + summary: Lists NATS users for application account + operationId: listNatsUsersByApp + parameters: + - in: path + name: appName + required: true schema: - $ref: "#/components/schemas/HalInfo" - required: true - ApplicationTemplateCreateRequest: - content: - application/json: + type: string + security: + - authToken: [] + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsUsersListResponse" + "401": + description: Not Authorized + "404": + description: Not Found + post: + tags: + - NATS + summary: Creates NATS user for application account + operationId: createNatsUserByApp + parameters: + - in: path + name: appName + required: true schema: - $ref: "#/components/schemas/ApplicationTemplateCreateRequest" - required: true - NewFlowRequest: - content: - application/json: + type: string + security: + - authToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/NatsUserCreateRequest" + responses: + "201": + description: Created + content: + application/json: + schema: + $ref: "#/components/schemas/NatsUserResponse" + "400": + description: Bad Request + "401": + description: Not Authorized + "404": + description: Not Found + /nats/accounts/{appName}/users/{userName}/creds: + get: + tags: + - NATS + summary: Gets NATS creds for specific account user + operationId: getNatsUserCreds + parameters: + - in: path + name: appName + required: true schema: - $ref: "#/components/schemas/NewFlowRequest" - description: New Flow Info - required: true - schemas: - EventRecord: + type: string + - in: path + name: userName + required: true + schema: + type: string + security: + - authToken: [] + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsCredsResponse" + "401": + description: Not Authorized + "404": + description: Not Found + /nats/accounts/{appName}/users/{userName}: + delete: + tags: + - NATS + summary: Deletes NATS account user + operationId: deleteNatsUserByApp + parameters: + - in: path + name: appName + required: true + schema: + type: string + - in: path + name: userName + required: true + schema: + type: string + security: + - authToken: [] + responses: + "204": + description: No Content + "400": + description: Bad Request (e.g. user linked to existing microservice) + "401": + description: Not Authorized + "404": + description: Not Found + /nats/accounts/{appName}/mqtt-bearer: + post: + tags: + - NATS + summary: Creates MQTT bearer NATS user JWT + operationId: createNatsMqttBearer + parameters: + - in: path + name: appName + required: true + schema: + type: string + security: + - authToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/NatsUserCreateRequest" + responses: + "201": + description: Created + content: + application/json: + schema: + $ref: "#/components/schemas/NatsUserResponse" + "400": + description: Bad Request + "401": + description: Not Authorized + "404": + description: Not Found + /nats/accounts/{appName}/mqtt-bearer/{userName}: + delete: + tags: + - NATS + summary: Deletes MQTT bearer NATS user + operationId: deleteNatsMqttBearer + parameters: + - in: path + name: appName + required: true + schema: + type: string + - in: path + name: userName + required: true + schema: + type: string + security: + - authToken: [] + responses: + "204": + description: No Content + "400": + description: Bad Request (e.g. not a bearer user or user linked to microservice) + "401": + description: Not Authorized + "404": + description: Not Found + /nats/account-rules: + get: + tags: + - NATS + summary: Lists NATS account rules + operationId: listNatsAccountRules + security: + - authToken: [] + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsAccountRuleListResponse" + "401": + description: Not Authorized + post: + tags: + - NATS + summary: Creates NATS account rule + operationId: createNatsAccountRule + security: + - authToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/NatsAccountRulePayload" + responses: + "201": + description: Created + content: + application/json: + schema: + $ref: "#/components/schemas/NatsAccountRulePayload" + "400": + description: Bad Request + "401": + description: Not Authorized + /nats/account-rules/yaml: + post: + tags: + - NATS + summary: Creates NATS account rule from YAML + operationId: createNatsAccountRuleYaml + security: + - authToken: [] + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + natsAccountRule: + type: string + format: binary + responses: + "201": + description: Created + "400": + description: Bad Request + "401": + description: Not Authorized + /nats/account-rules/{ruleName}: + patch: + tags: + - NATS + summary: Updates NATS account rule + description: Returns updated rule immediately and schedules downstream account JWT reissue/reconciliation in background. + operationId: updateNatsAccountRule + parameters: + - in: path + name: ruleName + required: true + schema: + type: string + security: + - authToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/NatsAccountRulePayload" + responses: + "200": + description: Success + "400": + description: Bad Request + "401": + description: Not Authorized + "404": + description: Not Found + delete: + tags: + - NATS + summary: Deletes NATS account rule + description: Rebinds applications using this rule to default rule and schedules account JWT reissue/reconciliation in background. + operationId: deleteNatsAccountRule + parameters: + - in: path + name: ruleName + required: true + schema: + type: string + security: + - authToken: [] + responses: + "204": + description: Deleted + "401": + description: Not Authorized + "404": + description: Not Found + /nats/account-rules/yaml/{ruleName}: + patch: + tags: + - NATS + summary: Updates NATS account rule from YAML + description: Returns updated rule immediately and schedules downstream account JWT reissue/reconciliation in background. + operationId: updateNatsAccountRuleYaml + parameters: + - in: path + name: ruleName + required: true + schema: + type: string + security: + - authToken: [] + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + natsAccountRule: + type: string + format: binary + responses: + "200": + description: Updated + "400": + description: Bad Request + "401": + description: Not Authorized + "404": + description: Not Found + /nats/user-rules: + get: + tags: + - NATS + summary: Lists NATS user rules + operationId: listNatsUserRules + security: + - authToken: [] + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/NatsUserRuleListResponse" + "401": + description: Not Authorized + post: + tags: + - NATS + summary: Creates NATS user rule + operationId: createNatsUserRule + security: + - authToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/NatsUserRulePayload" + responses: + "201": + description: Created + content: + application/json: + schema: + $ref: "#/components/schemas/NatsUserRulePayload" + "400": + description: Bad Request + "401": + description: Not Authorized + /nats/user-rules/yaml: + post: + tags: + - NATS + summary: Creates NATS user rule from YAML + operationId: createNatsUserRuleYaml + security: + - authToken: [] + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + natsUserRule: + type: string + format: binary + responses: + "201": + description: Created + "400": + description: Bad Request + "401": + description: Not Authorized + /nats/user-rules/{ruleName}: + patch: + tags: + - NATS + summary: Updates NATS user rule + description: Returns updated rule immediately and schedules bound user JWT+creds reissue/reconciliation in background. + operationId: updateNatsUserRule + parameters: + - in: path + name: ruleName + required: true + schema: + type: string + security: + - authToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/NatsUserRulePayload" + responses: + "200": + description: Updated + "400": + description: Bad Request + "401": + description: Not Authorized + "404": + description: Not Found + delete: + tags: + - NATS + summary: Deletes NATS user rule + description: Rebinds microservices using this rule to default rule and schedules user JWT+creds reissue/reconciliation in background. + operationId: deleteNatsUserRule + parameters: + - in: path + name: ruleName + required: true + schema: + type: string + security: + - authToken: [] + responses: + "204": + description: Deleted + "401": + description: Not Authorized + "404": + description: Not Found + /nats/user-rules/yaml/{ruleName}: + patch: + tags: + - NATS + summary: Updates NATS user rule from YAML + description: Returns updated rule immediately and schedules bound user JWT+creds reissue/reconciliation in background. + operationId: updateNatsUserRuleYaml + parameters: + - in: path + name: ruleName + required: true + schema: + type: string + security: + - authToken: [] + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + natsUserRule: + type: string + format: binary + responses: + "200": + description: Updated + "400": + description: Bad Request + "401": + description: Not Authorized + "404": + description: Not Found +tags: + - name: Controller + description: Manage your controller + - name: ioFog + description: Manage your agents + - name: Application + description: Manage your applications + - name: Application Template + description: Manage your application templates + - name: Catalog + description: Manage your catalog + - name: Registries + description: Manage your registries + - name: Microservices + description: Manage your microservices + - name: NATS + description: Manage NATS operator, hub, accounts, users, and rules + - name: Edge Resource + description: Manage your Edge Resources + - name: Diagnostics + description: Diagnostic your microservices + - name: Tunnel + description: Manage ssh tunnels + - name: Agent + description: Used by your agents to communicate with your controller + - name: User + description: Manage your users + - name: Secrets + description: Manage your secrets + - name: Certificates + description: Manage your certificates + - name: Services + description: Manage your services + - name: VolumeMounts + description: Manage your volume mounts + - name: ConfigMap + description: Manage your config maps + - name: Events + description: Manage audit events + - name: Roles + description: Manage RBAC roles + - name: RoleBindings + description: Manage RBAC role bindings + - name: ServiceAccounts + description: Manage RBAC service accounts +servers: + - url: http://localhost:51121/api/v3 +components: + securitySchemes: + authToken: + type: http + scheme: bearer + bearerFormat: JWT + requestBodies: + UpdateIOFogNodeRequestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/UpdateIOFogNodeRequestBody" + required: true + CreateUpdateCatalogItemRequestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/CreateUpdateCatalogItemRequestBody" + description: Microservice Catalog Item Info + required: true + HalInfo: + content: + application/json: + schema: + $ref: "#/components/schemas/HalInfo" + required: true + ApplicationTemplateCreateRequest: + content: + application/json: + schema: + $ref: "#/components/schemas/ApplicationTemplateCreateRequest" + required: true + NewFlowRequest: + content: + application/json: + schema: + $ref: "#/components/schemas/NewFlowRequest" + description: New Flow Info + required: true + schemas: + EventRecord: + type: object + properties: + id: + type: integer + timestamp: + type: integer + format: int64 + eventType: + type: string + endpointType: + type: string + actorId: + type: string + nullable: true + method: + type: string + nullable: true + resourceType: + type: string + nullable: true + resourceId: + type: string + nullable: true + endpointPath: + type: string + ipAddress: + type: string + nullable: true + status: + type: string + statusCode: + type: integer + nullable: true + statusMessage: + type: string + nullable: true + requestId: + type: string + nullable: true + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + required: + - id + - timestamp + - eventType + - endpointType + - endpointPath + - status + - createdAt + - updatedAt + EventListResponse: + type: object + properties: + events: + type: array + items: + $ref: "#/components/schemas/EventRecord" + total: + type: integer + limit: + type: integer + offset: + type: integer + required: + - events + - total + - limit + - offset + EventDeleteRequest: + type: object + properties: + days: + type: integer + minimum: 0 + maximum: 365 + required: + - days + EventDeleteResponse: + type: object + properties: + deletedCount: + type: integer + deletedBefore: + type: string + format: date-time + nullable: true + deletedAt: + type: string + format: date-time + deletedAll: + type: boolean + required: + - deletedCount + - deletedAt + - deletedAll + EdgeResourcesListResponse: + type: object + properties: + edgeResources: + type: array + items: + type: object + properties: + id: + type: number + name: + type: string + description: + type: string + version: + type: string + interfaceProtocol: + type: string + display: + $ref: '#/components/schemas/EdgeResourceDisplay' + EdgeResourceGetResponse: + type: object + properties: + id: + type: number + name: + type: string + description: + type: string + version: + type: string + interfaceProtocol: + type: string + display: + $ref: '#/components/schemas/EdgeResourceDisplay' + interface: + $ref: '#/components/schemas/EdgeResourceHTTPInterface' + custom: + type: object + EdgeResourceDisplay: + type: object + properties: + color: + type: string + icon: + type: string + name: + type: string + EdgeResourceHTTPInterface: + type: object + properties: + endpoints: + type: array + items: + type: object + properties: + name: + type: number + description: + type: number + method: + type: string + url: + type: string + requestType: + type: string + responseType: + type: string + requestPayloadExample: + type: string + responsePayloadExample: + type: string + EdgeResourceCreateSchema: + type: object + properties: + name: + type: string + description: + type: string + version: + type: string + interfaceProtocol: + type: string + display: + $ref: '#/components/schemas/EdgeResourceDisplay' + interface: + $ref: '#/components/schemas/EdgeResourceHTTPInterface' + EdgeResourceCreateResponse: + $ref: '#/components/schemas/EdgeResourceGetResponse' + EdgeResourceLinkSchema: + type: object + properties: + uuid: + type: string + ApplicationCreateFromTemplateRequest: + type: object + properties: + name: + type: string + description: + type: string + isActivated: + type: boolean + template: + type: object + properties: + name: + type: string + variables: + type: array + items: + type: object + properties: + key: + type: string + value: + type: string + ApplicationCreateRequest: + type: object + properties: + name: + type: string + description: + type: string + isActivated: + type: boolean + microservices: + type: array + items: + type: object + properties: + name: + type: string + config: + type: string + annotations: + type: string + catalogItemId: + type: integer + registryId: + type: integer + images: + type: array + items: + properties: + containerImage: + type: string + fogTypeId: + type: string + iofogUuid: + type: string + hostNetworkMode: + type: boolean + isPrivileged: + type: boolean + logSize: + type: number + rebuild: + type: boolean + volumeMappings: + type: array + items: + $ref: "#/components/schemas/VolumeMapping" + envs: + type: array + items: + type: object + properties: + key: + type: string + value: + type: string + runAsUser: + type: string + platform: + type: string + runtime: + type: string + cdiDevices: + type: array + items: + type: string + capAdd: + type: array + items: + type: string + capDrop: + type: array + items: + type: string + cmd: + type: array + items: + type: string + ports: + type: array + items: + $ref: "#/components/schemas/PortMappingsRequest" + natsConfig: + $ref: "#/components/schemas/NatsConfigObject" + natsConfig: + $ref: "#/components/schemas/NatsConfigObject" + ApplicationCreateResponse: + type: object + properties: + id: + type: number + name: + type: string + ApplicationGetResponse: + type: object + properties: + id: + type: number + name: + type: string + description: + type: string + isActivated: + type: boolean + natsConfig: + $ref: "#/components/schemas/NatsConfigObject" + microservices: + type: array + items: + $ref: "#/components/schemas/GetMicroservicesResponse" + ApplicationListResponse: + type: object + properties: + applications: + type: array + items: + $ref: "#/components/schemas/ApplicationGetResponse" + ApplicationTemplateCreateRequest: + type: object + properties: + name: + type: string + description: + type: string + variables: + type: array + items: + type: object + properties: + key: + type: string + description: + type: string + defaultValue: + type: string + application: + type: object + properties: + microservices: + type: array + items: + type: object + properties: + name: + type: string + config: + type: string + annotations: + type: string + catalogItemId: + type: integer + registryId: + type: integer + images: + type: array + items: + properties: + containerImage: + type: string + fogTypeId: + type: string + iofogUuid: + type: string + agentName: + type: string + hostNetworkMode: + type: boolean + isPrivileged: + type: boolean + logSize: + type: number + rebuild: + type: boolean + volumeMappings: + type: array + items: + $ref: "#/components/schemas/VolumeMapping" + envs: + type: array + items: + type: object + properties: + key: + type: string + value: + type: string + runAsUser: + type: number + platform: + type: string + runtime: + type: string + cdiDevices: + type: array + items: + type: string + capAdd: + type: array + items: + type: string + capDrop: + type: array + items: + type: string + cmd: + type: array + items: + type: string + ports: + type: array + items: + $ref: "#/components/schemas/PortMappingsRequest" + natsConfig: + $ref: "#/components/schemas/NatsConfigObject" + natsConfig: + $ref: "#/components/schemas/NatsConfigObject" + ApplicationTemplateCreateResponse: type: object properties: id: - type: integer - timestamp: - type: integer - format: int64 - eventType: - type: string - endpointType: - type: string - actorId: - type: string - nullable: true - method: - type: string - nullable: true - resourceType: - type: string - nullable: true - resourceId: - type: string - nullable: true - endpointPath: - type: string - ipAddress: - type: string - nullable: true - status: - type: string - statusCode: - type: integer - nullable: true - statusMessage: + type: number + name: type: string - nullable: true - requestId: + ApplicationTemplatePatchRequest: + type: object + properties: + description: + type: number + name: type: string - nullable: true - createdAt: + ApplicationTemplateGetResponse: + type: object + properties: + id: + type: number + name: type: string - format: date-time - updatedAt: + description: type: string - format: date-time - required: - - id - - timestamp - - eventType - - endpointType - - endpointPath - - status - - createdAt - - updatedAt - EventListResponse: + application: + type: object + properties: + microservices: + type: array + items: + $ref: "#/components/schemas/GetMicroservicesResponse" + natsConfig: + $ref: "#/components/schemas/NatsConfigObject" + ApplicationTemplateListResponse: type: object properties: - events: + applicationTemplates: type: array items: - $ref: "#/components/schemas/EventRecord" - total: - type: integer - limit: - type: integer - offset: - type: integer - required: - - events - - total - - limit - - offset - EventDeleteRequest: + $ref: "#/components/schemas/ApplicationTemplateGetResponse" + ServiceStatusResponse: type: object properties: - days: - type: integer - minimum: 0 - maximum: 365 - required: - - days - EventDeleteResponse: + status: + type: string + example: ok + timestamp: + type: number + IOFogTypesResponse: type: object properties: - deletedCount: - type: integer - deletedBefore: + fogTypes: + type: array + items: + $ref: "#/components/schemas/IOFogType" + IOFogType: + type: object + properties: + id: + type: number + name: type: string - format: date-time - nullable: true - deletedAt: + image: type: string - format: date-time - deletedAll: - type: boolean - required: - - deletedCount - - deletedAt - - deletedAll - EdgeResourcesListResponse: + description: + type: string + IOFogNodesListFilters: + type: array + items: + type: object + properties: + key: + type: string + value: + type: string + condition: + type: string + IOFogNodesListResponse: type: object properties: - edgeResources: + fogs: type: array items: - type: object - properties: - id: - type: number - name: - type: string - description: - type: string - version: - type: string - interfaceProtocol: - type: string - display: - $ref: '#/components/schemas/EdgeResourceDisplay' - EdgeResourceGetResponse: + $ref: "#/components/schemas/IOFogNodeInfoResponse" + IOFogNodeInfoResponse: type: object properties: - id: + lastActive: + type: number + daemonOperatingDuration: + type: number + daemonLastStart: + type: number + repositoryCount: + type: number + systemTime: + type: number + lastStatusTime: + type: number + processedMessages: + type: number + lastCommandTime: + type: number + logFileCount: + type: number + uuid: + type: string + name: + type: string + location: + type: string + gpsMode: + type: string + latitude: + type: number + longitude: + type: number + description: + type: string + daemonStatus: + type: string + memoryUsage: + type: number + diskUsage: + type: number + cpuUsage: + type: number + memoryViolation: + type: boolean + diskViolation: + type: boolean + cpuViolation: + type: boolean + systemTotalCpu: + type: number + catalogItemStatus: + type: string + repositoryStatus: + type: string + ipAddress: + type: string + ipAddressExternal: + type: string + catalogItemMessageCounts: + type: number + messageSpeed: + type: number + networkInterface: + type: string + dockerUrl: + type: string + containerEngine: + type: string + deploymentType: + type: string + diskLimit: + type: number + diskDirectory: + type: string + memoryLimit: + type: number + cpuLimit: type: number - name: - type: string - description: + logLimit: + type: number + logDirectory: type: string + bluetoothEnabled: + type: boolean + abstractedHardwareEnabled: + type: boolean version: type: string - interfaceProtocol: - type: string - display: - $ref: '#/components/schemas/EdgeResourceDisplay' - interface: - $ref: '#/components/schemas/EdgeResourceHTTPInterface' - custom: - type: object - EdgeResourceDisplay: - type: object - properties: - color: + isReadyToUpgrade: + type: boolean + isReadyToRollback: + type: boolean + statusFrequency: + type: number + changeFrequency: + type: number + deviceScanFrequency: + type: number + tunnel: type: string - icon: + watchdogEnabled: + type: boolean + dockerPruningFrequency: + type: number + availableDiskThreshold: + type: number + logLevel: type: string - name: + isSystem: + type: boolean + routerId: + type: number + createAt: + type: number + updatedAt: + type: number + fogTypeId: + type: number + routerMode: type: string - EdgeResourceHTTPInterface: - type: object - properties: - endpoints: + enum: + - none + - edge + - interior + messagingPort: + type: number + upstreamRouters: type: array items: - type: object - properties: - name: - type: number - description: - type: number - method: - type: string - url: - type: string - requestType: - type: string - responseType: - type: string - requestPayloadExample: - type: string - responsePayloadExample: - type: string - EdgeResourceCreateSchema: - type: object - properties: - name: - type: string - description: - type: string - version: + type: string + natsMode: type: string - interfaceProtocol: + enum: + - none + - leaf + - server + natsServerPort: + type: number + natsLeafPort: + type: number + natsClusterPort: + type: number + natsMqttPort: + type: number + natsHttpPort: + type: number + jsStorageSize: type: string - display: - $ref: '#/components/schemas/EdgeResourceDisplay' - interface: - $ref: '#/components/schemas/EdgeResourceHTTPInterface' - EdgeResourceCreateResponse: - $ref: '#/components/schemas/EdgeResourceGetResponse' - EdgeResourceLinkSchema: - type: object - properties: - uuid: + description: JetStream max file store (e.g. 10g). Units m, mb, g, gb, t, tb. + jsMemoryStoreSize: type: string - ApplicationCreateFromTemplateRequest: + description: JetStream max memory store (e.g. 1g). Units m, mb, g, gb, t, tb. + upstreamNatsServers: + type: array + items: + type: string + UpdateIOFogNodeRequestBody: type: object properties: name: type: string + location: + type: string + latitude: + type: number + longitude: + type: number description: type: string - isActivated: - type: boolean - template: - type: object - properties: - name: - type: string - variables: - type: array - items: - type: object - properties: - key: - type: string - value: - type: string - ApplicationCreateRequest: - type: object - properties: - name: + dockerUrl: type: string - description: + default: unix:///var/run/docker.sock + containerEngine: type: string - isActivated: - type: boolean - microservices: - type: array - items: - type: object - properties: - name: - type: string - config: - type: string - annotations: - type: string - catalogItemId: - type: integer - registryId: - type: integer - images: - type: array - items: - properties: - containerImage: - type: string - fogTypeId: - type: string - iofogUuid: - type: string - hostNetworkMode: - type: boolean - isPrivileged: - type: boolean - logSize: - type: number - rebuild: - type: boolean - volumeMappings: - type: array - items: - $ref: "#/components/schemas/VolumeMapping" - envs: - type: array - items: - type: object - properties: - key: - type: string - value: - type: string - runAsUser: - type: string - platform: - type: string - runtime: - type: string - cdiDevices: - type: array - items: - type: string - capAdd: - type: array - items: - type: string - capDrop: - type: array - items: - type: string - cmd: - type: array - items: - type: string - ports: - type: array - items: - $ref: "#/components/schemas/PortMappingsRequest" - pubTags: - type: array - items: - type: string - subTags: - type: array - items: - type: string - routes: - type: array - items: - type: object - properties: - from: - type: string - to: - type: string - name: - type: string - ApplicationCreateResponse: - type: object - properties: - id: + default: docker + deploymentType: + type: string + default: native + diskLimit: + type: number + default: 50 + diskDirectory: + type: string + default: /var/lib/iofog-agent + memoryLimit: + type: number + default: 4096 + format: MB + cpuLimit: + type: number + default: 80 + format: percent + logLimit: type: number - name: + default: 10 + format: GB + logDirectory: type: string - ApplicationGetResponse: - type: object - properties: - id: + default: /var/log/iofog + logFileCount: type: number - name: - type: string - description: + default: 10 + statusFrequency: + type: number + default: 10 + format: seconds + changeFrequency: + type: number + default: 20 + format: seconds + deviceScanFrequency: + type: number + default: 20 + format: seconds + bluetoothEnabled: + type: boolean + default: false + watchdogEnabled: + type: boolean + default: true + abstractedHardwareEnabled: + type: boolean + default: false + fogType: + type: number + dockerPruningFrequency: + type: number + availableDiskThreshold: + type: number + logLevel: type: string - isActivated: + default: info + isSystem: type: boolean - microservices: - type: array - items: - $ref: "#/components/schemas/GetMicroservicesResponse" - routes: + routerMode: + type: string + default: edge + enum: + - none + - edge + - interior + messagingPort: + type: number + interRouterPort: + type: number + edgeRouterPort: + type: number + natsMode: + type: string + enum: + - none + - leaf + - server + natsServerPort: + type: number + natsLeafPort: + type: number + natsClusterPort: + type: number + natsMqttPort: + type: number + natsHttpPort: + type: number + jsStorageSize: + type: string + description: JetStream max file store (e.g. 10g). Units m, mb, g, gb, t, tb. + jsMemoryStoreSize: + type: string + description: JetStream max memory store (e.g. 1g). Units m, mb, g, gb, t, tb. + upstreamNatsServers: type: array items: - properties: - name: - type: string - from: - type: string - to: - type: string - ApplicationListResponse: - type: object - properties: - applications: + type: string + host: + type: string + tags: type: array items: - $ref: "#/components/schemas/ApplicationGetResponse" - ApplicationTemplateCreateRequest: - type: object - properties: - name: - type: string - description: - type: string - variables: + type: string + upstreamRouters: type: array items: - type: object - properties: - key: - type: string - description: - type: string - defaultValue: - type: string - application: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - name: - type: string - config: - type: string - annotations: - type: string - catalogItemId: - type: integer - registryId: - type: integer - images: - type: array - items: - properties: - containerImage: - type: string - fogTypeId: - type: string - iofogUuid: - type: string - agentName: - type: string - hostNetworkMode: - type: boolean - isPrivileged: - type: boolean - logSize: - type: number - rebuild: - type: boolean - volumeMappings: - type: array - items: - $ref: "#/components/schemas/VolumeMapping" - envs: - type: array - items: - type: object - properties: - key: - type: string - value: - type: string - runAsUser: - type: number - platform: - type: string - runtime: - type: string - cdiDevices: - type: array - items: - type: string - capAdd: - type: array - items: - type: string - capDrop: - type: array - items: - type: string - cmd: - type: array - items: - type: string - ports: - type: array - items: - $ref: "#/components/schemas/PortMappingsRequest" - pubTags: - type: array - items: - type: string - subTags: - type: array - items: - type: string - routes: - type: array - items: - type: object - properties: - from: - type: string - to: - type: string - name: - type: string - ApplicationTemplateCreateResponse: - type: object - properties: - id: - type: number - name: - type: string - ApplicationTemplatePatchRequest: - type: object - properties: - description: - type: number - name: + type: string + networkRouter: type: string - ApplicationTemplateGetResponse: + NewIOFogNodeResponse: type: object properties: id: - type: number - name: - type: string - description: type: string - application: - type: object - properties: - microservices: - type: array - items: - $ref: "#/components/schemas/GetMicroservicesResponse" - routes: - type: array - items: - properties: - name: - type: string - from: - type: string - to: - type: string - ApplicationTemplateListResponse: - type: object - properties: - applicationTemplates: - type: array - items: - $ref: "#/components/schemas/ApplicationTemplateGetResponse" - ServiceStatusResponse: + ProvisioningKeyResponse: type: object properties: - status: + key: type: string - example: ok - timestamp: + expirationTime: type: number - IOFogTypesResponse: + AgentProvisioningRequest: type: object + required: + - type + - key properties: - fogTypes: - type: array - items: - $ref: "#/components/schemas/IOFogType" - IOFogType: + type: + type: number + enum: + - 1 + - 2 + description: | + Architecture + * '1': x86 + * '2': arm + key: + type: string + description: provisioning key + AgentProvisioningResponse: type: object properties: id: - type: number - name: - type: string - image: type: string - description: + description: ioFog Node Id + token: type: string - IOFogNodesListFilters: - type: array - items: - type: object - properties: - key: - type: string - value: - type: string - condition: - type: string - IOFogNodesListResponse: + description: Agent token + AgentDeprovisioningRequest: type: object properties: - fogs: + microserviceUuids: type: array items: - $ref: "#/components/schemas/IOFogNodeInfoResponse" - IOFogNodeInfoResponse: + type: string + IOFogNodeConfigChanges: type: object properties: - lastActive: + config: + type: boolean + version: + type: boolean + reboot: + type: boolean + deleteNode: + type: boolean + microservicesList: + type: boolean + microservicesConfig: + type: boolean + registries: + type: boolean + tunnel: + type: boolean + diagnostics: + type: boolean + isImageSnapshot: + type: boolean + prune: + type: boolean + routerChanged: + type: boolean + IOFogNodeConfig: + type: object + properties: + networkInterface: + type: string + dockerUrl: + type: string + containerEngine: + type: string + deploymentType: + type: string + diskLimit: type: number - daemonOperatingDuration: + diskDirectory: + type: string + memoryLimit: type: number - daemonLastStart: + cpuLimit: type: number - repositoryCount: + logLimit: type: number - systemTime: + logDirectory: + type: string + logFileCount: type: number - lastStatusTime: + statusFrequency: type: number - processedMessages: + changeFrequency: type: number - lastCommandTime: + deviceScanFrequency: type: number - logFileCount: + watchdogEnabled: + type: boolean + latitude: type: number - uuid: + longitude: + type: number + logLevel: type: string - name: + availableDiskThreshold: + type: number + dockerPruningFrequency: + type: number + routerHost: type: string - location: + routerPort: + type: number + IOFogNodeConfigRequest: + type: object + properties: + networkInterface: type: string - gpsMode: + dockerUrl: + type: string + containerEngine: + type: string + deploymentType: + type: string + diskLimit: + type: number + diskDirectory: + type: string + memoryLimit: + type: number + cpuLimit: + type: number + logLimit: + type: number + logDirectory: type: string + logFileCount: + type: number + statusFrequency: + type: number + changeFrequency: + type: number + deviceScanFrequency: + type: number + watchdogEnabled: + type: boolean latitude: type: number longitude: type: number - description: + gpsMode: + type: string + logLevel: type: string + availableDiskThreshold: + type: number + dockerPruningFrequency: + type: number + IOFogNodeGpsRequest: + type: object + properties: + latitude: + type: number + longitude: + type: number + AgentStatus: + type: object + properties: daemonStatus: type: string + daemonOperatingDuration: + type: number + daemonLastStart: + type: number memoryUsage: type: number diskUsage: @@ -6629,524 +7532,497 @@ components: type: boolean cpuViolation: type: boolean + systemAvailableDisk: + type: integer + systemAvailableMemory: + type: integer systemTotalCpu: type: number - catalogItemStatus: + microserviceStatus: type: string + repositoryCount: + type: number repositoryStatus: type: string + systemTime: + type: number + lastStatusTime: + type: number ipAddress: type: string - ipAddressExternal: - type: string - catalogItemMessageCounts: + processedMessages: type: number + microserviceMessageCounts: + type: string messageSpeed: type: number - networkInterface: + lastCommandTime: + type: number + tunnelStatus: type: string - dockerUrl: + version: type: string - containerEngine: + isReadyToUpgrade: + type: boolean + isReadyToRollback: + type: boolean + IOFogNodeTunnelConfigResponse: + type: object + properties: + username: + type: string + password: + type: string + host: + type: string + remotePort: + type: number + localPort: + type: number + rsaKey: + type: string + closed: + type: boolean + IOFogNodeStraceResponse: + type: object + properties: + straceValues: + type: array + items: + $ref: "#/components/schemas/MicroserviceStrace" + MicroserviceStrace: + type: object + properties: + microserviceUuid: + type: string + straceRun: + type: boolean + IOFogNodeStraceBuffer: + type: object + properties: + straceData: + type: array + items: + $ref: "#/components/schemas/MicroserviceStraceBuffer" + MicroserviceStraceBuffer: + type: object + properties: + microserviceUuid: + type: string + buffer: + type: string + MicroserviceStraceFTPBody: + type: object + properties: + ftpHost: + type: string + ftpPort: + type: number + ftpUser: + type: string + ftpPass: + type: string + ftpDestDir: + type: string + AgentMicroservicesListResponse: + type: object + properties: + microservices: + type: array + items: + $ref: "#/components/schemas/AgentMicroservicesInfoResponse" + AgentMicroservicesInfoResponse: + type: object + properties: + uuid: type: string - deploymentType: + imageId: type: string - diskLimit: - type: number - diskDirectory: + config: type: string - memoryLimit: - type: number - cpuLimit: - type: number - logLimit: - type: number - logDirectory: + annotations: type: string - bluetoothEnabled: - type: boolean - abstractedHardwareEnabled: + rebuild: type: boolean - version: - type: string - isReadyToUpgrade: + hostNetworkMode: type: boolean - isReadyToRollback: + isPrivileged: type: boolean - statusFrequency: - type: number - changeFrequency: + logSize: type: number - deviceScanFrequency: + registryId: type: number - tunnel: + portMappings: + type: array + items: + $ref: "#/components/schemas/PortMappingAgentRequest" + volumeMappings: + type: array + items: + $ref: "#/components/schemas/VolumeMapping" + imageSnapshot: type: string - watchdogEnabled: + delete: type: boolean - dockerPruningFrequency: - type: number - availableDiskThreshold: - type: number - logLevel: - type: string - isSystem: + deleteWithCleanUp: type: boolean - routerId: - type: number - createAt: - type: number - updatedAt: - type: number - fogTypeId: - type: number - routerMode: + env: + type: array + items: + $ref: "#/components/schemas/AgentEnvRequest" + runAsUser: type: string - enum: - - none - - edge - - interior - messagingPort: - type: number - upstreamRouters: + platform: + type: string + runtime: + type: string + cdiDevices: type: array items: type: string - UpdateIOFogNodeRequestBody: + capAdd: + type: array + items: + type: string + capDrop: + type: array + items: + type: string + cmd: + type: array + items: + type: string + idConsumer: + type: boolean + AgentEnvRequest: type: object properties: - name: - type: string - location: + key: type: string - latitude: - type: number - longitude: - type: number - description: + value: type: string - dockerUrl: + ReceiverMicroservices: + type: array + items: + type: string + VolumeMapping: + type: object + properties: + hostDestination: type: string - default: unix:///var/run/docker.sock - containerEngine: + example: /var/dest + containerDestination: type: string - default: docker - deploymentType: + example: /var/dest + accessMode: type: string - default: native - diskLimit: + example: rw + VolumeMappingResponse: + type: object + properties: + volumeMappings: + type: array + items: + $ref: "#/components/schemas/VolumeMappingRequest" + VolumeMappingRequest: + type: object + properties: + id: type: number - default: 50 - diskDirectory: + hostDestination: type: string - default: /var/lib/iofog - memoryLimit: - type: number - default: 4096 - format: MB - cpuLimit: - type: number - default: 80 - format: percent - logLimit: - type: number - default: 10 - format: GB - logDirectory: + example: /var/dest + containerDestination: type: string - default: /var/log/iofog - logFileCount: - type: number - default: 10 - statusFrequency: - type: number - default: 10 - format: seconds - changeFrequency: - type: number - default: 20 - format: seconds - deviceScanFrequency: + example: /var/dest + accessMode: + type: string + example: rw + type: + type: string + example: bind + PortMappingsResponse: + type: object + properties: + internal: type: number - default: 20 - format: seconds - bluetoothEnabled: - type: boolean - default: false - watchdogEnabled: - type: boolean - default: true - abstractedHardwareEnabled: - type: boolean - default: false - fogType: + external: type: number - dockerPruningFrequency: + protocol: + type: string + enum: + - tcp + - udp + required: + - internal + - external + - protocol + PortMappingsRequest: + type: object + properties: + internal: type: number - availableDiskThreshold: + external: type: number - logLevel: - type: string - default: info - isSystem: - type: boolean - routerMode: + protocol: type: string - default: edge enum: - - none - - edge - - interior - messagingPort: - type: number - interRouterPort: + - tcp + - udp + required: + - internal + - external + PortMappingsPublicResponse: + type: object + properties: + internal: type: number - edgeRouterPort: + external: type: number - host: - type: string - tags: - type: array - items: - type: string - upstreamRouters: - type: array - items: - type: string - networkRouter: + protocol: type: string - NewIOFogNodeResponse: + enum: + - tcp + - udp + required: + - internal + - external + - protocol + PortMappingsListResponse: type: object properties: - id: - type: string - ProvisioningKeyResponse: + ports: + type: array + items: + $ref: "#/components/schemas/PortMappingsItemResponse" + PortMappingsItemResponse: type: object properties: - key: - type: string - expirationTime: + internal: type: number - AgentProvisioningRequest: - type: object - required: - - type - - key - properties: - type: + external: type: number - enum: - - 1 - - 2 - description: | - Architecture - * '1': x86 - * '2': arm - key: + protocol: type: string - description: provisioning key - AgentProvisioningResponse: + enum: + - tcp + - udp + required: + - internal + - external + - protocol + PortMappingAgentRequest: type: object properties: - id: + portInternal: type: string - description: ioFog Node Id - token: + example: 80 + portExternal: type: string - description: Agent token - AgentDeprovisioningRequest: + example: 80 + microservicesConfig: + type: string + RegistriesListResponse: type: object properties: - microserviceUuids: + registries: type: array items: - type: string - IOFogNodeConfigChanges: + $ref: "#/components/schemas/RegistryResponse" + RegistryResponse: type: object properties: - config: - type: boolean - version: - type: boolean - reboot: - type: boolean - deleteNode: - type: boolean - microservicesList: - type: boolean - microservicesConfig: - type: boolean - routing: - type: boolean - registries: - type: boolean - tunnel: - type: boolean - diagnostics: - type: boolean - isImageSnapshot: - type: boolean - prune: - type: boolean - routerChanged: + id: + type: number + url: + type: string + isPublic: type: boolean - IOFogNodeConfig: - type: object - properties: - networkInterface: + username: type: string - dockerUrl: + password: type: string - containerEngine: + userEmail: type: string - deploymentType: + RegistryBody: + type: object + properties: + url: type: string - diskLimit: - type: number - diskDirectory: + isPublic: + type: boolean + username: type: string - memoryLimit: - type: number - cpuLimit: - type: number - logLimit: - type: number - logDirectory: + password: type: string - logFileCount: - type: number - statusFrequency: - type: number - changeFrequency: - type: number - deviceScanFrequency: - type: number - watchdogEnabled: - type: boolean - latitude: - type: number - longitude: - type: number - logLevel: + email: type: string - availableDiskThreshold: - type: number - dockerPruningFrequency: - type: number - routerHost: + ActionBody: + type: object + properties: + action: type: string - routerPort: - type: number - IOFogNodeConfigRequest: + enum: + - open + - close + MicroservicesCatalogResponse: type: object properties: - networkInterface: + catalogItems: + type: array + items: + $ref: "#/components/schemas/CatalogItemInfoResponse" + CatalogItemInfoResponse: + type: object + properties: + id: type: string - dockerUrl: + name: type: string - containerEngine: + description: type: string - deploymentType: + category: type: string - diskLimit: - type: number - diskDirectory: + publisher: type: string - memoryLimit: - type: number - cpuLimit: + diskRequired: type: number - logLimit: + ramRequired: type: number - logDirectory: + picture: type: string - logFileCount: - type: number - statusFrequency: - type: number - changeFrequency: - type: number - deviceScanFrequency: - type: number - watchdogEnabled: + isPublic: type: boolean - latitude: - type: number - longitude: + registryId: type: number - gpsMode: - type: string - logLevel: + inputType: + $ref: "#/components/schemas/InfoTypeResponse" + outputType: + $ref: "#/components/schemas/InfoTypeResponse" + configExample: type: string - availableDiskThreshold: - type: number - dockerPruningFrequency: - type: number - IOFogNodeGpsRequest: - type: object - properties: - latitude: - type: number - longitude: - type: number - AgentStatus: + images: + $ref: "#/components/schemas/MicroserviceContainerImages" + InfoTypeResponse: type: object properties: - daemonStatus: - type: string - daemonOperatingDuration: - type: number - daemonLastStart: - type: number - memoryUsage: - type: number - diskUsage: - type: number - cpuUsage: - type: number - memoryViolation: - type: boolean - diskViolation: - type: boolean - cpuViolation: - type: boolean - systemAvailableDisk: - type: integer - systemAvailableMemory: - type: integer - systemTotalCpu: - type: number - microserviceStatus: - type: string - repositoryCount: - type: number - repositoryStatus: + infoType: type: string - systemTime: - type: number - lastStatusTime: - type: number - ipAddress: + infoFormat: type: string - processedMessages: - type: number - microserviceMessageCounts: + MicroserviceContainerImages: + type: array + items: + $ref: "#/components/schemas/MicroserviceContainerImage" + MicroserviceContainerImage: + type: object + properties: + containerImage: type: string - messageSpeed: - type: number - lastCommandTime: + fogTypeId: type: number - tunnelStatus: - type: string - version: - type: string - isReadyToUpgrade: - type: boolean - isReadyToRollback: - type: boolean - IOFogNodeTunnelConfigResponse: + enum: + - 1 + - 2 + CreateUpdateCatalogItemRequestBody: type: object properties: - username: + name: type: string - password: + description: type: string - host: + category: type: string - remotePort: + images: + $ref: "#/components/schemas/MicroserviceContainerImages" + publisher: + type: string + diskRequired: type: number - localPort: + ramRequired: type: number - rsaKey: + picture: type: string - closed: + isPublic: type: boolean - IOFogNodeStraceResponse: - type: object - properties: - straceValues: - type: array - items: - $ref: "#/components/schemas/MicroserviceStrace" - MicroserviceStrace: - type: object - properties: - microserviceUuid: + registryId: + type: number + inputType: + $ref: "#/components/schemas/InfoTypeResponse" + outputType: + $ref: "#/components/schemas/InfoTypeResponse" + configExample: type: string - straceRun: - type: boolean - IOFogNodeStraceBuffer: + GetFlowsResponse: type: object properties: - straceData: + flows: type: array items: - $ref: "#/components/schemas/MicroserviceStraceBuffer" - MicroserviceStraceBuffer: + $ref: "#/components/schemas/FlowInfoResponse" + FlowInfoResponse: type: object properties: - microserviceUuid: + id: type: string - buffer: + name: type: string - MicroserviceStraceFTPBody: + description: + type: string + isActivated: + type: boolean + NewFlowRequest: type: object properties: - ftpHost: - type: string - ftpPort: - type: number - ftpUser: - type: string - ftpPass: + name: type: string - ftpDestDir: + description: type: string - AgentMicroservicesListResponse: + isActivated: + type: boolean + GetMicroservicesResponse: type: object properties: microservices: type: array items: - $ref: "#/components/schemas/AgentMicroservicesInfoResponse" - AgentMicroservicesInfoResponse: + $ref: "#/components/schemas/MicroserviceInfoResponse" + MicroserviceInfoResponse: type: object properties: uuid: type: string - imageId: + name: type: string config: type: string annotations: type: string - rebuild: - type: boolean hostNetworkMode: type: boolean isPrivileged: type: boolean - logSize: - type: number - registryId: + logLimit: type: number - portMappings: - type: array - items: - $ref: "#/components/schemas/PortMappingAgentRequest" - volumeMappings: + images: type: array items: - $ref: "#/components/schemas/VolumeMapping" - imageSnapshot: + properties: + containerImage: + type: string + fogTypeId: + type: string + iofogUuid: type: string - delete: - type: boolean - deleteWithCleanUp: - type: boolean - env: + envs: type: array items: - $ref: "#/components/schemas/AgentEnvRequest" + type: object + properties: + key: + type: string + value: + type: string runAsUser: type: string platform: @@ -7169,528 +8045,563 @@ components: type: array items: type: string - idConsumer: - type: boolean - AgentEnvRequest: - type: object - properties: - key: - type: string - value: - type: string - ReceiverMicroservices: - type: array - items: - type: string - VolumeMapping: - type: object - properties: - hostDestination: - type: string - example: /var/dest - containerDestination: - type: string - example: /var/dest - accessMode: - type: string - example: rw - VolumeMappingResponse: - type: object - properties: volumeMappings: type: array items: $ref: "#/components/schemas/VolumeMappingRequest" - VolumeMappingRequest: - type: object - properties: - id: - type: number - hostDestination: - type: string - example: /var/dest - containerDestination: - type: string - example: /var/dest - accessMode: - type: string - example: rw - type: - type: string - example: bind - PortMappingsResponse: + ports: + type: array + items: + $ref: "#/components/schemas/PortMappingsResponse" + natsAccess: + type: boolean + natsConfig: + $ref: "#/components/schemas/NatsConfigObject" + status: + type: object + properties: + status: + type: string + operatingDuration: + type: number + startTime: + type: number + cpuUsage: + type: number + memoryUsage: + type: number + containerId: + type: string + NewMicroserviceRequest: type: object properties: - internal: - type: number - external: - type: number - protocol: + name: type: string - enum: - - tcp - - udp - required: - - internal - - external - - protocol - PortMappingsRequest: - type: object - properties: - internal: - type: number - external: - type: number - protocol: + config: type: string - enum: - - tcp - - udp - required: - - internal - - external - PortMappingsPublicResponse: - type: object - properties: - internal: - type: number - external: - type: number - protocol: + annotations: type: string - enum: - - tcp - - udp - required: - - internal - - external - - protocol - PortMappingsListResponse: - type: object - properties: + catalogItemId: + type: integer + images: + type: array + items: + properties: + containerImage: + type: string + fogTypeId: + type: string + flowId: + type: integer + deprecated: true + application: + oneOf: + - type: string + - type: integer + iofogUuid: + type: string + agentName: + type: string + hostNetworkMode: + type: boolean + isPrivileged: + type: boolean + logSize: + type: number + volumeMappings: + type: array + items: + $ref: "#/components/schemas/VolumeMapping" ports: type: array items: - $ref: "#/components/schemas/PortMappingsItemResponse" - PortMappingsItemResponse: - type: object - properties: - internal: - type: number - external: - type: number - protocol: - type: string - enum: - - tcp - - udp - required: - - internal - - external - - protocol - PortMappingAgentRequest: - type: object - properties: - portInternal: + $ref: "#/components/schemas/PortMappingsRequest" + runAsUser: type: string - example: 80 - portExternal: + platform: type: string - example: 80 - microservicesConfig: - type: string - RegistriesListResponse: - type: object - properties: - registries: + runtime: + type: string + cdiDevices: type: array items: - $ref: "#/components/schemas/RegistryResponse" - RegistryResponse: + type: string + capAdd: + type: array + items: + type: string + capDrop: + type: array + items: + type: string + cmd: + type: array + items: + type: string + natsConfig: + $ref: "#/components/schemas/NatsConfigObject" + serviceAccount: + type: object + properties: + roleRef: + $ref: "#/components/schemas/RoleRef" + additionalProperties: false + UpdateMicroserviceRequest: type: object properties: - id: - type: number - url: + name: type: string - isPublic: - type: boolean - username: + config: type: string - password: + annotations: type: string - userEmail: + rebuild: + type: boolean + iofogUuid: type: string - RegistryBody: - type: object - properties: - url: + agentName: type: string - isPublic: + hostNetworkMode: type: boolean - username: - type: string - password: + isPrivileged: + type: boolean + logLimit: + type: number + volumeMappings: + type: array + items: + $ref: "#/components/schemas/VolumeMapping" + images: + type: array + items: + properties: + containerImage: + type: string + fogTypeId: + type: string + runAsUser: type: string - email: + platform: type: string - ActionBody: + runtime: + type: string + cdiDevices: + type: array + items: + type: string + capAdd: + type: array + items: + type: string + capDrop: + type: array + items: + type: string + cmd: + type: array + items: + type: string + natsConfig: + $ref: "#/components/schemas/NatsConfigObject" + serviceAccount: + type: object + properties: + roleRef: + $ref: "#/components/schemas/RoleRef" + additionalProperties: false + NatsConfigObject: type: object properties: - action: + natsAccess: + type: boolean + natsRule: type: string - enum: - - open - - close - MicroservicesCatalogResponse: + additionalProperties: false + NatsHubRequest: type: object + required: + - host properties: - catalogItems: - type: array - items: - $ref: "#/components/schemas/CatalogItemInfoResponse" - CatalogItemInfoResponse: + host: + type: string + serverPort: + type: integer + clusterPort: + type: integer + leafPort: + type: integer + mqttPort: + type: integer + httpPort: + type: integer + jsStorageSize: + type: string + description: JetStream max file store (e.g. 10g, 1t). Units m, mb, g, gb, t, tb. + jsMemoryStoreSize: + type: string + description: JetStream max memory store (e.g. 1g). Units m, mb, g, gb, t, tb. + NatsHubResponse: + $ref: "#/components/schemas/NatsHubRequest" + NatsOperatorResponse: type: object properties: - id: - type: string name: type: string - description: + publicKey: type: string - category: + jwt: type: string - publisher: + NatsBootstrapResponse: + type: object + properties: + operatorJwt: type: string - diskRequired: - type: number - ramRequired: - type: number - picture: + operatorPublicKey: type: string - isPublic: - type: boolean - registryId: - type: number - inputType: - $ref: "#/components/schemas/InfoTypeResponse" - outputType: - $ref: "#/components/schemas/InfoTypeResponse" - configExample: + operatorSeed: type: string - images: - $ref: "#/components/schemas/MicroserviceContainerImages" - InfoTypeResponse: - type: object - properties: - infoType: + systemAccountJwt: type: string - infoFormat: + systemAccountPublicKey: type: string - MicroserviceContainerImages: - type: array - items: - $ref: "#/components/schemas/MicroserviceContainerImage" - MicroserviceContainerImage: - type: object - properties: - containerImage: + sysUserCredsBase64: type: string - fogTypeId: - type: number - enum: - - 1 - - 2 - CreateUpdateCatalogItemRequestBody: + NatsAccountResponse: type: object properties: + id: + type: integer name: type: string - description: - type: string - category: - type: string - images: - $ref: "#/components/schemas/MicroserviceContainerImages" - publisher: + publicKey: type: string - diskRequired: - type: number - ramRequired: - type: number - picture: + jwt: type: string - isPublic: + isSystem: type: boolean - registryId: - type: number - inputType: - $ref: "#/components/schemas/InfoTypeResponse" - outputType: - $ref: "#/components/schemas/InfoTypeResponse" - configExample: - type: string - GetFlowsResponse: + applicationId: + type: integer + NatsAccountsListResponse: type: object properties: - flows: + accounts: type: array items: - $ref: "#/components/schemas/FlowInfoResponse" - FlowInfoResponse: + $ref: "#/components/schemas/NatsAccountResponse" + NatsUserCreateRequest: type: object + required: + - name properties: - id: + name: type: string + expiresIn: + type: string + pattern: "^[0-9]+[hdm]$" + example: "7d" + natsRule: + type: string + NatsUserResponse: + type: object + properties: + id: + type: integer name: type: string - description: + publicKey: type: string - isActivated: + jwt: + type: string + isBearer: type: boolean - NewFlowRequest: + NatsUserWithContextResponse: type: object + description: NATS user with account and application context (for list-all response) properties: + id: + type: integer name: type: string - description: + publicKey: type: string - isActivated: + jwt: + type: string + isBearer: type: boolean - GetMicroservicesResponse: + accountId: + type: integer + accountName: + type: string + applicationId: + type: integer + applicationName: + type: string + microserviceUuid: + type: string + format: uuid + NatsUsersListResponse: type: object properties: - microservices: + users: type: array items: - $ref: "#/components/schemas/MicroserviceInfoResponse" - MicroserviceInfoResponse: + $ref: "#/components/schemas/NatsUserResponse" + NatsAllUsersListResponse: type: object properties: - uuid: + users: + type: array + items: + $ref: "#/components/schemas/NatsUserWithContextResponse" + NatsAccountEnsureRequest: + type: object + properties: + natsRule: + type: string + description: Account rule name (defaults to default-account if omitted) + NatsCredsResponse: + type: object + properties: + credsBase64: type: string + description: NATS credentials file content encoded as base64 + NatsAccountRulePayload: + type: object + description: NATS account rule (authorization policy for an account) + properties: name: type: string - config: + minLength: 1 + maxLength: 255 + description: type: string - annotations: + infoUrl: type: string - hostNetworkMode: + maxConnections: + type: integer + minimum: -1 + maxLeafNodeConnections: + type: integer + minimum: -1 + maxData: + type: integer + minimum: -1 + maxExports: + type: integer + minimum: -1 + maxImports: + type: integer + minimum: -1 + maxMsgPayload: + type: integer + minimum: -1 + maxSubscriptions: + type: integer + minimum: -1 + exportsAllowWildcards: type: boolean - isPrivileged: + disallowBearer: type: boolean - logLimit: - type: number - images: + responsePermissions: + type: object + properties: + maxMsgs: + type: integer + minimum: 0 + expires: + type: integer + minimum: 0 + respMax: + type: integer + minimum: 0 + respTtl: + type: integer + minimum: 0 + imports: type: array + description: Stream/service imports (NATS account policy) items: + type: object properties: - containerImage: + name: type: string - fogTypeId: + subject: type: string - iofogUuid: - type: string - envs: + type: + type: string + enum: [stream, service] + account: + type: string + token: + type: string + to: + type: string + local_subject: + type: string + share: + type: boolean + exports: type: array + description: Stream/service exports (NATS account policy) items: type: object properties: - key: + name: type: string - value: + subject: type: string - runAsUser: - type: string - platform: - type: string - runtime: - type: string - cdiDevices: + type: + type: string + enum: [stream, service] + description: + type: string + info_url: + type: string + token_req: + type: boolean + response_type: + type: string + enum: [Singleton, Stream, Chunked] + account_token_position: + type: integer + memStorage: + type: integer + minimum: -1 + description: JetStream memory storage limit in bytes + diskStorage: + type: integer + minimum: -1 + description: JetStream disk storage limit in bytes + streams: + type: integer + minimum: -1 + description: JetStream max streams + consumer: + type: integer + minimum: -1 + description: JetStream max consumers + maxAckPending: + type: integer + minimum: -1 + memMaxStreamBytes: + type: integer + minimum: -1 + diskMaxStreamBytes: + type: integer + minimum: -1 + maxBytesRequired: + type: boolean + tieredLimits: + type: object + additionalProperties: true + pubAllow: type: array items: type: string - capAdd: + pubDeny: type: array items: type: string - capDrop: + subAllow: type: array items: type: string - cmd: + subDeny: type: array items: type: string - volumeMappings: - type: array - items: - $ref: "#/components/schemas/VolumeMappingRequest" - ports: + NatsAccountRuleListResponse: + type: object + properties: + rules: type: array items: - $ref: "#/components/schemas/PortMappingsResponse" - status: - type: object - properties: - status: - type: string - operatingDuration: - type: number - startTime: - type: number - cpuUsage: - type: number - memoryUsage: - type: number - containerId: - type: string - NewMicroserviceRequest: + $ref: "#/components/schemas/NatsAccountRulePayload" + NatsUserRulePayload: type: object + description: NATS user rule (authorization policy for a user) properties: name: type: string - config: - type: string - annotations: + minLength: 1 + maxLength: 255 + description: type: string - catalogItemId: + maxSubscriptions: type: integer - images: - type: array - items: - properties: - containerImage: - type: string - fogTypeId: - type: string - flowId: + minimum: -1 + maxPayload: type: integer - iofogUuid: - type: string - agentName: - type: string - hostNetworkMode: + minimum: -1 + maxData: + type: integer + minimum: -1 + bearerToken: type: boolean - isPrivileged: + proxyRequired: type: boolean - logSize: - type: number - volumeMappings: - type: array - items: - $ref: "#/components/schemas/VolumeMapping" - ports: - type: array - items: - $ref: "#/components/schemas/PortMappingsRequest" - runAsUser: - type: string - platform: - type: string - runtime: - type: string - cdiDevices: - type: array - items: - type: string - capAdd: - type: array - items: - type: string - capDrop: - type: array - items: - type: string - cmd: - type: array - items: - type: string - pubTags: + allowedConnectionTypes: type: array items: type: string - subTags: + enum: + - STANDARD + - WEBSOCKET + - LEAFNODE + - LEAFNODE_WS + - MQTT + - MQTT_WS + - IN_PROCESS + src: type: array items: type: string - serviceAccount: - type: object - properties: - roleRef: - $ref: "#/components/schemas/RoleRef" - additionalProperties: false - UpdateMicroserviceRequest: - type: object - required: - - name - properties: - name: - type: string - config: - type: string - annotations: - type: string - rebuild: - type: boolean - iofogUuid: - type: string - agentName: - type: string - hostNetworkMode: - type: boolean - isPrivileged: - type: boolean - logLimit: - type: number - volumeMappings: - type: array - items: - $ref: "#/components/schemas/VolumeMapping" - images: + description: Allowed client connection source IP/CIDR + times: type: array items: + type: object properties: - containerImage: + start: type: string - fogTypeId: + end: type: string - runAsUser: + description: Allowed time windows for connections + timesLocation: type: string - platform: - type: string - runtime: - type: string - cdiDevices: + respMax: + type: integer + minimum: 0 + respTtl: + type: integer + minimum: 0 + pubAllow: type: array items: type: string - capAdd: + pubDeny: type: array items: type: string - capDrop: + subAllow: type: array items: type: string - cmd: + subDeny: type: array items: type: string - pubTags: + tags: type: array items: type: string - subTags: + NatsUserRuleListResponse: + type: object + properties: + rules: type: array items: - type: string - serviceAccount: - type: object - properties: - roleRef: - $ref: "#/components/schemas/RoleRef" - additionalProperties: false + $ref: "#/components/schemas/NatsUserRulePayload" IOFogNodeTunnelStatusInfoResponse: type: object properties: @@ -7819,46 +8730,6 @@ components: type: string data: type: object - RouteListResponse: - type: object - properties: - routes: - type: array - items: - $ref: "#/components/schemas/RouteResponse" - RouteResponse: - type: object - properties: - id: - type: number - name: - type: string - sourceMicroserviceUuid: - type: string - destMicroserviceUuid: - type: string - NewRouteRequest: - type: object - properties: - name: - type: string - sourceMicroserviceUuid: - type: string - destMicroserviceUuid: - type: string - required: - - name - - sourceMicroserviceUuid - - destMicroserviceUuid - UpdateRouteRequest: - type: object - properties: - name: - type: string - sourceMicroserviceUuid: - type: string - destMicroserviceUuid: - type: string SecretCreate: type: object required: @@ -8513,6 +9384,9 @@ components: type: integer name: type: string + applicationName: + type: string + description: Application name this service account belongs to roleRef: $ref: "#/components/schemas/RoleRef" required: @@ -8523,10 +9397,14 @@ components: properties: name: type: string + applicationName: + type: string + description: Application name this service account belongs to roleRef: $ref: "#/components/schemas/RoleRef" required: - name + - applicationName - roleRef ServiceAccountResponse: type: object @@ -8535,6 +9413,9 @@ components: type: integer name: type: string + applicationName: + type: string + description: Application name this service account belongs to roleRef: $ref: "#/components/schemas/RoleRef" required: diff --git a/package-lock.json b/package-lock.json index 582fc5359..725fb39ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,29 +1,31 @@ { "name": "@datasance/iofogcontroller", - "version": "3.6.0", + "version": "3.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@datasance/iofogcontroller", - "version": "3.6.0", + "version": "3.7.0", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@aws-sdk/client-secrets-manager": "^3.981.0", + "@aws-sdk/client-secrets-manager": "^3.999.0", "@azure/identity": "^4.13.0", "@azure/keyvault-secrets": "^4.10.0", - "@datasance/ecn-viewer": "1.3.0", + "@datasance/ecn-viewer": "1.4.2", "@google-cloud/secret-manager": "^6.1.1", - "@kubernetes/client-node": "^0.22.3", + "@kubernetes/client-node": "^1.4.0", "@msgpack/msgpack": "^3.1.2", + "@nats-io/jwt": "^0.0.10-5", + "@nats-io/nkeys": "^2.0.3", "@opentelemetry/api": "^1.9.0", "@opentelemetry/exporter-trace-otlp-http": "^0.200.0", "@opentelemetry/instrumentation-express": "^0.48.1", "@opentelemetry/instrumentation-http": "^0.200.0", "@opentelemetry/resources": "^1.8.0", "@opentelemetry/sdk-node": "^0.200.0", - "axios": "1.12.2", + "axios": "1.13.5", "bignumber.js": "^9.3.0", "body-parser": "^1.20.4", "command-line-args": "5.2.1", @@ -54,7 +56,7 @@ "pino": "9.13.1", "pino-std-serializers": "7.0.0", "portscanner": "2.2.0", - "qs": "6.14.1", + "qs": "6.14.2", "rhea": "^3.0.4", "sequelize": "6.37.7", "sqlite3": "^5.1.7", @@ -85,12 +87,16 @@ "sinon-chai": "3.7.0", "snyk": "^1.1291.0", "standard": "12.0.1" + }, + "engines": { + "node": "^24.0.0" } }, "node_modules/@aws-crypto/sha256-browser": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", @@ -105,6 +111,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -116,6 +123,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" @@ -128,6 +136,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" @@ -140,6 +149,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", @@ -153,6 +163,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" } @@ -161,6 +172,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", @@ -171,6 +183,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -182,6 +195,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" @@ -194,6 +208,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" @@ -203,111 +218,49 @@ } }, "node_modules/@aws-sdk/client-secrets-manager": { - "version": "3.981.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.981.0.tgz", - "integrity": "sha512-NVSbeeU/IjVobvFrwR4vLaEn3L83SfqRZXjIyBlHtU6agtHVCOJCdhrkK0z7uFahxD9FqqiQTYMYhzIfgL7VjA==", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/credential-provider-node": "^3.972.4", - "@aws-sdk/middleware-host-header": "^3.972.3", - "@aws-sdk/middleware-logger": "^3.972.3", - "@aws-sdk/middleware-recursion-detection": "^3.972.3", - "@aws-sdk/middleware-user-agent": "^3.972.5", - "@aws-sdk/region-config-resolver": "^3.972.3", - "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.981.0", - "@aws-sdk/util-user-agent-browser": "^3.972.3", - "@aws-sdk/util-user-agent-node": "^3.972.3", - "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.22.0", - "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/hash-node": "^4.2.8", - "@smithy/invalid-dependency": "^4.2.8", - "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.12", - "@smithy/middleware-retry": "^4.4.29", - "@smithy/middleware-serde": "^4.2.9", - "@smithy/middleware-stack": "^4.2.8", - "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.28", - "@smithy/util-defaults-mode-node": "^4.2.31", - "@smithy/util-endpoints": "^3.2.8", - "@smithy/util-middleware": "^4.2.8", - "@smithy/util-retry": "^4.2.8", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.980.0.tgz", - "integrity": "sha512-AhNXQaJ46C1I+lQ+6Kj+L24il5K9lqqIanJd8lMszPmP7bLnmX0wTKK0dxywcvrLdij3zhWttjAKEBNgLtS8/A==", + "version": "3.999.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.999.0.tgz", + "integrity": "sha512-HOuEkNng/ZnkN2OQ0LxCl92hhIviQ/cKVvFj4S7NxLYG/Rc652qyysOtzTbg3QM+cG4rimuIzBG5uTlYFSti6A==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/middleware-host-header": "^3.972.3", - "@aws-sdk/middleware-logger": "^3.972.3", - "@aws-sdk/middleware-recursion-detection": "^3.972.3", - "@aws-sdk/middleware-user-agent": "^3.972.5", - "@aws-sdk/region-config-resolver": "^3.972.3", - "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.980.0", - "@aws-sdk/util-user-agent-browser": "^3.972.3", - "@aws-sdk/util-user-agent-node": "^3.972.3", - "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.22.0", - "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/hash-node": "^4.2.8", - "@smithy/invalid-dependency": "^4.2.8", - "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.12", - "@smithy/middleware-retry": "^4.4.29", - "@smithy/middleware-serde": "^4.2.9", - "@smithy/middleware-stack": "^4.2.8", - "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.28", - "@smithy/util-defaults-mode-node": "^4.2.31", - "@smithy/util-endpoints": "^3.2.8", - "@smithy/util-middleware": "^4.2.8", - "@smithy/util-retry": "^4.2.8", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/util-endpoints": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.980.0.tgz", - "integrity": "sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw==", - "dependencies": { - "@aws-sdk/types": "^3.973.1", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-endpoints": "^3.2.8", + "@aws-sdk/core": "^3.973.15", + "@aws-sdk/credential-provider-node": "^3.972.14", + "@aws-sdk/middleware-host-header": "^3.972.6", + "@aws-sdk/middleware-logger": "^3.972.6", + "@aws-sdk/middleware-recursion-detection": "^3.972.6", + "@aws-sdk/middleware-user-agent": "^3.972.15", + "@aws-sdk/region-config-resolver": "^3.972.6", + "@aws-sdk/types": "^3.973.4", + "@aws-sdk/util-endpoints": "^3.996.3", + "@aws-sdk/util-user-agent-browser": "^3.972.6", + "@aws-sdk/util-user-agent-node": "^3.973.0", + "@smithy/config-resolver": "^4.4.9", + "@smithy/core": "^3.23.6", + "@smithy/fetch-http-handler": "^5.3.11", + "@smithy/hash-node": "^4.2.10", + "@smithy/invalid-dependency": "^4.2.10", + "@smithy/middleware-content-length": "^4.2.10", + "@smithy/middleware-endpoint": "^4.4.20", + "@smithy/middleware-retry": "^4.4.37", + "@smithy/middleware-serde": "^4.2.11", + "@smithy/middleware-stack": "^4.2.10", + "@smithy/node-config-provider": "^4.3.10", + "@smithy/node-http-handler": "^4.4.12", + "@smithy/protocol-http": "^5.3.10", + "@smithy/smithy-client": "^4.12.0", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.10", + "@smithy/util-base64": "^4.3.1", + "@smithy/util-body-length-browser": "^4.2.1", + "@smithy/util-body-length-node": "^4.2.2", + "@smithy/util-defaults-mode-browser": "^4.3.36", + "@smithy/util-defaults-mode-node": "^4.2.39", + "@smithy/util-endpoints": "^3.3.1", + "@smithy/util-middleware": "^4.2.10", + "@smithy/util-retry": "^4.2.10", + "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" }, "engines": { @@ -315,22 +268,23 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.973.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.5.tgz", - "integrity": "sha512-IMM7xGfLGW6lMvubsA4j6BHU5FPgGAxoQ/NA63KqNLMwTS+PeMBcx8DPHL12Vg6yqOZnqok9Mu4H2BdQyq7gSA==", - "dependencies": { - "@aws-sdk/types": "^3.973.1", - "@aws-sdk/xml-builder": "^3.972.2", - "@smithy/core": "^3.22.0", - "@smithy/node-config-provider": "^4.3.8", - "@smithy/property-provider": "^4.2.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/signature-v4": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", - "@smithy/types": "^4.12.0", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-middleware": "^4.2.8", - "@smithy/util-utf8": "^4.2.0", + "version": "3.973.15", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.15.tgz", + "integrity": "sha512-AlC0oQ1/mdJ8vCIqu524j5RB7M8i8E24bbkZmya1CuiQxkY7SdIZAyw7NDNMGaNINQFq/8oGRMX0HeOfCVsl/A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.4", + "@aws-sdk/xml-builder": "^3.972.8", + "@smithy/core": "^3.23.6", + "@smithy/node-config-provider": "^4.3.10", + "@smithy/property-provider": "^4.2.10", + "@smithy/protocol-http": "^5.3.10", + "@smithy/signature-v4": "^5.3.10", + "@smithy/smithy-client": "^4.12.0", + "@smithy/types": "^4.13.0", + "@smithy/util-base64": "^4.3.1", + "@smithy/util-middleware": "^4.2.10", + "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" }, "engines": { @@ -338,14 +292,15 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.3.tgz", - "integrity": "sha512-OBYNY4xQPq7Rx+oOhtyuyO0AQvdJSpXRg7JuPNBJH4a1XXIzJQl4UHQTPKZKwfJXmYLpv4+OkcFen4LYmDPd3g==", - "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/types": "^3.973.1", - "@smithy/property-provider": "^4.2.8", - "@smithy/types": "^4.12.0", + "version": "3.972.13", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.13.tgz", + "integrity": "sha512-6ljXKIQ22WFKyIs1jbORIkGanySBHaPPTOI4OxACP5WXgbcR0nDYfqNJfXEGwCK7IzHdNbCSFsNKKs0qCexR8Q==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.15", + "@aws-sdk/types": "^3.973.4", + "@smithy/property-provider": "^4.2.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -353,19 +308,20 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.5.tgz", - "integrity": "sha512-GpvBgEmSZPvlDekd26Zi+XsI27Qz7y0utUx0g2fSTSiDzhnd1FSa1owuodxR0BcUKNL7U2cOVhhDxgZ4iSoPVg==", - "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/types": "^3.973.1", - "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/node-http-handler": "^4.4.8", - "@smithy/property-provider": "^4.2.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", - "@smithy/types": "^4.12.0", - "@smithy/util-stream": "^4.5.10", + "version": "3.972.15", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.15.tgz", + "integrity": "sha512-dJuSTreu/T8f24SHDNTjd7eQ4rabr0TzPh2UTCwYexQtzG3nTDKm1e5eIdhiroTMDkPEJeY+WPkA6F9wod/20A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.15", + "@aws-sdk/types": "^3.973.4", + "@smithy/fetch-http-handler": "^5.3.11", + "@smithy/node-http-handler": "^4.4.12", + "@smithy/property-provider": "^4.2.10", + "@smithy/protocol-http": "^5.3.10", + "@smithy/smithy-client": "^4.12.0", + "@smithy/types": "^4.13.0", + "@smithy/util-stream": "^4.5.15", "tslib": "^2.6.2" }, "engines": { @@ -373,23 +329,24 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.3.tgz", - "integrity": "sha512-rMQAIxstP7cLgYfsRGrGOlpyMl0l8JL2mcke3dsIPLWke05zKOFyR7yoJzWCsI/QiIxjRbxpvPiAeKEA6CoYkg==", - "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/credential-provider-env": "^3.972.3", - "@aws-sdk/credential-provider-http": "^3.972.5", - "@aws-sdk/credential-provider-login": "^3.972.3", - "@aws-sdk/credential-provider-process": "^3.972.3", - "@aws-sdk/credential-provider-sso": "^3.972.3", - "@aws-sdk/credential-provider-web-identity": "^3.972.3", - "@aws-sdk/nested-clients": "3.980.0", - "@aws-sdk/types": "^3.973.1", - "@smithy/credential-provider-imds": "^4.2.8", - "@smithy/property-provider": "^4.2.8", - "@smithy/shared-ini-file-loader": "^4.4.3", - "@smithy/types": "^4.12.0", + "version": "3.972.13", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.13.tgz", + "integrity": "sha512-JKSoGb7XeabZLBJptpqoZIFbROUIS65NuQnEHGOpuT9GuuZwag2qciKANiDLFiYk4u8nSrJC9JIOnWKVvPVjeA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.15", + "@aws-sdk/credential-provider-env": "^3.972.13", + "@aws-sdk/credential-provider-http": "^3.972.15", + "@aws-sdk/credential-provider-login": "^3.972.13", + "@aws-sdk/credential-provider-process": "^3.972.13", + "@aws-sdk/credential-provider-sso": "^3.972.13", + "@aws-sdk/credential-provider-web-identity": "^3.972.13", + "@aws-sdk/nested-clients": "^3.996.3", + "@aws-sdk/types": "^3.973.4", + "@smithy/credential-provider-imds": "^4.2.10", + "@smithy/property-provider": "^4.2.10", + "@smithy/shared-ini-file-loader": "^4.4.5", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -397,17 +354,18 @@ } }, "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.3.tgz", - "integrity": "sha512-Gc3O91iVvA47kp2CLIXOwuo5ffo1cIpmmyIewcYjAcvurdFHQ8YdcBe1KHidnbbBO4/ZtywGBACsAX5vr3UdoA==", - "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/nested-clients": "3.980.0", - "@aws-sdk/types": "^3.973.1", - "@smithy/property-provider": "^4.2.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/shared-ini-file-loader": "^4.4.3", - "@smithy/types": "^4.12.0", + "version": "3.972.13", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.13.tgz", + "integrity": "sha512-RtYcrxdnJHKY8MFQGLltCURcjuMjnaQpAxPE6+/QEdDHHItMKZgabRe/KScX737F9vJMQsmJy9EmMOkCnoC1JQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.15", + "@aws-sdk/nested-clients": "^3.996.3", + "@aws-sdk/types": "^3.973.4", + "@smithy/property-provider": "^4.2.10", + "@smithy/protocol-http": "^5.3.10", + "@smithy/shared-ini-file-loader": "^4.4.5", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -415,21 +373,22 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.4.tgz", - "integrity": "sha512-UwerdzosMSY7V5oIZm3NsMDZPv2aSVzSkZxYxIOWHBeKTZlUqW7XpHtJMZ4PZpJ+HMRhgP+MDGQx4THndgqJfQ==", - "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.3", - "@aws-sdk/credential-provider-http": "^3.972.5", - "@aws-sdk/credential-provider-ini": "^3.972.3", - "@aws-sdk/credential-provider-process": "^3.972.3", - "@aws-sdk/credential-provider-sso": "^3.972.3", - "@aws-sdk/credential-provider-web-identity": "^3.972.3", - "@aws-sdk/types": "^3.973.1", - "@smithy/credential-provider-imds": "^4.2.8", - "@smithy/property-provider": "^4.2.8", - "@smithy/shared-ini-file-loader": "^4.4.3", - "@smithy/types": "^4.12.0", + "version": "3.972.14", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.14.tgz", + "integrity": "sha512-WqoC2aliIjQM/L3oFf6j+op/enT2i9Cc4UTxxMEKrJNECkq4/PlKE5BOjSYFcq6G9mz65EFbXJh7zOU4CvjSKQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.13", + "@aws-sdk/credential-provider-http": "^3.972.15", + "@aws-sdk/credential-provider-ini": "^3.972.13", + "@aws-sdk/credential-provider-process": "^3.972.13", + "@aws-sdk/credential-provider-sso": "^3.972.13", + "@aws-sdk/credential-provider-web-identity": "^3.972.13", + "@aws-sdk/types": "^3.973.4", + "@smithy/credential-provider-imds": "^4.2.10", + "@smithy/property-provider": "^4.2.10", + "@smithy/shared-ini-file-loader": "^4.4.5", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -437,15 +396,16 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.3.tgz", - "integrity": "sha512-xkSY7zjRqeVc6TXK2xr3z1bTLm0wD8cj3lAkproRGaO4Ku7dPlKy843YKnHrUOUzOnMezdZ4xtmFc0eKIDTo2w==", - "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/types": "^3.973.1", - "@smithy/property-provider": "^4.2.8", - "@smithy/shared-ini-file-loader": "^4.4.3", - "@smithy/types": "^4.12.0", + "version": "3.972.13", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.13.tgz", + "integrity": "sha512-rsRG0LQA4VR+jnDyuqtXi2CePYSmfm5GNL9KxiW8DSe25YwJSr06W8TdUfONAC+rjsTI+aIH2rBGG5FjMeANrw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.15", + "@aws-sdk/types": "^3.973.4", + "@smithy/property-provider": "^4.2.10", + "@smithy/shared-ini-file-loader": "^4.4.5", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -453,17 +413,18 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.3.tgz", - "integrity": "sha512-8Ww3F5Ngk8dZ6JPL/V5LhCU1BwMfQd3tLdoEuzaewX8FdnT633tPr+KTHySz9FK7fFPcz5qG3R5edVEhWQD4AA==", - "dependencies": { - "@aws-sdk/client-sso": "3.980.0", - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/token-providers": "3.980.0", - "@aws-sdk/types": "^3.973.1", - "@smithy/property-provider": "^4.2.8", - "@smithy/shared-ini-file-loader": "^4.4.3", - "@smithy/types": "^4.12.0", + "version": "3.972.13", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.13.tgz", + "integrity": "sha512-fr0UU1wx8kNHDhTQBXioc/YviSW8iXuAxHvnH7eQUtn8F8o/FU3uu6EUMvAQgyvn7Ne5QFnC0Cj0BFlwCk+RFw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.15", + "@aws-sdk/nested-clients": "^3.996.3", + "@aws-sdk/token-providers": "3.999.0", + "@aws-sdk/types": "^3.973.4", + "@smithy/property-provider": "^4.2.10", + "@smithy/shared-ini-file-loader": "^4.4.5", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -471,16 +432,17 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.3.tgz", - "integrity": "sha512-62VufdcH5rRfiRKZRcf1wVbbt/1jAntMj1+J0qAd+r5pQRg2t0/P9/Rz16B1o5/0Se9lVL506LRjrhIJAhYBfA==", - "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/nested-clients": "3.980.0", - "@aws-sdk/types": "^3.973.1", - "@smithy/property-provider": "^4.2.8", - "@smithy/shared-ini-file-loader": "^4.4.3", - "@smithy/types": "^4.12.0", + "version": "3.972.13", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.13.tgz", + "integrity": "sha512-a6iFMh1pgUH0TdcouBppLJUfPM7Yd3R9S1xFodPtCRoLqCz2RQFA3qjA8x4112PVYXEd4/pHX2eihapq39w0rA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.15", + "@aws-sdk/nested-clients": "^3.996.3", + "@aws-sdk/types": "^3.973.4", + "@smithy/property-provider": "^4.2.10", + "@smithy/shared-ini-file-loader": "^4.4.5", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -488,13 +450,14 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.3.tgz", - "integrity": "sha512-aknPTb2M+G3s+0qLCx4Li/qGZH8IIYjugHMv15JTYMe6mgZO8VBpYgeGYsNMGCqCZOcWzuf900jFBG5bopfzmA==", - "dependencies": { - "@aws-sdk/types": "^3.973.1", - "@smithy/protocol-http": "^5.3.8", - "@smithy/types": "^4.12.0", + "version": "3.972.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.6.tgz", + "integrity": "sha512-5XHwjPH1lHB+1q4bfC7T8Z5zZrZXfaLcjSMwTd1HPSPrCmPFMbg3UQ5vgNWcVj0xoX4HWqTGkSf2byrjlnRg5w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.4", + "@smithy/protocol-http": "^5.3.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -502,12 +465,13 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.3.tgz", - "integrity": "sha512-Ftg09xNNRqaz9QNzlfdQWfpqMCJbsQdnZVJP55jfhbKi1+FTWxGuvfPoBhDHIovqWKjqbuiew3HuhxbJ0+OjgA==", + "version": "3.972.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.6.tgz", + "integrity": "sha512-iFnaMFMQdljAPrvsCVKYltPt2j40LQqukAbXvW7v0aL5I+1GO7bZ/W8m12WxW3gwyK5p5u1WlHg8TSAizC5cZw==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.973.1", - "@smithy/types": "^4.12.0", + "@aws-sdk/types": "^3.973.4", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -515,14 +479,15 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.3.tgz", - "integrity": "sha512-PY57QhzNuXHnwbJgbWYTrqIDHYSeOlhfYERTAuc16LKZpTZRJUjzBFokp9hF7u1fuGeE3D70ERXzdbMBOqQz7Q==", + "version": "3.972.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.6.tgz", + "integrity": "sha512-dY4v3of5EEMvik6+UDwQ96KfUFDk8m1oZDdkSc5lwi4o7rFrjnv0A+yTV+gu230iybQZnKgDLg/rt2P3H+Vscw==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.973.1", + "@aws-sdk/types": "^3.973.4", "@aws/lambda-invoke-store": "^0.2.2", - "@smithy/protocol-http": "^5.3.8", - "@smithy/types": "^4.12.0", + "@smithy/protocol-http": "^5.3.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -530,31 +495,17 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.972.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.5.tgz", - "integrity": "sha512-TVZQ6PWPwQbahUI8V+Er+gS41ctIawcI/uMNmQtQ7RMcg3JYn6gyKAFKUb3HFYx2OjYlx1u11sETSwwEUxVHTg==", - "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.980.0", - "@smithy/core": "^3.22.0", - "@smithy/protocol-http": "^5.3.8", - "@smithy/types": "^4.12.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent/node_modules/@aws-sdk/util-endpoints": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.980.0.tgz", - "integrity": "sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw==", - "dependencies": { - "@aws-sdk/types": "^3.973.1", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-endpoints": "^3.2.8", + "version": "3.972.15", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.15.tgz", + "integrity": "sha512-ABlFVcIMmuRAwBT+8q5abAxOr7WmaINirDJBnqGY5b5jSDo00UMlg/G4a0xoAgwm6oAECeJcwkvDlxDwKf58fQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.15", + "@aws-sdk/types": "^3.973.4", + "@aws-sdk/util-endpoints": "^3.996.3", + "@smithy/core": "^3.23.6", + "@smithy/protocol-http": "^5.3.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -562,62 +513,48 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.980.0.tgz", - "integrity": "sha512-/dONY5xc5/CCKzOqHZCTidtAR4lJXWkGefXvTRKdSKMGaYbbKsxDckisd6GfnvPSLxWtvQzwgRGRutMRoYUApQ==", + "version": "3.996.3", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.3.tgz", + "integrity": "sha512-AU5TY1V29xqwg/MxmA2odwysTez+ccFAhmfRJk+QZT5HNv90UTA9qKd1J9THlsQkvmH7HWTEV1lDNxkQO5PzNw==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/middleware-host-header": "^3.972.3", - "@aws-sdk/middleware-logger": "^3.972.3", - "@aws-sdk/middleware-recursion-detection": "^3.972.3", - "@aws-sdk/middleware-user-agent": "^3.972.5", - "@aws-sdk/region-config-resolver": "^3.972.3", - "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.980.0", - "@aws-sdk/util-user-agent-browser": "^3.972.3", - "@aws-sdk/util-user-agent-node": "^3.972.3", - "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.22.0", - "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/hash-node": "^4.2.8", - "@smithy/invalid-dependency": "^4.2.8", - "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.12", - "@smithy/middleware-retry": "^4.4.29", - "@smithy/middleware-serde": "^4.2.9", - "@smithy/middleware-stack": "^4.2.8", - "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.28", - "@smithy/util-defaults-mode-node": "^4.2.31", - "@smithy/util-endpoints": "^3.2.8", - "@smithy/util-middleware": "^4.2.8", - "@smithy/util-retry": "^4.2.8", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-endpoints": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.980.0.tgz", - "integrity": "sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw==", - "dependencies": { - "@aws-sdk/types": "^3.973.1", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-endpoints": "^3.2.8", + "@aws-sdk/core": "^3.973.15", + "@aws-sdk/middleware-host-header": "^3.972.6", + "@aws-sdk/middleware-logger": "^3.972.6", + "@aws-sdk/middleware-recursion-detection": "^3.972.6", + "@aws-sdk/middleware-user-agent": "^3.972.15", + "@aws-sdk/region-config-resolver": "^3.972.6", + "@aws-sdk/types": "^3.973.4", + "@aws-sdk/util-endpoints": "^3.996.3", + "@aws-sdk/util-user-agent-browser": "^3.972.6", + "@aws-sdk/util-user-agent-node": "^3.973.0", + "@smithy/config-resolver": "^4.4.9", + "@smithy/core": "^3.23.6", + "@smithy/fetch-http-handler": "^5.3.11", + "@smithy/hash-node": "^4.2.10", + "@smithy/invalid-dependency": "^4.2.10", + "@smithy/middleware-content-length": "^4.2.10", + "@smithy/middleware-endpoint": "^4.4.20", + "@smithy/middleware-retry": "^4.4.37", + "@smithy/middleware-serde": "^4.2.11", + "@smithy/middleware-stack": "^4.2.10", + "@smithy/node-config-provider": "^4.3.10", + "@smithy/node-http-handler": "^4.4.12", + "@smithy/protocol-http": "^5.3.10", + "@smithy/smithy-client": "^4.12.0", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.10", + "@smithy/util-base64": "^4.3.1", + "@smithy/util-body-length-browser": "^4.2.1", + "@smithy/util-body-length-node": "^4.2.2", + "@smithy/util-defaults-mode-browser": "^4.3.36", + "@smithy/util-defaults-mode-node": "^4.2.39", + "@smithy/util-endpoints": "^3.3.1", + "@smithy/util-middleware": "^4.2.10", + "@smithy/util-retry": "^4.2.10", + "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" }, "engines": { @@ -625,14 +562,15 @@ } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.3.tgz", - "integrity": "sha512-v4J8qYAWfOMcZ4MJUyatntOicTzEMaU7j3OpkRCGGFSL2NgXQ5VbxauIyORA+pxdKZ0qQG2tCQjQjZDlXEC3Ow==", - "dependencies": { - "@aws-sdk/types": "^3.973.1", - "@smithy/config-resolver": "^4.4.6", - "@smithy/node-config-provider": "^4.3.8", - "@smithy/types": "^4.12.0", + "version": "3.972.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.6.tgz", + "integrity": "sha512-Aa5PusHLXAqLTX1UKDvI3pHQJtIsF7Q+3turCHqfz/1F61/zDMWfbTC8evjhrrYVAtz9Vsv3SJ/waSUeu7B6gw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.4", + "@smithy/config-resolver": "^4.4.9", + "@smithy/node-config-provider": "^4.3.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -640,16 +578,17 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.980.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.980.0.tgz", - "integrity": "sha512-1nFileg1wAgDmieRoj9dOawgr2hhlh7xdvcH57b1NnqfPaVlcqVJyPc6k3TLDUFPY69eEwNxdGue/0wIz58vjA==", - "dependencies": { - "@aws-sdk/core": "^3.973.5", - "@aws-sdk/nested-clients": "3.980.0", - "@aws-sdk/types": "^3.973.1", - "@smithy/property-provider": "^4.2.8", - "@smithy/shared-ini-file-loader": "^4.4.3", - "@smithy/types": "^4.12.0", + "version": "3.999.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.999.0.tgz", + "integrity": "sha512-cx0hHUlgXULfykx4rdu/ciNAJaa3AL5xz3rieCz7NKJ68MJwlj3664Y8WR5MGgxfyYJBdamnkjNSx5Kekuc0cg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.15", + "@aws-sdk/nested-clients": "^3.996.3", + "@aws-sdk/types": "^3.973.4", + "@smithy/property-provider": "^4.2.10", + "@smithy/shared-ini-file-loader": "^4.4.5", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -657,11 +596,12 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.973.1", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.1.tgz", - "integrity": "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg==", + "version": "3.973.4", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.4.tgz", + "integrity": "sha512-RW60aH26Bsc016Y9B98hC0Plx6fK5P2v/iQYwMzrSjiDh1qRMUCP6KrXHYEHe3uFvKiOC93Z9zk4BJsUi6Tj1Q==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -669,14 +609,15 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.981.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.981.0.tgz", - "integrity": "sha512-a8nXh/H3/4j+sxhZk+N3acSDlgwTVSZbX9i55dx41gI1H+geuonuRG+Shv3GZsCb46vzc08RK2qC78ypO8uRlg==", - "dependencies": { - "@aws-sdk/types": "^3.973.1", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-endpoints": "^3.2.8", + "version": "3.996.3", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.996.3.tgz", + "integrity": "sha512-yWIQSNiCjykLL+ezN5A+DfBb1gfXTytBxm57e64lYmwxDHNmInYHRJYYRAGWG1o77vKEiWaw4ui28e3yb1k5aQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.4", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.10", + "@smithy/util-endpoints": "^3.3.1", "tslib": "^2.6.2" }, "engines": { @@ -687,6 +628,7 @@ "version": "3.965.4", "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.4.tgz", "integrity": "sha512-H1onv5SkgPBK2P6JR2MjGgbOnttoNzSPIRoeZTNPZYyaplwGg50zS3amXvXqF0/qfXpWEC9rLWU564QTB9bSog==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -695,25 +637,27 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.3.tgz", - "integrity": "sha512-JurOwkRUcXD/5MTDBcqdyQ9eVedtAsZgw5rBwktsPTN7QtPiS2Ld1jkJepNgYoCufz1Wcut9iup7GJDoIHp8Fw==", + "version": "3.972.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.6.tgz", + "integrity": "sha512-Fwr/llD6GOrFgQnKaI2glhohdGuBDfHfora6iG9qsBBBR8xv1SdCSwbtf5CWlUdCw5X7g76G/9Hf0Inh0EmoxA==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.973.1", - "@smithy/types": "^4.12.0", + "@aws-sdk/types": "^3.973.4", + "@smithy/types": "^4.13.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.972.3.tgz", - "integrity": "sha512-gqG+02/lXQtO0j3US6EVnxtwwoXQC5l2qkhLCrqUrqdtcQxV7FDMbm9wLjKqoronSHyELGTjbFKK/xV5q1bZNA==", - "dependencies": { - "@aws-sdk/middleware-user-agent": "^3.972.5", - "@aws-sdk/types": "^3.973.1", - "@smithy/node-config-provider": "^4.3.8", - "@smithy/types": "^4.12.0", + "version": "3.973.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.0.tgz", + "integrity": "sha512-A9J2G4Nf236e9GpaC1JnA8wRn6u6GjnOXiTwBLA6NUJhlBTIGfrTy+K1IazmF8y+4OFdW3O5TZlhyspJMqiqjA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "^3.972.15", + "@aws-sdk/types": "^3.973.4", + "@smithy/node-config-provider": "^4.3.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -729,12 +673,13 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.972.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.3.tgz", - "integrity": "sha512-bCk63RsBNCWW4tt5atv5Sbrh+3J3e8YzgyF6aZb1JeXcdzG4k5SlPLeTMFOIXFuuFHIwgphUhn4i3uS/q49eww==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.8.tgz", + "integrity": "sha512-Ql8elcUdYCha83Ol7NznBsgN5GVZnv3vUd86fEc6waU6oUdY0T1O9NODkEEOS/Uaogr87avDrUC6DSeM4oXjZg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0", - "fast-xml-parser": "5.3.4", + "@smithy/types": "^4.13.0", + "fast-xml-parser": "5.3.6", "tslib": "^2.6.2" }, "engines": { @@ -745,6 +690,7 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.3.tgz", "integrity": "sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==", + "license": "Apache-2.0", "engines": { "node": ">=18.0.0" } @@ -753,6 +699,7 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/@azure-rest/core-client/-/core-client-2.5.1.tgz", "integrity": "sha512-EHaOXW0RYDKS5CFffnixdyRPak5ytiCtU7uXDcP/uiY+A6jFRwNGzzJBiznkCzvi5EYpY+YWinieqHb0oY916A==", + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", @@ -769,6 +716,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "license": "MIT", "dependencies": { "tslib": "^2.6.2" }, @@ -780,6 +728,7 @@ "version": "1.10.1", "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.10.1.tgz", "integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==", + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-util": "^1.13.0", @@ -793,6 +742,7 @@ "version": "1.10.1", "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.1.tgz", "integrity": "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==", + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", @@ -807,22 +757,26 @@ } }, "node_modules/@azure/core-http-compat": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.3.1.tgz", - "integrity": "sha512-az9BkXND3/d5VgdRRQVkiJb2gOmDU8Qcq4GvjtBmDICNiQ9udFmDk4ZpSB5Qq1OmtDJGlQAfBaS4palFsazQ5g==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.3.2.tgz", + "integrity": "sha512-Tf6ltdKzOJEgxZeWLCjMxrxbodB/ZeCbzzA1A2qHbhzAjzjHoBVSUeSl/baT/oHAxhc4qdqVaDKnc2+iE932gw==", + "license": "MIT", "dependencies": { - "@azure/abort-controller": "^2.1.2", - "@azure/core-client": "^1.10.0", - "@azure/core-rest-pipeline": "^1.22.0" + "@azure/abort-controller": "^2.1.2" }, "engines": { "node": ">=20.0.0" + }, + "peerDependencies": { + "@azure/core-client": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0" } }, "node_modules/@azure/core-lro": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.7.2.tgz", "integrity": "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==", + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-util": "^1.2.0", @@ -837,6 +791,7 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.6.2.tgz", "integrity": "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==", + "license": "MIT", "dependencies": { "tslib": "^2.6.2" }, @@ -848,6 +803,7 @@ "version": "1.22.2", "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.22.2.tgz", "integrity": "sha512-MzHym+wOi8CLUlKCQu12de0nwcq9k9Kuv43j4Wa++CsCpJwps2eeBQwD2Bu8snkxTtDKDx4GwjuR9E8yC8LNrg==", + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", @@ -865,6 +821,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.3.1.tgz", "integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==", + "license": "MIT", "dependencies": { "tslib": "^2.6.2" }, @@ -876,6 +833,7 @@ "version": "1.13.1", "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.13.1.tgz", "integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==", + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.1.2", "@typespec/ts-http-runtime": "^0.3.0", @@ -889,6 +847,7 @@ "version": "4.13.0", "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.0.tgz", "integrity": "sha512-uWC0fssc+hs1TGGVkkghiaFkkS7NkTxfnCH+Hdg+yTehTpMcehpok4PgUKKdyCH+9ldu6FhiHRv84Ntqj1vVcw==", + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.9.0", @@ -910,6 +869,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@azure/keyvault-common/-/keyvault-common-2.0.0.tgz", "integrity": "sha512-wRLVaroQtOqfg60cxkzUkGKrKMsCP6uYXAOomOIysSMyt1/YM0eUn9LqieAWM8DLcU4+07Fio2YGpPeqUbpP9w==", + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.3.0", @@ -928,6 +888,7 @@ "version": "4.10.0", "resolved": "https://registry.npmjs.org/@azure/keyvault-secrets/-/keyvault-secrets-4.10.0.tgz", "integrity": "sha512-WvXc3h2hqHL1pMzUU7ANE2RBKoxjK3JQc0YNn6GUFvOWQtf2ZR+sH4/5cZu8zAg62v9qLCduBN7065nHKl+AOA==", + "license": "MIT", "dependencies": { "@azure-rest/core-client": "^2.3.3", "@azure/abort-controller": "^2.1.2", @@ -950,6 +911,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz", "integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==", + "license": "MIT", "dependencies": { "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" @@ -959,30 +921,33 @@ } }, "node_modules/@azure/msal-browser": { - "version": "4.27.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.27.0.tgz", - "integrity": "sha512-bZ8Pta6YAbdd0o0PEaL1/geBsPrLEnyY/RDWqvF1PP9RUH8EMLvUMGoZFYS6jSlUan6KZ9IMTLCnwpWWpQRK/w==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.29.0.tgz", + "integrity": "sha512-/f3eHkSNUTl6DLQHm+bKecjBKcRQxbd/XLx8lvSYp8Nl/HRyPuIPOijt9Dt0sH50/SxOwQ62RnFCmFlGK+bR/w==", + "license": "MIT", "dependencies": { - "@azure/msal-common": "15.13.3" + "@azure/msal-common": "15.15.0" }, "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-common": { - "version": "15.13.3", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.13.3.tgz", - "integrity": "sha512-shSDU7Ioecya+Aob5xliW9IGq1Ui8y4EVSdWGyI1Gbm4Vg61WpP95LuzcY214/wEjSn6w4PZYD4/iVldErHayQ==", + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.15.0.tgz", + "integrity": "sha512-/n+bN0AKlVa+AOcETkJSKj38+bvFs78BaP4rNtv3MJCmPH0YrHiskMRe74OhyZ5DZjGISlFyxqvf9/4QVEi2tw==", + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-node": { - "version": "3.8.4", - "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-3.8.4.tgz", - "integrity": "sha512-lvuAwsDpPDE/jSuVQOBMpLbXuVuLsPNRwWCyK3/6bPlBk0fGWegqoZ0qjZclMWyQ2JNvIY3vHY7hoFmFmFQcOw==", + "version": "3.8.8", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-3.8.8.tgz", + "integrity": "sha512-+f1VrJH1iI517t4zgmuhqORja0bL6LDQXfBqkjuMmfTYXTQQnh1EvwwxO3UbKLT05N0obF72SRHFrC1RBDv5Gg==", + "license": "MIT", "dependencies": { - "@azure/msal-common": "15.13.3", + "@azure/msal-common": "15.15.0", "jsonwebtoken": "^9.0.0", "uuid": "^8.3.0" }, @@ -994,17 +959,19 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -1013,29 +980,31 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -1055,13 +1024,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/core/node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -1078,25 +1049,28 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -1106,12 +1080,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", + "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -1126,6 +1101,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -1135,47 +1111,45 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, "node_modules/@babel/helper-globals": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1189,6 +1163,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1198,6 +1173,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1207,30 +1183,33 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.28.5" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -1240,31 +1219,33 @@ } }, "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", "debug": "^4.3.1" }, "engines": { @@ -1276,6 +1257,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -1292,13 +1274,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" @@ -1312,21 +1296,24 @@ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.1.90" } }, "node_modules/@datasance/ecn-viewer": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@datasance/ecn-viewer/-/ecn-viewer-1.3.0.tgz", - "integrity": "sha512-tRjy+H7SVRfLyFLU9LhiibUNIMa1vNNdlYOh7OHaka9BYGurKG39klD4uEADGF+CIcK8AKmTnvwBK72fNpfM8g==" + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@datasance/ecn-viewer/-/ecn-viewer-1.4.2.tgz", + "integrity": "sha512-f+le0TnjsGhgS8EbzEY61KLrwbDLSrlXsNnVyxSa+nZlaQTyomCGWEt6Vh9GFYBYlus+Tm0Q4hbSOsAwqkeuUA==", + "license": "EPL-2.0" }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" }, @@ -1345,6 +1332,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -1357,6 +1345,7 @@ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -1366,6 +1355,7 @@ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz", "integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", @@ -1380,6 +1370,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -1396,13 +1387,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@eslint/config-helpers": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.3.tgz", "integrity": "sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -1412,6 +1405,7 @@ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" }, @@ -1420,19 +1414,20 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.4.tgz", + "integrity": "sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==", "dev": true, + "license": "MIT", "dependencies": { - "ajv": "^6.12.4", + "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", + "minimatch": "^3.1.3", "strip-json-comments": "^3.1.1" }, "engines": { @@ -1447,6 +1442,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -1463,13 +1459,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@eslint/js": { "version": "9.28.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -1482,6 +1480,7 @@ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -1491,6 +1490,7 @@ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@eslint/core": "^0.15.2", "levn": "^0.4.1" @@ -1504,6 +1504,7 @@ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" }, @@ -1516,18 +1517,21 @@ "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-5.5.3.tgz", "integrity": "sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==", "deprecated": "Please update to a newer version.", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", "optional": true }, "node_modules/@google-cloud/secret-manager": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/@google-cloud/secret-manager/-/secret-manager-6.1.1.tgz", "integrity": "sha512-dwSuxJ9RNmAW46FjK1StiNIeOiSHHQs/XIy4VArJ6bBMR+WsIvR+zhPh2pa40aFa9uTty67j38Rl268TVV62EA==", + "license": "Apache-2.0", "dependencies": { "google-gax": "^5.0.0" }, @@ -1536,9 +1540,10 @@ } }, "node_modules/@grpc/grpc-js": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.2.tgz", - "integrity": "sha512-QzVUtEFyu05UNx2xr0fCQmStUO17uVQhGNowtxs00IgTZT6/W2PBLfUkj30s0FKJ29VtTa3ArVNIhNP6akQhqA==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz", + "integrity": "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==", + "license": "Apache-2.0", "dependencies": { "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" @@ -1551,6 +1556,7 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", + "license": "Apache-2.0", "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", @@ -1569,6 +1575,7 @@ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18.0" } @@ -1578,6 +1585,7 @@ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" @@ -1591,6 +1599,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -1604,6 +1613,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -1616,6 +1626,7 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -1632,6 +1643,7 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -1643,6 +1655,7 @@ "version": "6.2.3", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -1653,12 +1666,14 @@ "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -1675,6 +1690,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -1689,6 +1705,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -1705,6 +1722,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", "dependencies": { "minipass": "^7.0.4" }, @@ -1712,19 +1730,12 @@ "node": ">=18.0.0" } }, - "node_modules/@isaacs/fs-minipass/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -1741,6 +1752,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } @@ -1750,6 +1762,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -1763,6 +1776,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -1776,6 +1790,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -1788,6 +1803,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -1803,6 +1819,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -1815,6 +1832,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1823,13 +1841,15 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1839,6 +1859,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" @@ -1849,6 +1870,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -1859,6 +1881,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -1867,13 +1890,15 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -1883,6 +1908,7 @@ "version": "4.4.2", "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/js-sdsl" @@ -1892,6 +1918,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz", "integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==", + "license": "MIT", "engines": { "node": ">= 10.16.0" }, @@ -1903,6 +1930,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz", "integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==", + "license": "MIT", "engines": { "node": ">= 10.16.0" }, @@ -1911,38 +1939,76 @@ } }, "node_modules/@kubernetes/client-node": { - "version": "0.22.3", - "resolved": "https://registry.npmjs.org/@kubernetes/client-node/-/client-node-0.22.3.tgz", - "integrity": "sha512-dG8uah3+HDJLpJEESshLRZlAZ4PgDeV9mZXT0u1g7oy4KMRzdZ7n5g0JEIlL6QhK51/2ztcIqURAnjfjJt6Z+g==", - "dependencies": { - "byline": "^5.0.0", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@kubernetes/client-node/-/client-node-1.4.0.tgz", + "integrity": "sha512-Zge3YvF7DJi264dU1b3wb/GmzR99JhUpqTvp+VGHfwZT+g7EOOYNScDJNZwXy9cszyIGPIs0VHr+kk8e95qqrA==", + "license": "Apache-2.0", + "dependencies": { + "@types/js-yaml": "^4.0.1", + "@types/node": "^24.0.0", + "@types/node-fetch": "^2.6.13", + "@types/stream-buffers": "^3.0.3", + "form-data": "^4.0.0", + "hpagent": "^1.2.0", "isomorphic-ws": "^5.0.0", "js-yaml": "^4.1.0", - "jsonpath-plus": "^10.2.0", - "request": "^2.88.0", + "jsonpath-plus": "^10.3.0", + "node-fetch": "^2.7.0", + "openid-client": "^6.1.3", "rfc4648": "^1.3.0", + "socks-proxy-agent": "^8.0.4", "stream-buffers": "^3.0.2", - "tar": "^7.0.0", - "tslib": "^2.4.1", - "ws": "^8.18.0" - }, - "optionalDependencies": { - "openid-client": "^6.1.3" + "tar-fs": "^3.0.9", + "ws": "^8.18.2" } }, - "node_modules/@kubernetes/client-node/@cypress/request@3.0.8": {}, "node_modules/@msgpack/msgpack": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.1.2.tgz", - "integrity": "sha512-JEW4DEtBzfe8HvUYecLU9e6+XJnKDlUAIve8FvPzF3Kzs6Xo/KuZkZJsDH0wJXl/qEZbeeE7edxDNY3kMs39hQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.1.3.tgz", + "integrity": "sha512-47XIizs9XZXvuJgoaJUIE2lFoID8ugvc0jzSHP+Ptfk8nTbnR8g788wv48N03Kx0UkAv559HWRQ3yzOgzlRNUA==", + "license": "ISC", "engines": { "node": ">= 18" } }, + "node_modules/@nats-io/jwt": { + "version": "0.0.10-5", + "resolved": "https://registry.npmjs.org/@nats-io/jwt/-/jwt-0.0.10-5.tgz", + "integrity": "sha512-DoBIEJIgWZJLtMRef+oFvk1lEgyTIVcAZbBXYGm91B7az1bCu7A3Npsn/VD7RH5waYAz+EPS8Ot7zyU6iKAuqg==", + "license": "Apache-2.0", + "dependencies": { + "@nats-io/nkeys": "^1.2.0-4" + } + }, + "node_modules/@nats-io/jwt/node_modules/@nats-io/nkeys": { + "version": "1.2.0-8", + "resolved": "https://registry.npmjs.org/@nats-io/nkeys/-/nkeys-1.2.0-8.tgz", + "integrity": "sha512-o6nfNYySzVZL7mIJA+ejD3JdMFbLn9VWtptM2cnHh4jeF/FvhPhCkn8BH4jQE7asCV/SSialu6jGhsAFV1FKkQ==", + "license": "Apache-2.0", + "dependencies": { + "tweetnacl": "^1.0.3" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@nats-io/nkeys": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nats-io/nkeys/-/nkeys-2.0.3.tgz", + "integrity": "sha512-JVt56GuE6Z89KUkI4TXUbSI9fmIfAmk6PMPknijmuL72GcD+UgIomTcRWiNvvJKxA01sBbmIPStqJs5cMRBC3A==", + "license": "Apache-2.0", + "dependencies": { + "tweetnacl": "^1.0.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@noble/hashes": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", "engines": { "node": "^14.21.3 || >=16" }, @@ -1954,6 +2020,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", "optional": true, "dependencies": { "@gar/promisify": "^1.0.1", @@ -1965,6 +2032,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", "optional": true, "dependencies": { "mkdirp": "^1.0.4", @@ -1974,10 +2042,33 @@ "node": ">=10" } }, + "node_modules/@npmcli/move-file/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@npmcli/move-file/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", "optional": true, "bin": { "mkdirp": "bin/cmd.js" @@ -1986,16 +2077,35 @@ "node": ">=10" } }, + "node_modules/@npmcli/move-file/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@one-ini/wasm": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@opentelemetry/api": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", "engines": { "node": ">=8.0.0" } @@ -2004,6 +2114,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.200.0.tgz", "integrity": "sha512-IKJBQxh91qJ+3ssRly5hYEJ8NDHu9oY/B1PXVSCWf7zytmYO9RNLB0Ox9XQ/fJ8m6gY6Q6NtBWlmXfaXt5Uc4Q==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.3.0" }, @@ -2015,6 +2126,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.0.0.tgz", "integrity": "sha512-IEkJGzK1A9v3/EHjXh3s2IiFc6L4jfK+lNgKVgUjeUJQRRhnVFMIO3TAvKwonm9O1HebCuoOt98v8bZW7oVQHA==", + "license": "Apache-2.0", "engines": { "node": "^18.19.0 || >=20.6.0" }, @@ -2026,6 +2138,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.0.tgz", "integrity": "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, @@ -2040,6 +2153,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.200.0.tgz", "integrity": "sha512-+3MDfa5YQPGM3WXxW9kqGD85Q7s9wlEMVNhXXG7tYFLnIeaseUt9YtCeFhEDFzfEktacdFpOtXmJuNW8cHbU5A==", + "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.0", @@ -2059,6 +2173,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.200.0.tgz", "integrity": "sha512-KfWw49htbGGp9s8N4KI8EQ9XuqKJ0VG+yVYVYFiCYSjEV32qpQ5qZ9UZBzOZ6xRb+E16SXOSCT3RkqBVSABZ+g==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@opentelemetry/core": "2.0.0", @@ -2077,6 +2192,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.200.0.tgz", "integrity": "sha512-GmahpUU/55hxfH4TP77ChOfftADsCq/nuri73I/AVLe2s4NIglvTsaACkFVZAVmnXXyPS00Fk3x27WS3yO07zA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@opentelemetry/core": "2.0.0", @@ -2097,6 +2213,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2112,6 +2229,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.200.0.tgz", "integrity": "sha512-uHawPRvKIrhqH09GloTuYeq2BjyieYHIpiklOvxm9zhrCL2eRsnI/6g9v2BZTVtGp8tEgIa7rCQ6Ltxw6NBgew==", + "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.0", @@ -2133,6 +2251,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2148,6 +2267,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.200.0.tgz", "integrity": "sha512-5BiR6i8yHc9+qW7F6LqkuUnIzVNA7lt0qRxIKcKT+gq3eGUPHZ3DY29sfxI3tkvnwMgtnHDMNze5DdxW39HsAw==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-exporter-base": "0.200.0", @@ -2166,6 +2286,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2181,6 +2302,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.200.0.tgz", "integrity": "sha512-E+uPj0yyvz81U9pvLZp3oHtFrEzNSqKGVkIViTQY1rH3TOobeJPSpLnTVXACnCwkPR5XeTvPnK3pZ2Kni8AFMg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/exporter-metrics-otlp-http": "0.200.0", @@ -2200,6 +2322,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2215,6 +2338,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.200.0.tgz", "integrity": "sha512-ZYdlU9r0USuuYppiDyU2VFRA0kFl855ylnb3N/2aOlXrbA4PMCznen7gmPbetGQu7pz8Jbaf4fwvrDnVdQQXSw==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", @@ -2231,6 +2355,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2246,6 +2371,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.200.0.tgz", "integrity": "sha512-hmeZrUkFl1YMsgukSuHCFPYeF9df0hHoKeHUthRKFCxiURs+GwF1VuabuHmBMZnjTbsuvNjOB+JSs37Csem/5Q==", + "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.0", @@ -2266,6 +2392,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2281,6 +2408,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.200.0.tgz", "integrity": "sha512-Goi//m/7ZHeUedxTGVmEzH19NgqJY+Bzr6zXo1Rni1+hwqaksEyJ44gdlEMREu6dzX1DlAaH/qSykSVzdrdafA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-exporter-base": "0.200.0", @@ -2299,6 +2427,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2314,6 +2443,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.200.0.tgz", "integrity": "sha512-V9TDSD3PjK1OREw2iT9TUTzNYEVWJk4Nhodzhp9eiz4onDMYmPy3LaGbPv81yIR6dUb/hNp/SIhpiCHwFUq2Vg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-exporter-base": "0.200.0", @@ -2332,6 +2462,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2347,6 +2478,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.0.0.tgz", "integrity": "sha512-icxaKZ+jZL/NHXX8Aru4HGsrdhK0MLcuRXkX5G5IRmCgoRLw+Br6I/nMVozX2xjGGwV7hw2g+4Slj8K7s4HbVg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", @@ -2364,6 +2496,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2379,6 +2512,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.200.0.tgz", "integrity": "sha512-pmPlzfJd+vvgaZd/reMsC8RWgTXn2WY1OWT5RT42m3aOn5532TozwXNDhg1vzqJ+jnvmkREcdLr27ebJEQt0Jg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@types/shimmer": "^1.2.0", @@ -2397,6 +2531,7 @@ "version": "0.48.1", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.48.1.tgz", "integrity": "sha512-j8NYOf9DRWtchbWor/zA0poI42TpZG9tViIKA0e1lC+6MshTqSJYtgNv8Fn1sx1Wn/TRyp+5OgSXiE4LDfvpEg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.200.0", @@ -2413,6 +2548,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.200.0.tgz", "integrity": "sha512-9tqGbCJikhYU68y3k9mi6yWsMyMeCcwoQuHvIXan5VvvPPQ5WIZaV6Mxu/MCVe4swRNoFs8Th+qyj0TZV5ELvw==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/instrumentation": "0.200.0", @@ -2430,6 +2566,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.200.0.tgz", "integrity": "sha512-IxJgA3FD7q4V6gGq4bnmQM5nTIyMDkoGFGrBrrDjB6onEiq1pafma55V+bHvGYLWvcqbBbRfezr1GED88lacEQ==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/otlp-transformer": "0.200.0" @@ -2445,6 +2582,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.200.0.tgz", "integrity": "sha512-CK2S+bFgOZ66Bsu5hlDeOX6cvW5FVtVjFFbWuaJP0ELxJKBB6HlbLZQ2phqz/uLj1cWap5xJr/PsR3iGoB7Vqw==", + "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.0", @@ -2462,6 +2600,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.200.0.tgz", "integrity": "sha512-+9YDZbYybOnv7sWzebWOeK6gKyt2XE7iarSyBFkwwnP559pEevKOUD8NyDHhRjCSp13ybh9iVXlMfcj/DwF/yw==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@opentelemetry/core": "2.0.0", @@ -2482,6 +2621,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2497,6 +2637,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.0.0.tgz", "integrity": "sha512-blx9S2EI49Ycuw6VZq+bkpaIoiJFhsDuvFGhBIoH3vJ5oYjJ2U0s3fAM5jYft99xVIAv6HqoPtlP9gpVA2IZtA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0" }, @@ -2511,6 +2652,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.0.0.tgz", "integrity": "sha512-Mbm/LSFyAtQKP0AQah4AfGgsD+vsZcyreZoQ5okFBk33hU7AquU4TltgyL9dvaO8/Zkoud8/0gEvwfOZ5d7EPA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0" }, @@ -2525,6 +2667,7 @@ "version": "1.30.1", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" @@ -2540,6 +2683,7 @@ "version": "1.30.1", "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/semantic-conventions": "1.28.0" }, @@ -2554,6 +2698,7 @@ "version": "1.28.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", "engines": { "node": ">=14" } @@ -2562,6 +2707,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.200.0.tgz", "integrity": "sha512-VZG870063NLfObmQQNtCVcdXXLzI3vOjjrRENmU37HYiPFa0ZXpXVDsTD02Nh3AT3xYJzQaWKl2X2lQ2l7TWJA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@opentelemetry/core": "2.0.0", @@ -2578,6 +2724,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2593,6 +2740,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.0.tgz", "integrity": "sha512-Bvy8QDjO05umd0+j+gDeWcTaVa1/R2lDj/eOvjzpm8VQj1K1vVZJuyjThpV5/lSHyYW2JaHF2IQ7Z8twJFAhjA==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0" @@ -2608,6 +2756,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2623,6 +2772,7 @@ "version": "0.200.0", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.200.0.tgz", "integrity": "sha512-S/YSy9GIswnhYoDor1RusNkmRughipvTCOQrlF1dzI70yQaf68qgf5WMnzUxdlCl3/et/pvaO75xfPfuEmCK5A==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@opentelemetry/core": "2.0.0", @@ -2658,6 +2808,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2673,6 +2824,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.0.tgz", "integrity": "sha512-qQnYdX+ZCkonM7tA5iU4fSRsVxbFGml8jbxOgipRGMFHKaXKHQ30js03rTobYjKjIfnOsZSbHKWF0/0v0OQGfw==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/resources": "2.0.0", @@ -2689,6 +2841,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.0.tgz", "integrity": "sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "2.0.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -2704,6 +2857,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.0.0.tgz", "integrity": "sha512-omdilCZozUjQwY3uZRBwbaRMJ3p09l4t187Lsdf0dGMye9WKD4NGcpgZRvqhI1dwcH6og+YXQEtoO9Wx3ykilg==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/context-async-hooks": "2.0.0", "@opentelemetry/core": "2.0.0", @@ -2717,9 +2871,10 @@ } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.38.0.tgz", - "integrity": "sha512-kocjix+/sSggfJhwXqClZ3i9Y/MI0fp7b+g7kCRm6psy2dsf8uApTRclwG18h8Avm7C9+fnt+O36PspJ/OzoWg==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.39.0.tgz", + "integrity": "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==", + "license": "Apache-2.0", "engines": { "node": ">=14" } @@ -2728,6 +2883,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", + "license": "MIT", "dependencies": { "@noble/hashes": "^1.1.5" } @@ -2736,6 +2892,7 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", "optional": true, "engines": { "node": ">=14" @@ -2746,6 +2903,7 @@ "resolved": "https://registry.npmjs.org/@postman/form-data/-/form-data-3.1.1.tgz", "integrity": "sha512-vjh8Q2a8S6UCm/KKs31XFJqEEgmbjBmpPNVV2eVav6905wyFAwaUOBGA1NPBI4ERH9MMZc6w0umFgM6WbEPMdg==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -2760,6 +2918,7 @@ "resolved": "https://registry.npmjs.org/@postman/tough-cookie/-/tough-cookie-4.1.3-postman.1.tgz", "integrity": "sha512-txpgUqZOnWYnUHZpHjkfb0IwVH4qJmyq77pPnJLlfhMtdCLMFTEeQHlzQiK906aaNCe4NEB5fGJHo9uzGbFMeA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -2771,10 +2930,11 @@ } }, "node_modules/@postman/tunnel-agent": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@postman/tunnel-agent/-/tunnel-agent-0.6.4.tgz", - "integrity": "sha512-CJJlq8V7rNKhAw4sBfjixKpJW00SHqebqNUQKxMoepgeWZIbdPcD+rguRcivGhS4N12PymDcKgUgSD4rVC+RjQ==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@postman/tunnel-agent/-/tunnel-agent-0.6.8.tgz", + "integrity": "sha512-2U42SmZW5G+suEcS++zB94sBWNO4qD4bvETGFRFDTqSpYl5ksfjcPqzYpgQgXgUmb6dfz+fAGbkcRamounGm0w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" }, @@ -2785,27 +2945,32 @@ "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -2814,33 +2979,39 @@ "node_modules/@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" }, "node_modules/@sentry-internal/tracing": { "version": "7.120.4", "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.120.4.tgz", "integrity": "sha512-Fz5+4XCg3akeoFK+K7g+d7HqGMjmnLoY2eJlpONJmaeT9pXY7yfUyXKZMmMajdE2LxxKJgQ2YKvSCaGVamTjHw==", "dev": true, + "license": "MIT", "dependencies": { "@sentry/core": "7.120.4", "@sentry/types": "7.120.4", @@ -2855,6 +3026,7 @@ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.120.4.tgz", "integrity": "sha512-TXu3Q5kKiq8db9OXGkWyXUbIxMMuttB5vJ031yolOl5T/B69JRyAoKuojLBjRv1XX583gS1rSSoX8YXX7ATFGA==", "dev": true, + "license": "MIT", "dependencies": { "@sentry/types": "7.120.4", "@sentry/utils": "7.120.4" @@ -2868,6 +3040,7 @@ "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.120.4.tgz", "integrity": "sha512-kkBTLk053XlhDCg7OkBQTIMF4puqFibeRO3E3YiVc4PGLnocXMaVpOSCkMqAc1k1kZ09UgGi8DxfQhnFEjUkpA==", "dev": true, + "license": "MIT", "dependencies": { "@sentry/core": "7.120.4", "@sentry/types": "7.120.4", @@ -2883,6 +3056,7 @@ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.120.4.tgz", "integrity": "sha512-qq3wZAXXj2SRWhqErnGCSJKUhPSlZ+RGnCZjhfjHpP49KNpcd9YdPTIUsFMgeyjdh6Ew6aVCv23g1hTP0CHpYw==", "dev": true, + "license": "MIT", "dependencies": { "@sentry-internal/tracing": "7.120.4", "@sentry/core": "7.120.4", @@ -2899,6 +3073,7 @@ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.120.4.tgz", "integrity": "sha512-cUq2hSSe6/qrU6oZsEP4InMI5VVdD86aypE+ENrQ6eZEVLTCYm1w6XhW1NvIu3UuWh7gZec4a9J7AFpYxki88Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2908,6 +3083,7 @@ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.120.4.tgz", "integrity": "sha512-zCKpyDIWKHwtervNK2ZlaK8mMV7gVUijAgFeJStH+CU/imcdquizV3pFLlSQYRswG+Lbyd6CT/LGRh3IbtkCFw==", "dev": true, + "license": "MIT", "dependencies": { "@sentry/types": "7.120.4" }, @@ -2920,6 +3096,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } @@ -2929,6 +3106,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz", "integrity": "sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1" } @@ -2938,6 +3116,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.3.tgz", "integrity": "sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", "type-detect": "^4.1.0" @@ -2948,6 +3127,7 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -2956,14 +3136,16 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "dev": true + "dev": true, + "license": "(Unlicense OR Apache-2.0)" }, "node_modules/@smithy/abort-controller": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.8.tgz", - "integrity": "sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.10.tgz", + "integrity": "sha512-qocxM/X4XGATqQtUkbE9SPUB6wekBi+FyJOMbPj0AhvyvFGYEmOlz6VB22iMePCQsFmMIvFSeViDvA7mZJG47g==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -2971,15 +3153,16 @@ } }, "node_modules/@smithy/config-resolver": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.6.tgz", - "integrity": "sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==", - "dependencies": { - "@smithy/node-config-provider": "^4.3.8", - "@smithy/types": "^4.12.0", - "@smithy/util-config-provider": "^4.2.0", - "@smithy/util-endpoints": "^3.2.8", - "@smithy/util-middleware": "^4.2.8", + "version": "4.4.9", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.9.tgz", + "integrity": "sha512-ejQvXqlcU30h7liR9fXtj7PIAau1t/sFbJpgWPfiYDs7zd16jpH0IsSXKcba2jF6ChTXvIjACs27kNMc5xxE2Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.10", + "@smithy/types": "^4.13.0", + "@smithy/util-config-provider": "^4.2.1", + "@smithy/util-endpoints": "^3.3.1", + "@smithy/util-middleware": "^4.2.10", "tslib": "^2.6.2" }, "engines": { @@ -2987,19 +3170,20 @@ } }, "node_modules/@smithy/core": { - "version": "3.22.1", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.22.1.tgz", - "integrity": "sha512-x3ie6Crr58MWrm4viHqqy2Du2rHYZjwu8BekasrQx4ca+Y24dzVAwq3yErdqIbc2G3I0kLQA13PQ+/rde+u65g==", - "dependencies": { - "@smithy/middleware-serde": "^4.2.9", - "@smithy/protocol-http": "^5.3.8", - "@smithy/types": "^4.12.0", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-middleware": "^4.2.8", - "@smithy/util-stream": "^4.5.11", - "@smithy/util-utf8": "^4.2.0", - "@smithy/uuid": "^1.1.0", + "version": "3.23.6", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.23.6.tgz", + "integrity": "sha512-4xE+0L2NrsFKpEVFlFELkIHQddBvMbQ41LRIP74dGCXnY1zQ9DgksrBcRBDJT+iOzGy4VEJIeU3hkUK5mn06kg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/middleware-serde": "^4.2.11", + "@smithy/protocol-http": "^5.3.10", + "@smithy/types": "^4.13.0", + "@smithy/util-base64": "^4.3.1", + "@smithy/util-body-length-browser": "^4.2.1", + "@smithy/util-middleware": "^4.2.10", + "@smithy/util-stream": "^4.5.15", + "@smithy/util-utf8": "^4.2.1", + "@smithy/uuid": "^1.1.1", "tslib": "^2.6.2" }, "engines": { @@ -3007,14 +3191,15 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.8.tgz", - "integrity": "sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw==", - "dependencies": { - "@smithy/node-config-provider": "^4.3.8", - "@smithy/property-provider": "^4.2.8", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.10.tgz", + "integrity": "sha512-3bsMLJJLTZGZqVGGeBVFfLzuRulVsGTj12BzRKODTHqUABpIr0jMN1vN3+u6r2OfyhAQ2pXaMZWX/swBK5I6PQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.10", + "@smithy/property-provider": "^4.2.10", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.10", "tslib": "^2.6.2" }, "engines": { @@ -3022,14 +3207,15 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.9.tgz", - "integrity": "sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==", - "dependencies": { - "@smithy/protocol-http": "^5.3.8", - "@smithy/querystring-builder": "^4.2.8", - "@smithy/types": "^4.12.0", - "@smithy/util-base64": "^4.3.0", + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.11.tgz", + "integrity": "sha512-wbTRjOxdFuyEg0CpumjZO0hkUl+fetJFqxNROepuLIoijQh51aMBmzFLfoQdwRjxsuuS2jizzIUTjPWgd8pd7g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.10", + "@smithy/querystring-builder": "^4.2.10", + "@smithy/types": "^4.13.0", + "@smithy/util-base64": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -3037,13 +3223,14 @@ } }, "node_modules/@smithy/hash-node": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.8.tgz", - "integrity": "sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA==", - "dependencies": { - "@smithy/types": "^4.12.0", - "@smithy/util-buffer-from": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.10.tgz", + "integrity": "sha512-1VzIOI5CcsvMDvP3iv1vG/RfLJVVVc67dCRyLSB2Hn9SWCZrDO3zvcIzj3BfEtqRW5kcMg5KAeVf1K3dR6nD3w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.0", + "@smithy/util-buffer-from": "^4.2.1", + "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" }, "engines": { @@ -3051,11 +3238,12 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.8.tgz", - "integrity": "sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.10.tgz", + "integrity": "sha512-vy9KPNSFUU0ajFYk0sDZIYiUlAWGEAhRfehIr5ZkdFrRFTAuXEPUd41USuqHU6vvLX4r6Q9X7MKBco5+Il0Org==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3063,9 +3251,10 @@ } }, "node_modules/@smithy/is-array-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", - "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.1.tgz", + "integrity": "sha512-Yfu664Qbf1B4IYIsYgKoABt010daZjkaCRvdU/sPnZG6TtHOB0md0RjNdLGzxe5UIdn9js4ftPICzmkRa9RJ4Q==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -3074,12 +3263,13 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.8.tgz", - "integrity": "sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.10.tgz", + "integrity": "sha512-TQZ9kX5c6XbjhaEBpvhSvMEZ0klBs1CFtOdPFwATZSbC9UeQfKHPLPN9Y+I6wZGMOavlYTOlHEPDrt42PMSH9w==", + "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.8", - "@smithy/types": "^4.12.0", + "@smithy/protocol-http": "^5.3.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3087,17 +3277,18 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.13.tgz", - "integrity": "sha512-x6vn0PjYmGdNuKh/juUJJewZh7MoQ46jYaJ2mvekF4EesMuFfrl4LaW/k97Zjf8PTCPQmPgMvwewg7eNoH9n5w==", - "dependencies": { - "@smithy/core": "^3.22.1", - "@smithy/middleware-serde": "^4.2.9", - "@smithy/node-config-provider": "^4.3.8", - "@smithy/shared-ini-file-loader": "^4.4.3", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-middleware": "^4.2.8", + "version": "4.4.20", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.20.tgz", + "integrity": "sha512-9W6Np4ceBP3XCYAGLoMCmn8t2RRVzuD1ndWPLBbv7H9CrwM9Bprf6Up6BM9ZA/3alodg0b7Kf6ftBK9R1N04vw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.23.6", + "@smithy/middleware-serde": "^4.2.11", + "@smithy/node-config-provider": "^4.3.10", + "@smithy/shared-ini-file-loader": "^4.4.5", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.10", + "@smithy/util-middleware": "^4.2.10", "tslib": "^2.6.2" }, "engines": { @@ -3105,18 +3296,19 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.4.30", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.30.tgz", - "integrity": "sha512-CBGyFvN0f8hlnqKH/jckRDz78Snrp345+PVk8Ux7pnkUCW97Iinse59lY78hBt04h1GZ6hjBN94BRwZy1xC8Bg==", - "dependencies": { - "@smithy/node-config-provider": "^4.3.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/service-error-classification": "^4.2.8", - "@smithy/smithy-client": "^4.11.2", - "@smithy/types": "^4.12.0", - "@smithy/util-middleware": "^4.2.8", - "@smithy/util-retry": "^4.2.8", - "@smithy/uuid": "^1.1.0", + "version": "4.4.37", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.37.tgz", + "integrity": "sha512-/1psZZllBBSQ7+qo5+hhLz7AEPGLx3Z0+e3ramMBEuPK2PfvLK4SrncDB9VegX5mBn+oP/UTDrM6IHrFjvX1ZA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.10", + "@smithy/protocol-http": "^5.3.10", + "@smithy/service-error-classification": "^4.2.10", + "@smithy/smithy-client": "^4.12.0", + "@smithy/types": "^4.13.0", + "@smithy/util-middleware": "^4.2.10", + "@smithy/util-retry": "^4.2.10", + "@smithy/uuid": "^1.1.1", "tslib": "^2.6.2" }, "engines": { @@ -3124,12 +3316,13 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.9.tgz", - "integrity": "sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.11.tgz", + "integrity": "sha512-STQdONGPwbbC7cusL60s7vOa6He6A9w2jWhoapL0mgVjmR19pr26slV+yoSP76SIssMTX/95e5nOZ6UQv6jolg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.8", - "@smithy/types": "^4.12.0", + "@smithy/protocol-http": "^5.3.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3137,11 +3330,12 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.8.tgz", - "integrity": "sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.10.tgz", + "integrity": "sha512-pmts/WovNcE/tlyHa8z/groPeOtqtEpp61q3W0nW1nDJuMq/x+hWa/OVQBtgU0tBqupeXq0VBOLA4UZwE8I0YA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3149,13 +3343,14 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.8.tgz", - "integrity": "sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==", - "dependencies": { - "@smithy/property-provider": "^4.2.8", - "@smithy/shared-ini-file-loader": "^4.4.3", - "@smithy/types": "^4.12.0", + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.10.tgz", + "integrity": "sha512-UALRbJtVX34AdP2VECKVlnNgidLHA2A7YgcJzwSBg1hzmnO/bZBHl/LDQQyYifzUwp1UOODnl9JJ3KNawpUJ9w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.10", + "@smithy/shared-ini-file-loader": "^4.4.5", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3163,14 +3358,15 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.9.tgz", - "integrity": "sha512-KX5Wml5mF+luxm1szW4QDz32e3NObgJ4Fyw+irhph4I/2geXwUy4jkIMUs5ZPGflRBeR6BUkC2wqIab4Llgm3w==", - "dependencies": { - "@smithy/abort-controller": "^4.2.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/querystring-builder": "^4.2.8", - "@smithy/types": "^4.12.0", + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.12.tgz", + "integrity": "sha512-zo1+WKJkR9x7ZtMeMDAAsq2PufwiLDmkhcjpWPRRkmeIuOm6nq1qjFICSZbnjBvD09ei8KMo26BWxsu2BUU+5w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.10", + "@smithy/protocol-http": "^5.3.10", + "@smithy/querystring-builder": "^4.2.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3178,11 +3374,12 @@ } }, "node_modules/@smithy/property-provider": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.8.tgz", - "integrity": "sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.10.tgz", + "integrity": "sha512-5jm60P0CU7tom0eNrZ7YrkgBaoLFXzmqB0wVS+4uK8PPGmosSrLNf6rRd50UBvukztawZ7zyA8TxlrKpF5z9jw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3190,11 +3387,12 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "5.3.8", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.8.tgz", - "integrity": "sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.10.tgz", + "integrity": "sha512-2NzVWpYY0tRdfeCJLsgrR89KE3NTWT2wGulhNUxYlRmtRmPwLQwKzhrfVaiNlA9ZpJvbW7cjTVChYKgnkqXj1A==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3202,12 +3400,13 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.8.tgz", - "integrity": "sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.10.tgz", + "integrity": "sha512-HeN7kEvuzO2DmAzLukE9UryiUvejD3tMp9a1D1NJETerIfKobBUCLfviP6QEk500166eD2IATaXM59qgUI+YDA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0", - "@smithy/util-uri-escape": "^4.2.0", + "@smithy/types": "^4.13.0", + "@smithy/util-uri-escape": "^4.2.1", "tslib": "^2.6.2" }, "engines": { @@ -3215,11 +3414,12 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.8.tgz", - "integrity": "sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.10.tgz", + "integrity": "sha512-4Mh18J26+ao1oX5wXJfWlTT+Q1OpDR8ssiC9PDOuEgVBGloqg18Fw7h5Ct8DyT9NBYwJgtJ2nLjKKFU6RP1G1Q==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3227,22 +3427,24 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.8.tgz", - "integrity": "sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.10.tgz", + "integrity": "sha512-0R/+/Il5y8nB/By90o8hy/bWVYptbIfvoTYad0igYQO5RefhNCDmNzqxaMx7K1t/QWo0d6UynqpqN5cCQt1MCg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0" + "@smithy/types": "^4.13.0" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.3.tgz", - "integrity": "sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.5.tgz", + "integrity": "sha512-pHgASxl50rrtOztgQCPmOXFjRW+mCd7ALr/3uXNzRrRoGV5G2+78GOsQ3HlQuBVHCh9o6xqMNvlIKZjWn4Euug==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3250,17 +3452,18 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.3.8", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.8.tgz", - "integrity": "sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==", - "dependencies": { - "@smithy/is-array-buffer": "^4.2.0", - "@smithy/protocol-http": "^5.3.8", - "@smithy/types": "^4.12.0", - "@smithy/util-hex-encoding": "^4.2.0", - "@smithy/util-middleware": "^4.2.8", - "@smithy/util-uri-escape": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.10.tgz", + "integrity": "sha512-Wab3wW8468WqTKIxI+aZe3JYO52/RYT/8sDOdzkUhjnLakLe9qoQqIcfih/qxcF4qWEFoWBszY0mj5uxffaVXA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.1", + "@smithy/protocol-http": "^5.3.10", + "@smithy/types": "^4.13.0", + "@smithy/util-hex-encoding": "^4.2.1", + "@smithy/util-middleware": "^4.2.10", + "@smithy/util-uri-escape": "^4.2.1", + "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" }, "engines": { @@ -3268,16 +3471,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.11.2.tgz", - "integrity": "sha512-SCkGmFak/xC1n7hKRsUr6wOnBTJ3L22Qd4e8H1fQIuKTAjntwgU8lrdMe7uHdiT2mJAOWA/60qaW9tiMu69n1A==", - "dependencies": { - "@smithy/core": "^3.22.1", - "@smithy/middleware-endpoint": "^4.4.13", - "@smithy/middleware-stack": "^4.2.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/types": "^4.12.0", - "@smithy/util-stream": "^4.5.11", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.12.0.tgz", + "integrity": "sha512-R8bQ9K3lCcXyZmBnQqUZJF4ChZmtWT5NLi6x5kgWx5D+/j0KorXcA0YcFg/X5TOgnTCy1tbKc6z2g2y4amFupQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.23.6", + "@smithy/middleware-endpoint": "^4.4.20", + "@smithy/middleware-stack": "^4.2.10", + "@smithy/protocol-http": "^5.3.10", + "@smithy/types": "^4.13.0", + "@smithy/util-stream": "^4.5.15", "tslib": "^2.6.2" }, "engines": { @@ -3285,9 +3489,10 @@ } }, "node_modules/@smithy/types": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.12.0.tgz", - "integrity": "sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.13.0.tgz", + "integrity": "sha512-COuLsZILbbQsdrwKQpkkpyep7lCsByxwj7m0Mg5v66/ZTyenlfBc40/QFQ5chO0YN/PNEH1Bi3fGtfXPnYNeDw==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -3296,12 +3501,13 @@ } }, "node_modules/@smithy/url-parser": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.8.tgz", - "integrity": "sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.10.tgz", + "integrity": "sha512-uypjF7fCDsRk26u3qHmFI/ePL7bxxB9vKkE+2WKEciHhz+4QtbzWiHRVNRJwU3cKhrYDYQE3b0MRFtqfLYdA4A==", + "license": "Apache-2.0", "dependencies": { - "@smithy/querystring-parser": "^4.2.8", - "@smithy/types": "^4.12.0", + "@smithy/querystring-parser": "^4.2.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3309,12 +3515,13 @@ } }, "node_modules/@smithy/util-base64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz", - "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.1.tgz", + "integrity": "sha512-BKGuawX4Doq/bI/uEmg+Zyc36rJKWuin3py89PquXBIBqmbnJwBBsmKhdHfNEp0+A4TDgLmT/3MSKZ1SxHcR6w==", + "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", + "@smithy/util-buffer-from": "^4.2.1", + "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" }, "engines": { @@ -3322,9 +3529,10 @@ } }, "node_modules/@smithy/util-body-length-browser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz", - "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.1.tgz", + "integrity": "sha512-SiJeLiozrAoCrgDBUgsVbmqHmMgg/2bA15AzcbcW+zan7SuyAVHN4xTSbq0GlebAIwlcaX32xacnrG488/J/6g==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -3333,9 +3541,10 @@ } }, "node_modules/@smithy/util-body-length-node": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz", - "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.2.tgz", + "integrity": "sha512-4rHqBvxtJEBvsZcFQSPQqXP2b/yy/YlB66KlcEgcH2WNoOKCKB03DSLzXmOsXjbl8dJ4OEYTn31knhdznwk7zw==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -3344,11 +3553,12 @@ } }, "node_modules/@smithy/util-buffer-from": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz", - "integrity": "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.1.tgz", + "integrity": "sha512-/swhmt1qTiVkaejlmMPPDgZhEaWb/HWMGRBheaxwuVkusp/z+ErJyQxO6kaXumOciZSWlmq6Z5mNylCd33X7Ig==", + "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": "^4.2.0", + "@smithy/is-array-buffer": "^4.2.1", "tslib": "^2.6.2" }, "engines": { @@ -3356,9 +3566,10 @@ } }, "node_modules/@smithy/util-config-provider": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz", - "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.1.tgz", + "integrity": "sha512-462id/00U8JWFw6qBuTSWfN5TxOHvDu4WliI97qOIOnuC/g+NDAknTU8eoGXEPlLkRVgWEr03jJBLV4o2FL8+A==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -3367,13 +3578,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.3.29", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.29.tgz", - "integrity": "sha512-nIGy3DNRmOjaYaaKcQDzmWsro9uxlaqUOhZDHQed9MW/GmkBZPtnU70Pu1+GT9IBmUXwRdDuiyaeiy9Xtpn3+Q==", - "dependencies": { - "@smithy/property-provider": "^4.2.8", - "@smithy/smithy-client": "^4.11.2", - "@smithy/types": "^4.12.0", + "version": "4.3.36", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.36.tgz", + "integrity": "sha512-R0smq7EHQXRVMxkAxtH5akJ/FvgAmNF6bUy/GwY/N20T4GrwjT633NFm0VuRpC+8Bbv8R9A0DoJ9OiZL/M3xew==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.10", + "@smithy/smithy-client": "^4.12.0", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3381,16 +3593,17 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.2.32", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.32.tgz", - "integrity": "sha512-7dtFff6pu5fsjqrVve0YMhrnzJtccCWDacNKOkiZjJ++fmjGExmmSu341x+WU6Oc1IccL7lDuaUj7SfrHpWc5Q==", - "dependencies": { - "@smithy/config-resolver": "^4.4.6", - "@smithy/credential-provider-imds": "^4.2.8", - "@smithy/node-config-provider": "^4.3.8", - "@smithy/property-provider": "^4.2.8", - "@smithy/smithy-client": "^4.11.2", - "@smithy/types": "^4.12.0", + "version": "4.2.39", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.39.tgz", + "integrity": "sha512-otWuoDm35btJV1L8MyHrPl462B07QCdMTktKc7/yM+Psv6KbED/ziXiHnmr7yPHUjfIwE9S8Max0LO24Mo3ZVg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/config-resolver": "^4.4.9", + "@smithy/credential-provider-imds": "^4.2.10", + "@smithy/node-config-provider": "^4.3.10", + "@smithy/property-provider": "^4.2.10", + "@smithy/smithy-client": "^4.12.0", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3398,12 +3611,13 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.8.tgz", - "integrity": "sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.3.1.tgz", + "integrity": "sha512-xyctc4klmjmieQiF9I1wssBWleRV0RhJ2DpO8+8yzi2LO1Z+4IWOZNGZGNj4+hq9kdo+nyfrRLmQTzc16Op2Vg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.8", - "@smithy/types": "^4.12.0", + "@smithy/node-config-provider": "^4.3.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3411,9 +3625,10 @@ } }, "node_modules/@smithy/util-hex-encoding": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz", - "integrity": "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.1.tgz", + "integrity": "sha512-c1hHtkgAWmE35/50gmdKajgGAKV3ePJ7t6UtEmpfCWJmQE9BQAQPz0URUVI89eSkcDqCtzqllxzG28IQoZPvwA==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -3422,11 +3637,12 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.8.tgz", - "integrity": "sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.10.tgz", + "integrity": "sha512-LxaQIWLp4y0r72eA8mwPNQ9va4h5KeLM0I3M/HV9klmFaY2kN766wf5vsTzmaOpNNb7GgXAd9a25P3h8T49PSA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.12.0", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3434,12 +3650,13 @@ } }, "node_modules/@smithy/util-retry": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.8.tgz", - "integrity": "sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.10.tgz", + "integrity": "sha512-HrBzistfpyE5uqTwiyLsFHscgnwB0kgv8vySp7q5kZ0Eltn/tjosaSGGDj/jJ9ys7pWzIP/icE2d+7vMKXLv7A==", + "license": "Apache-2.0", "dependencies": { - "@smithy/service-error-classification": "^4.2.8", - "@smithy/types": "^4.12.0", + "@smithy/service-error-classification": "^4.2.10", + "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "engines": { @@ -3447,17 +3664,18 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.5.11", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.11.tgz", - "integrity": "sha512-lKmZ0S/3Qj2OF5H1+VzvDLb6kRxGzZHq6f3rAsoSu5cTLGsn3v3VQBA8czkNNXlLjoFEtVu3OQT2jEeOtOE2CA==", - "dependencies": { - "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/node-http-handler": "^4.4.9", - "@smithy/types": "^4.12.0", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-buffer-from": "^4.2.0", - "@smithy/util-hex-encoding": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", + "version": "4.5.15", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.15.tgz", + "integrity": "sha512-OlOKnaqnkU9X+6wEkd7mN+WB7orPbCVDauXOj22Q7VtiTkvy7ZdSsOg4QiNAZMgI4OkvNf+/VLUC3VXkxuWJZw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/fetch-http-handler": "^5.3.11", + "@smithy/node-http-handler": "^4.4.12", + "@smithy/types": "^4.13.0", + "@smithy/util-base64": "^4.3.1", + "@smithy/util-buffer-from": "^4.2.1", + "@smithy/util-hex-encoding": "^4.2.1", + "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" }, "engines": { @@ -3465,9 +3683,10 @@ } }, "node_modules/@smithy/util-uri-escape": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz", - "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.1.tgz", + "integrity": "sha512-YmiUDn2eo2IOiWYYvGQkgX5ZkBSiTQu4FlDo5jNPpAxng2t6Sjb6WutnZV9l6VR4eJul1ABmCrnWBC9hKHQa6Q==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -3476,11 +3695,12 @@ } }, "node_modules/@smithy/util-utf8": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", - "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.1.tgz", + "integrity": "sha512-DSIwNaWtmzrNQHv8g7DBGR9mulSit65KSj5ymGEIAknmIN8IpbZefEep10LaMG/P/xquwbmJ1h9ectz8z6mV6g==", + "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-buffer-from": "^4.2.1", "tslib": "^2.6.2" }, "engines": { @@ -3488,9 +3708,10 @@ } }, "node_modules/@smithy/uuid": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz", - "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.1.tgz", + "integrity": "sha512-dSfDCeihDmZlV2oyr0yWPTUfh07suS+R5OB+FZGiv/hHyK3hrFBW5rR1UYjfa57vBsrP9lciFkRPzebaV1Qujw==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -3502,39 +3723,44 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz", "integrity": "sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==", + "license": "MIT", "optional": true }, "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "optional": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "license": "MIT", "engines": { - "node": ">= 6" + "node": ">= 10" } }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "license": "MIT", "optional": true }, "node_modules/@types/chai": { "version": "4.3.20", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/cookiejar": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", "dependencies": { "@types/ms": "*" } @@ -3543,37 +3769,68 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" }, "node_modules/@types/node": { - "version": "24.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", - "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "version": "24.10.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.13.tgz", + "integrity": "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==", + "license": "MIT", "dependencies": { "undici-types": "~7.16.0" } }, + "node_modules/@types/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.4" + } + }, "node_modules/@types/shimmer": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", - "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==" + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", + "license": "MIT" + }, + "node_modules/@types/stream-buffers": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/stream-buffers/-/stream-buffers-3.0.8.tgz", + "integrity": "sha512-J+7VaHKNvlNPJPEJXX/fKa9DZtR/xPMwuIbe+yNOwp1YB+ApUOBv2aUpEoBJEi8nJgbgs1x8e73ttg0r1rSUdw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/superagent": { "version": "4.1.13", "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.13.tgz", "integrity": "sha512-YIGelp3ZyMiH0/A09PMAORO0EBGlF5xIKfDpK74wdYvWUs2o96b5CItJcWPdH409b7SAXIIG6p8NdU/4U2Maww==", "dev": true, + "license": "MIT", "dependencies": { "@types/cookiejar": "*", "@types/node": "*" @@ -3582,21 +3839,24 @@ "node_modules/@types/validator": { "version": "13.15.10", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz", - "integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==" + "integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==", + "license": "MIT" }, "node_modules/@types/yauzl": { "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", "optional": true, "dependencies": { "@types/node": "*" } }, "node_modules/@typespec/ts-http-runtime": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.2.tgz", - "integrity": "sha512-IlqQ/Gv22xUC1r/WQm4StLkYQmaaTsXAhUVsNE0+xiyf0yRFiH5++q78U3bw6bLKDCTmh0uqKB9eG9+Bt75Dkg==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.3.tgz", + "integrity": "sha512-91fp6CAAJSRtH5ja95T1FHSKa8aPW9/Zw6cta81jlZTUw/+Vq8jM/AfF/14h2b71wwR84JUTW/3Y8QPhDAawFA==", + "license": "MIT", "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", @@ -3611,6 +3871,7 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -3619,6 +3880,7 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -3631,6 +3893,7 @@ "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -3642,6 +3905,7 @@ "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", "peerDependencies": { "acorn": "^8" } @@ -3651,6 +3915,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -3659,6 +3924,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/afterward/-/afterward-2.0.0.tgz", "integrity": "sha512-7n9Vkbb8cmMRKKSfe5qgyqX4Yjdaty0QP/+GXYawZK8Vcq+8E5FCmbWbwfCoiBnDoAY/edKLNg2TwgGcwdA+3Q==", + "license": "MIT", "dependencies": { "define-error": "~1.0.0" } @@ -3667,6 +3933,7 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", "engines": { "node": ">= 14" } @@ -3675,6 +3942,7 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", "optional": true, "dependencies": { "humanize-ms": "^1.2.1" @@ -3688,6 +3956,7 @@ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "devOptional": true, + "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -3697,10 +3966,11 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3717,6 +3987,7 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, + "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } @@ -3726,6 +3997,7 @@ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3735,6 +4007,7 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -3743,6 +4016,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -3751,6 +4025,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -3766,6 +4041,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3777,13 +4053,15 @@ "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" }, "node_modules/append-transform": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, + "license": "MIT", "dependencies": { "default-require-extensions": "^3.0.0" }, @@ -3795,19 +4073,22 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "license": "ISC", "optional": true }, "node_modules/archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/are-we-there-yet": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", "deprecated": "This package is no longer supported.", + "license": "ISC", "optional": true, "dependencies": { "delegates": "^1.0.0", @@ -3821,6 +4102,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", "optional": true, "dependencies": { "inherits": "^2.0.3", @@ -3835,6 +4117,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", "optional": true, "dependencies": { "safe-buffer": "~5.2.0" @@ -3843,12 +4126,14 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "license": "MIT", "engines": { "node": ">=6" } @@ -3858,6 +4143,7 @@ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" @@ -3872,13 +4158,15 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" }, "node_modules/array-includes": { "version": "3.1.9", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", @@ -3901,6 +4189,7 @@ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", @@ -3920,13 +4209,15 @@ "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": "~2.1.0" } @@ -3935,6 +4226,7 @@ "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "license": "MIT", "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", @@ -3947,6 +4239,7 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8" } @@ -3956,6 +4249,7 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" } @@ -3964,6 +4258,7 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.0.1" @@ -3975,13 +4270,15 @@ "node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -3989,13 +4286,15 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true, + "license": "ISC", "engines": { "node": ">= 4.0.0" } @@ -4004,6 +4303,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", "engines": { "node": ">=8.0.0" } @@ -4013,6 +4313,7 @@ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -4028,6 +4329,7 @@ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "*" } @@ -4036,23 +4338,40 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/axios": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, + "node_modules/b4a": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz", + "integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, "node_modules/babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^1.1.3", "esutils": "^2.0.2", @@ -4064,6 +4383,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -4073,6 +4393,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -4082,6 +4403,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", @@ -4098,6 +4420,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -4106,13 +4429,15 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/babel-code-frame/node_modules/strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, @@ -4125,14 +4450,111 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/bare-fs": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.4.tgz", + "integrity": "sha512-POK4oplfA7P7gqvetNmCs4CNtm9fNsx+IAh7jH7GgU0OJdge2rso0R20TNWVq6VoWcCvsTdlNDaleLHGaKx8CA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" + }, + "engines": { + "bare": ">=1.16.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-os": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz", + "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "bare": ">=1.14.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-stream": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.8.0.tgz", + "integrity": "sha512-reUN0M2sHRqCdG4lUK3Fw8w98eeUIZHL5c3H7Mbhk2yVBL+oofgaIp0ieLfD5QXwPCypBpmEEKU2WZKzbAk8GA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "streamx": "^2.21.0", + "teex": "^1.0.1" + }, + "peerDependencies": { + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/bare-url": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.3.2.tgz", + "integrity": "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-path": "^3.0.0" + } }, "node_modules/base64-js": { "version": "1.5.1", @@ -4151,21 +4573,27 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.3.tgz", - "integrity": "sha512-8QdH6czo+G7uBsNo0GiUfouPN1lRzKdJTGnKXwe12gkFbnnOUaUKGN55dMkfy+mnxmvjwl9zcI4VncczcVXDhA==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", "dev": true, + "license": "Apache-2.0", "bin": { - "baseline-browser-mapping": "dist/cli.js" + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/basic-ftp": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", - "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.0.tgz", + "integrity": "sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==", + "license": "MIT", "optional": true, "engines": { "node": ">=10.0.0" @@ -4176,15 +4604,24 @@ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "tweetnacl": "^0.14.3" } }, - "node_modules/bdd-lazy-var": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/bdd-lazy-var/-/bdd-lazy-var-2.6.1.tgz", - "integrity": "sha512-X3ADwcFji/IHIrYJhTTpaiWhoOx4pl4whdAx1dmvdeUPsMUb7fVYFvf/Q33VEAEAVkEwi5rgNSZ0Y9oOVeQV+A==", + "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "license": "Unlicense" + }, + "node_modules/bdd-lazy-var": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/bdd-lazy-var/-/bdd-lazy-var-2.6.1.tgz", + "integrity": "sha512-X3ADwcFji/IHIrYJhTTpaiWhoOx4pl4whdAx1dmvdeUPsMUb7fVYFvf/Q33VEAEAVkEwi5rgNSZ0Y9oOVeQV+A==", "dev": true, + "license": "MIT", "peerDependencies": { "jasmine": ">=2", "jasmine-core": ">=2", @@ -4210,6 +4647,7 @@ "version": "9.3.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", "engines": { "node": "*" } @@ -4219,6 +4657,7 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -4230,6 +4669,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", "dependencies": { "file-uri-to-path": "1.0.0" } @@ -4238,6 +4678,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -4248,6 +4689,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -4261,6 +4703,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } @@ -4269,17 +4712,20 @@ "version": "2.11.0", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", "integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==" + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", + "license": "MIT" }, "node_modules/body-parser": { "version": "1.20.4", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "license": "MIT", "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", @@ -4304,21 +4750,25 @@ "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/bowser": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.13.1.tgz", - "integrity": "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==" + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", + "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "devOptional": true, + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz", + "integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==", + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/braces": { @@ -4326,6 +4776,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -4336,13 +4787,15 @@ "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" }, "node_modules/brotli": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", "dev": true, + "license": "MIT", "dependencies": { "base64-js": "^1.1.2" } @@ -4351,7 +4804,8 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/browserslist": { "version": "4.28.1", @@ -4372,6 +4826,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -4404,6 +4859,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -4413,6 +4869,7 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", "optional": true, "engines": { "node": "*" @@ -4421,17 +4878,20 @@ "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" }, "node_modules/bundle-name": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "license": "MIT", "dependencies": { "run-applescript": "^7.0.0" }, @@ -4453,18 +4913,11 @@ "node": ">=10.16.0" } }, - "node_modules/byline": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", - "integrity": "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -4473,6 +4926,7 @@ "version": "15.3.0", "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", "optional": true, "dependencies": { "@npmcli/fs": "^1.0.0", @@ -4498,11 +4952,22 @@ "node": ">= 10" } }, + "node_modules/cacache/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=10" + } + }, "node_modules/cacache/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", "optional": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -4523,6 +4988,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -4531,10 +4997,24 @@ "node": ">=10" } }, + "node_modules/cacache/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/cacache/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", "optional": true, "bin": { "mkdirp": "bin/cmd.js" @@ -4547,6 +5027,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", "optional": true, "dependencies": { "aggregate-error": "^3.0.0" @@ -4558,11 +5039,36 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cacache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, + "license": "MIT", "dependencies": { "hasha": "^5.0.0", "make-dir": "^3.0.0", @@ -4578,6 +5084,7 @@ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, + "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", @@ -4595,6 +5102,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -4607,6 +5115,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" @@ -4623,6 +5132,7 @@ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha512-UJiE1otjXPF5/x+T3zTnSFiTOEmJoGTD9HmBoxnCUwho61a2eSNn/VwtwuIBDAo2SEOv1AJ7ARI5gCmohFLu/g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^0.2.0" }, @@ -4635,6 +5145,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", "integrity": "sha512-Zv4Dns9IbXXmPkgRRUjAaJQgfN4xX5p6+RQFhWUqscdvvK2xK/ZL8b3IXIJsj+4sD+f24NwnWy2BY8AJ82JB0A==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -4644,6 +5155,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4653,14 +5165,15 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001759", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", - "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", + "version": "1.0.30001774", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001774.tgz", + "integrity": "sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==", "dev": true, "funding": [ { @@ -4675,12 +5188,14 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/capture-stack-trace": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.2.tgz", "integrity": "sha512-X/WM2UQs6VMHUtjUDnZTRI+i1crWteJySFzr9UpGoQa4WQffXVTTXuekjl7TjZRlcF2XfjgITT0HxZ9RnxeT0w==", + "license": "MIT", "engines": { "node": ">=0.10.0" }, @@ -4692,13 +5207,15 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/chai": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", "dev": true, + "license": "MIT", "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", @@ -4715,6 +5232,7 @@ "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.2.tgz", "integrity": "sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==", "dev": true, + "license": "WTFPL", "dependencies": { "check-error": "^1.0.2" }, @@ -4727,6 +5245,7 @@ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, + "license": "MIT", "dependencies": { "get-func-name": "^2.0.2" }, @@ -4739,6 +5258,7 @@ "resolved": "https://registry.npmjs.org/chai-http/-/chai-http-4.4.0.tgz", "integrity": "sha512-uswN3rZpawlRaa5NiDUHcDZ3v2dw5QgLyAwnQ2tnVNuP7CwIsOFuYJ0xR1WiR7ymD4roBnJIzOUep7w9jQMFJA==", "dev": true, + "license": "MIT", "dependencies": { "@types/chai": "4", "@types/superagent": "4.1.13", @@ -4757,6 +5277,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4772,6 +5293,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "license": "MIT", "dependencies": { "chalk": "^4.1.2" }, @@ -4786,13 +5308,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.0.0.tgz", "integrity": "sha512-xVgPpulCooDjY6zH4m9YW3jbkaBe3FKIAvF5sj5t7aBNsVl2ljIE+xwJ4iNgiDZHFQvNIpjdKdVOQvvk5ZfxbQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/charenc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": "*" } @@ -4802,15 +5326,17 @@ "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0.0" } }, "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 16" } @@ -4820,6 +5346,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4844,6 +5371,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -4852,27 +5380,25 @@ } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "optional": true, - "engines": { - "node": ">=10" - } + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" }, "node_modules/chromedriver": { - "version": "143.0.0", - "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-143.0.0.tgz", - "integrity": "sha512-zsDjk9nLeQsMcnFXP4huqCOqneIdox3ECIR4laBOH7sog1+K2rTgrK60ogSeYaHUnx9OTAMFkwJL29ekVgVQgw==", + "version": "145.0.6", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-145.0.6.tgz", + "integrity": "sha512-qobFdfjk7G7U9GKB6RYGBuqQ8L0QG1M30p90sNIWLKdpeobhsedfBhVxRqT4m/nWAtM0PhNb9GDD9qzDwSSGlA==", "hasInstallScript": true, + "license": "Apache-2.0", "optional": true, "dependencies": { "@testim/chrome-version": "^1.1.4", - "axios": "^1.12.0", + "axios": "^1.13.5", "compare-versions": "^6.1.0", "extract-zip": "^2.0.1", "proxy-agent": "^6.4.0", - "proxy-from-env": "^1.1.0", + "proxy-from-env": "^2.0.0", "tcp-port-used": "^1.0.2" }, "bin": { @@ -4882,23 +5408,33 @@ "node": ">=20" } }, + "node_modules/chromedriver/node_modules/proxy-from-env": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.0.0.tgz", + "integrity": "sha512-h2lD3OfRraP3R51rNFKIE8nX+qoLr1mE74X91YhVxtDbt+OD6ntoNZv56+JgI4RCdtwQ5eexsOk1KdOQDfvPCQ==", + "license": "MIT", + "optional": true + }, "node_modules/circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "deprecated": "CircularJSON is in maintenance only, flatted is its successor.", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cjs-module-lexer": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==" + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "license": "MIT" }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "devOptional": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4908,6 +5444,7 @@ "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", "dev": true, + "license": "ISC", "dependencies": { "d": "^1.0.1", "es5-ext": "^0.10.64", @@ -4924,6 +5461,7 @@ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", "dev": true, + "license": "MIT", "dependencies": { "restore-cursor": "^2.0.0" }, @@ -4936,6 +5474,7 @@ "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", "dev": true, + "license": "MIT", "dependencies": { "string-width": "^4.2.3" }, @@ -4948,6 +5487,7 @@ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, + "license": "MIT", "dependencies": { "string-width": "^4.2.0" }, @@ -4962,12 +5502,14 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -4981,6 +5523,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -4991,12 +5534,14 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, "node_modules/color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", "optional": true, "bin": { "color-support": "bin.js" @@ -5007,6 +5552,7 @@ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.1.90" } @@ -5015,6 +5561,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -5026,6 +5573,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "license": "MIT", "dependencies": { "array-back": "^3.1.0", "find-replace": "^3.0.0", @@ -5040,6 +5588,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.3.tgz", "integrity": "sha512-PqMLy5+YGwhMh1wS04mVG44oqDsgyLRSKJBdOo1bnYhMKBW65gZF1dRp2OZRhiTjgUHljy99qkO7bsctLaw35Q==", + "license": "MIT", "dependencies": { "array-back": "^6.2.2", "chalk-template": "^0.4.0", @@ -5054,6 +5603,7 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "license": "MIT", "engines": { "node": ">=12.17" } @@ -5062,6 +5612,7 @@ "version": "7.3.0", "resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz", "integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==", + "license": "MIT", "engines": { "node": ">=12.17" } @@ -5071,6 +5622,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" } @@ -5079,12 +5631,14 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/compare-versions": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", + "license": "MIT", "optional": true }, "node_modules/component-emitter": { @@ -5092,16 +5646,11 @@ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "devOptional": true - }, "node_modules/concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", @@ -5109,6 +5658,7 @@ "engines": [ "node >= 0.8" ], + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -5119,12 +5669,14 @@ "node_modules/concat-stream/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" }, "node_modules/concat-stream/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5138,12 +5690,14 @@ "node_modules/concat-stream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" }, "node_modules/concat-stream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -5152,6 +5706,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/concurrent-queue/-/concurrent-queue-7.0.2.tgz", "integrity": "sha512-icXDqc0JBdcQ3ubXiXcqVhuFeRrec39zVD2X5z7FKwwj0pImnfLWtAhGyX4CcBDD+YoqLesClOeRss+pZnm6/Q==", + "license": "MIT", "dependencies": { "afterward": "~2.0.0", "define-error": "~1.0.0", @@ -5167,6 +5722,7 @@ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, + "license": "MIT", "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" @@ -5176,12 +5732,14 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", "optional": true }, "node_modules/contains-path": { @@ -5189,6 +5747,7 @@ "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", "integrity": "sha512-OKZnPGeMQy2RPaUIBPFFd71iNf4791H12MCRuVQDnzGRwCYNYmTDy5pdafo2SLAcEMKzTOQnLWG4QdcjeJUMEg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5197,6 +5756,7 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -5208,6 +5768,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5216,12 +5777,14 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cookie": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5230,6 +5793,7 @@ "version": "1.4.7", "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", "dependencies": { "cookie": "0.7.2", "cookie-signature": "1.0.6" @@ -5241,23 +5805,27 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/cookiejar": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -5270,6 +5838,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5284,6 +5853,7 @@ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": "*" } @@ -5292,13 +5862,15 @@ "version": "4.16.3", "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.16.3.tgz", "integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/d": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", "dev": true, + "license": "ISC", "dependencies": { "es5-ext": "^0.10.64", "type": "^2.7.2" @@ -5320,6 +5892,7 @@ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" }, @@ -5331,6 +5904,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "license": "MIT", "optional": true, "engines": { "node": ">= 14" @@ -5341,6 +5915,7 @@ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -5358,6 +5933,7 @@ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -5375,6 +5951,7 @@ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -5391,6 +5968,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -5400,6 +5978,7 @@ "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", "integrity": "sha512-gV/pe1YIaKNgLYnd1g9VNW80tcb7oV5qvNUxG7NM8rbDpnl6RGunzlAtlGSb0wEs3nesu2vHNiX9TSsZ+Y+RjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5409,6 +5988,7 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5417,6 +5997,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" }, @@ -5432,6 +6013,7 @@ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -5440,6 +6022,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", "engines": { "node": ">=4.0.0" } @@ -5448,12 +6031,14 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "devOptional": true + "devOptional": true, + "license": "MIT" }, "node_modules/default-browser": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", - "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "license": "MIT", "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" @@ -5469,6 +6054,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "license": "MIT", "engines": { "node": ">=18" }, @@ -5481,6 +6067,7 @@ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", "dev": true, + "license": "MIT", "dependencies": { "strip-bom": "^4.0.0" }, @@ -5496,6 +6083,7 @@ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -5512,6 +6100,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-error/-/define-error-1.0.0.tgz", "integrity": "sha512-HLdUb9mNENZ/tjnZGlITfOnx7wSM7a6e+WEDyhKSrsN/g5dJUS6kepG6qJApRLAdjRofQ2W8R3yrtI6GeyGGVg==", + "license": "MIT", "dependencies": { "capture-stack-trace": "~1.0.0" } @@ -5520,6 +6109,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -5532,6 +6122,7 @@ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -5548,6 +6139,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "license": "MIT", "optional": true, "dependencies": { "ast-types": "^0.13.4", @@ -5563,6 +6155,7 @@ "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz", "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==", "dev": true, + "license": "ISC", "dependencies": { "find-root": "^1.0.0", "glob": "^7.0.5", @@ -5576,8 +6169,9 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5597,12 +6191,14 @@ "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -5611,12 +6207,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", "optional": true }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", "engines": { "node": ">=0.10" } @@ -5625,6 +6223,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -5634,6 +6233,7 @@ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" @@ -5643,6 +6243,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -5652,6 +6253,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", "engines": { "node": ">=8" } @@ -5660,42 +6262,54 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/dezalgo": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "license": "ISC", "dependencies": { "asap": "^2.0.0", "wrappy": "1" } }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha512-lsGyRuYr4/PIB0txi+Fy2xOMI2dGaTguCaotzFGkVZuKR5usKfcRWIFKNM3QNrU7hh/+w2bwTW+ZeXPK5l8uVg==", "dev": true, "dependencies": { - "esutils": "^2.0.2" + "esutils": "^2.0.2", + "isarray": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, + "node_modules/doctrine/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, "node_modules/dotenv": { "version": "16.6.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -5704,14 +6318,16 @@ } }, "node_modules/dottie": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", - "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.7.tgz", + "integrity": "sha512-7lAK2A0b3zZr3UC5aE69CPdCFR4RHW1o2Dr74TqFykxkUCBXSRJum/yPc7g8zRHJqWKomPLHwFLLoUnn8PXXRg==", + "license": "MIT" }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -5725,6 +6341,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", + "license": "MIT", "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", @@ -5736,6 +6353,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -5749,6 +6367,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } @@ -5756,13 +6375,15 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dev": true, + "license": "MIT", "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -5772,6 +6393,7 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" } @@ -5781,6 +6403,7 @@ "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", "dev": true, + "license": "MIT", "dependencies": { "@one-ini/wasm": "0.1.1", "commander": "^10.0.0", @@ -5794,48 +6417,27 @@ "node": ">=14" } }, - "node_modules/editorconfig/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/editorconfig/node_modules/commander": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" } }, - "node_modules/editorconfig/node_modules/minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", "dependencies": { "jake": "^10.8.5" }, @@ -5847,15 +6449,17 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.266", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz", - "integrity": "sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==", - "dev": true + "version": "1.5.302", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz", + "integrity": "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==", + "dev": true, + "license": "ISC" }, "node_modules/elliptic": { "version": "6.6.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "license": "MIT", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -5869,12 +6473,14 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -5883,6 +6489,7 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", "dependencies": { "iconv-lite": "^0.6.2" } @@ -5891,6 +6498,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -5902,6 +6510,7 @@ "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", "dependencies": { "once": "^1.4.0" } @@ -5910,6 +6519,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -5918,6 +6528,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", "optional": true, "engines": { "node": ">=6" @@ -5927,6 +6538,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", "optional": true }, "node_modules/error-ex": { @@ -5934,15 +6546,17 @@ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es-abstract": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", - "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", @@ -6010,6 +6624,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -6018,6 +6633,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -6026,6 +6642,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -6037,6 +6654,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -6052,6 +6670,7 @@ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", @@ -6070,6 +6689,7 @@ "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "dev": true, "hasInstallScript": true, + "license": "ISC", "dependencies": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", @@ -6084,13 +6704,15 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", "dev": true, + "license": "MIT", "dependencies": { "d": "1", "es5-ext": "^0.10.35", @@ -6102,6 +6724,7 @@ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", "dev": true, + "license": "ISC", "dependencies": { "d": "^1.0.2", "ext": "^1.7.0" @@ -6115,6 +6738,7 @@ "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "dev": true, + "license": "ISC", "dependencies": { "d": "1", "es5-ext": "^0.10.46", @@ -6126,6 +6750,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -6133,13 +6758,15 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6151,6 +6778,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", "optional": true, "dependencies": { "esprima": "^4.0.1", @@ -6173,6 +6801,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -6233,6 +6862,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=0.10.0" }, @@ -6240,11 +6870,37 @@ "eslint": ">=5.16.0" } }, + "node_modules/eslint-config-standard": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz", + "integrity": "sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=5.0.0", + "eslint-plugin-import": ">=2.13.0", + "eslint-plugin-node": ">=7.0.0", + "eslint-plugin-promise": ">=4.0.0", + "eslint-plugin-standard": ">=4.0.0" + } + }, + "node_modules/eslint-config-standard-jsx": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-6.0.2.tgz", + "integrity": "sha512-D+YWAoXw+2GIdbMBRAzWwr1ZtvnSf4n4yL0gKGg7ShUOGXkSOLerI17K4F6LdQMJPNMoWYqepzQD/fKY+tXNSg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=5.0.0", + "eslint-plugin-react": ">=7.11.1" + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -6256,6 +6912,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -6264,13 +6921,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/eslint-module-utils": { "version": "2.12.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -6288,6 +6947,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -6296,13 +6956,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/eslint-plugin-es": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.1.tgz", "integrity": "sha512-5fa/gR2yR3NxQf+UXkeLeP8FBBl6tSgdrAz1+cF84v1FMM4twGwQoqTnn+QxFLcPOrF4pdKEJKDB/q9GoyJrCA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-utils": "^1.4.2", "regexpp": "^2.0.1" @@ -6314,11 +6976,37 @@ "eslint": ">=4.19.1" } }, + "node_modules/eslint-plugin-import": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", + "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "contains-path": "^0.1.0", + "debug": "^2.6.8", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.2.0", + "has": "^1.0.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0", + "resolve": "^1.6.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "2.x - 5.x" + } + }, "node_modules/eslint-plugin-node": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-7.0.1.tgz", "integrity": "sha512-lfVw3TEqThwq0j2Ba/Ckn2ABdwmL5dkOgAux1rvOk6CO7A6yGyPI2+zIxN6FyNkp1X1X/BSvKOceD6mBWSj4Yw==", "dev": true, + "license": "MIT", "dependencies": { "eslint-plugin-es": "^1.3.1", "eslint-utils": "^1.3.1", @@ -6339,6 +7027,7 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -6348,6 +7037,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -6357,10 +7047,44 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz", "integrity": "sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==", "dev": true, + "license": "ISC", "engines": { "node": ">=6" } }, + "node_modules/eslint-plugin-react": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz", + "integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.0.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.0.1", + "prop-types": "^15.6.2" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/eslint-plugin-standard": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.2.tgz", @@ -6380,6 +7104,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "peerDependencies": { "eslint": ">=5.0.0" } @@ -6389,6 +7114,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -6405,6 +7131,7 @@ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^1.1.0" }, @@ -6417,6 +7144,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } @@ -6426,6 +7154,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -6438,6 +7167,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -6454,13 +7184,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/esniff": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", "dev": true, + "license": "ISC", "dependencies": { "d": "^1.0.1", "es5-ext": "^0.10.62", @@ -6476,6 +7208,7 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", @@ -6489,10 +7222,11 @@ } }, "node_modules/espree/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -6505,6 +7239,7 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "devOptional": true, + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -6514,10 +7249,11 @@ } }, "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -6530,6 +7266,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -6542,6 +7279,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "devOptional": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -6551,6 +7289,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "devOptional": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -6559,6 +7298,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -6568,15 +7308,26 @@ "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", "dev": true, + "license": "MIT", "dependencies": { "d": "1", "es5-ext": "~0.10.14" } }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, "node_modules/eventuate": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eventuate/-/eventuate-4.0.0.tgz", "integrity": "sha512-SysKo5/rgqCaXlO4H4DE62JXCFtDpdm+boWOzaeaYph3Xejy04Cc4/E2HDPnOES0MFb643WgKRlx09W2iVAIBw==", + "license": "MIT", "dependencies": { "define-error": "~1.0.0", "object-assign": "~3.0.0", @@ -6587,6 +7338,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6595,6 +7347,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "license": "MIT", "dependencies": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", @@ -6612,6 +7365,7 @@ "version": "6.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "license": "MIT", "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -6627,6 +7381,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", "engines": { "node": ">=4" } @@ -6635,6 +7390,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -6643,6 +7399,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", "dependencies": { "shebang-regex": "^1.0.0" }, @@ -6654,6 +7411,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6662,6 +7420,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -6673,6 +7432,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", "engines": { "node": ">=6" } @@ -6681,6 +7441,7 @@ "version": "4.22.1", "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -6726,6 +7487,7 @@ "version": "1.18.2", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz", "integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==", + "license": "MIT", "dependencies": { "cookie": "0.7.2", "cookie-signature": "1.0.7", @@ -6743,13 +7505,15 @@ "node_modules/express-session/node_modules/cookie-signature": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" }, "node_modules/ext": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", "dev": true, + "license": "ISC", "dependencies": { "type": "^2.7.2" } @@ -6757,13 +7521,15 @@ "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" }, "node_modules/external-editor": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, + "license": "MIT", "dependencies": { "chardet": "^0.4.0", "iconv-lite": "^0.4.17", @@ -6777,12 +7543,14 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", "integrity": "sha512-j/Toj7f1z98Hh2cYo2BVr85EpIRWqUi7rtRSGxh/cqUjqrnJe9l9UE7IUGd2vQ2p+kSHLkSzObQPZPLUC6TQwg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", "optional": true, "dependencies": { "debug": "^4.1.1", @@ -6803,6 +7571,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "optional": true, "dependencies": { "ms": "^2.1.3" @@ -6820,6 +7589,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", "optional": true, "dependencies": { "pump": "^3.0.0" @@ -6835,6 +7605,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", "optional": true }, "node_modules/extsprintf": { @@ -6844,44 +7615,69 @@ "dev": true, "engines": [ "node >=0.6.0" - ] + ], + "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/fast-xml-builder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.0.0.tgz", + "integrity": "sha512-fpZuDogrAgnyt9oDDz+5DBz0zgPdPZz6D4IR7iESxRXElrlGTRkHJ9eEt+SACRJwT0FNFrt71DFQIUFBJfX/uQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" }, "node_modules/fast-xml-parser": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.4.tgz", - "integrity": "sha512-EFd6afGmXlCx8H8WTZHhAoDaWaGyuIBoZJ2mknrNxug+aZKjkp0a0dlars9Izl+jF+7Gu1/5f/2h68cQpe0IiA==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.4.1.tgz", + "integrity": "sha512-BQ30U1mKkvXQXXkAGcuyUA/GA26oEB7NzOtsxCDtyu62sjGw5QraKFhx2Em3WQNjPw9PG6MQ9yuIIgkSDfGu5A==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" } ], + "license": "MIT", "dependencies": { - "strnum": "^2.1.0" + "fast-xml-builder": "^1.0.0", + "strnum": "^2.1.2" }, "bin": { "fxparser": "src/cli/cli.js" @@ -6891,6 +7687,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", "optional": true, "dependencies": { "pend": "~1.2.0" @@ -6910,6 +7707,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -6923,6 +7721,7 @@ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -6935,6 +7734,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -6944,6 +7744,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -6956,6 +7757,7 @@ "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6963,33 +7765,19 @@ "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" }, "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.5.tgz", + "integrity": "sha512-ct/ckWBV/9Dg3MlvCXsLcSUyoWwv9mCKqlhLNB2DAuXR/NZolSXlQqP5dyy6guWlPXBhodZyZ5lGPQcbQDxrEQ==", + "license": "Apache-2.0", "dependencies": { - "brace-expansion": "^2.0.1" + "minimatch": "^10.2.1" }, "engines": { - "node": ">=10" + "node": "20 || >=22" } }, "node_modules/filesize": { @@ -6997,6 +7785,7 @@ "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.4.tgz", "integrity": "sha512-ryBwPIIeErmxgPnm6cbESAzXjuEFubs+yKYLBZvg3CaiNcmkJChoOGcBSrZ6IwkMwPABwPpVXE6IlNdGJJrvEg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">= 10.4.0" } @@ -7006,6 +7795,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -7014,16 +7804,17 @@ } }, "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "statuses": "2.0.1", + "statuses": "~2.0.2", "unpipe": "~1.0.0" }, "engines": { @@ -7035,6 +7826,7 @@ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, + "license": "MIT", "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -7051,6 +7843,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "license": "MIT", "dependencies": { "array-back": "^3.0.1" }, @@ -7062,13 +7855,15 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -7085,6 +7880,7 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, + "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } @@ -7094,6 +7890,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -7106,7 +7903,8 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/follow-redirects": { "version": "1.15.11", @@ -7118,6 +7916,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -7132,6 +7931,7 @@ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.2.7" }, @@ -7147,6 +7947,7 @@ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^3.0.2" @@ -7160,6 +7961,7 @@ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "*" } @@ -7168,6 +7970,7 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -7183,6 +7986,7 @@ "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", "dependencies": { "fetch-blob": "^3.1.2" }, @@ -7194,6 +7998,7 @@ "version": "3.5.4", "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", + "license": "MIT", "dependencies": { "@paralleldrive/cuid2": "^2.2.2", "dezalgo": "^1.0.4", @@ -7210,6 +8015,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -7218,6 +8024,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -7225,12 +8032,14 @@ "node_modules/forwarded-parse": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", - "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==" + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "license": "MIT" }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -7253,18 +8062,21 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" }, "node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -7280,6 +8092,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -7288,6 +8101,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", "optional": true, "dependencies": { "minipass": "^3.0.0" @@ -7296,19 +8110,41 @@ "node": ">= 8" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "devOptional": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, "os": [ "darwin" ], @@ -7332,6 +8168,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7341,6 +8178,7 @@ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -7360,13 +8198,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7376,6 +8216,7 @@ "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", "deprecated": "This package is no longer supported.", + "license": "ISC", "optional": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", @@ -7395,6 +8236,7 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "license": "Apache-2.0", "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", @@ -7405,99 +8247,38 @@ "node": ">=18" } }, - "node_modules/gaxios/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/gaxios/node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/gaxios/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/gaxios/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/gaxios/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "node_modules/gaxios/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 12" } }, - "node_modules/gaxios/node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "node_modules/gaxios/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/gaxios/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "engines": { - "node": ">=14" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, "node_modules/gcp-metadata": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", @@ -7511,6 +8292,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "license": "MIT", "dependencies": { "is-property": "^1.0.2" } @@ -7520,6 +8302,7 @@ "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -7529,6 +8312,7 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -7537,6 +8321,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -7546,6 +8331,7 @@ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -7554,6 +8340,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", @@ -7578,6 +8365,7 @@ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0.0" } @@ -7586,6 +8374,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" @@ -7599,6 +8388,7 @@ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -7607,6 +8397,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "license": "MIT", "dependencies": { "pump": "^3.0.0" }, @@ -7619,6 +8410,7 @@ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -7635,6 +8427,7 @@ "version": "6.0.5", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", + "license": "MIT", "optional": true, "dependencies": { "basic-ftp": "^5.0.2", @@ -7649,6 +8442,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "optional": true, "dependencies": { "ms": "^2.1.3" @@ -7666,6 +8460,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", "optional": true }, "node_modules/getpass": { @@ -7673,6 +8468,7 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" } @@ -7680,14 +8476,16 @@ "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" }, "node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7707,6 +8505,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -7714,32 +8513,12 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/global-agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "boolean": "^3.0.1", "es6-error": "^4.1.1", @@ -7757,6 +8536,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -7769,6 +8549,7 @@ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -7784,6 +8565,7 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz", "integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==", + "license": "Apache-2.0", "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", @@ -7801,6 +8583,7 @@ "version": "5.0.6", "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-5.0.6.tgz", "integrity": "sha512-1kGbqVQBZPAAu4+/R1XxPQKP0ydbNYoLAr4l0ZO2bMV0kLyLW4I1gAk++qBLWt7DPORTzmWRMsCZe86gDjShJA==", + "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.12.6", "@grpc/proto-loader": "^0.8.0", @@ -7818,107 +8601,38 @@ "node": ">=18" } }, - "node_modules/google-gax/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/google-gax/node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/google-gax/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/google-gax/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/google-gax/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/google-gax/node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "node_modules/google-gax/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", "engines": { - "node": ">= 6" + "node": ">= 12" } }, - "node_modules/google-gax/node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "node_modules/google-gax/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/google-gax/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "engines": { - "node": ">=14" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, "node_modules/google-logging-utils": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", "engines": { "node": ">=14" } @@ -7927,6 +8641,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7938,12 +8653,14 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "devOptional": true + "devOptional": true, + "license": "ISC" }, "node_modules/gtoken": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "license": "MIT", "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" @@ -7957,6 +8674,7 @@ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", @@ -7978,6 +8696,7 @@ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", "dev": true, + "license": "ISC", "engines": { "node": ">=4" } @@ -7988,6 +8707,7 @@ "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "deprecated": "this library is no longer supported", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" @@ -8001,6 +8721,7 @@ "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -8010,6 +8731,7 @@ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, @@ -8022,6 +8744,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8031,6 +8754,7 @@ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -8042,6 +8766,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -8051,6 +8776,7 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -8063,6 +8789,7 @@ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, + "license": "MIT", "dependencies": { "dunder-proto": "^1.0.0" }, @@ -8077,6 +8804,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -8088,6 +8816,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -8102,12 +8831,14 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", "optional": true }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -8118,6 +8849,7 @@ "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, + "license": "MIT", "dependencies": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" @@ -8134,6 +8866,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -8145,6 +8878,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -8157,6 +8891,7 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, + "license": "MIT", "bin": { "he": "bin/he" } @@ -8165,6 +8900,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==", + "license": "MIT", "engines": { "node": ">=16.0.0" } @@ -8173,6 +8909,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "license": "MIT", "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -8183,24 +8920,37 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "dev": true, + "license": "ISC" + }, + "node_modules/hpagent": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", + "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", + "license": "MIT", + "engines": { + "node": ">=14" + } }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/http-cache-semantics": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause", "optional": true }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", @@ -8216,18 +8966,11 @@ "url": "https://opencollective.com/express" } }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -8240,6 +8983,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -8255,23 +8999,26 @@ "node_modules/http-proxy-agent/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/http-reasons": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/http-reasons/-/http-reasons-0.1.0.tgz", "integrity": "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz", + "integrity": "sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==", "dev": true, + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^2.0.2", - "sshpk": "^1.14.1" + "sshpk": "^1.18.0" }, "engines": { "node": ">=0.10" @@ -8307,6 +9054,7 @@ "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-1.1.1.tgz", "integrity": "sha512-uhSZLPPD2VXXOSN8Cni3kIsoFHaU2pT/nySEU/fHr/ePbqHYr0jeiQRmUKLEirC09SFPsdMoA7LU7UXMd/w0Kw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6.15.1" } @@ -8315,6 +9063,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", "dependencies": { "agent-base": "^7.1.2", "debug": "4" @@ -8327,6 +9076,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -8342,12 +9092,14 @@ "node_modules/https-proxy-agent/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", "optional": true, "dependencies": { "ms": "^2.0.0" @@ -8357,6 +9109,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -8381,13 +9134,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -8396,13 +9151,15 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -8418,6 +9175,7 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", "dependencies": { "acorn": "^8.14.0", "acorn-import-attributes": "^1.9.5", @@ -8426,9 +9184,10 @@ } }, "node_modules/import-in-the-middle/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -8441,6 +9200,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "devOptional": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -8450,6 +9210,7 @@ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "devOptional": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8458,6 +9219,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", "optional": true }, "node_modules/inflection": { @@ -8466,7 +9228,8 @@ "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", "engines": [ "node >= 0.4.0" - ] + ], + "license": "MIT" }, "node_modules/inflight": { "version": "1.0.6", @@ -8474,6 +9237,7 @@ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "devOptional": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -8482,12 +9246,14 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ini": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "license": "ISC", "engines": { "node": ">=10" } @@ -8497,6 +9263,7 @@ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-escapes": "^3.0.0", "chalk": "^2.0.0", @@ -8521,6 +9288,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -8530,6 +9298,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -8542,6 +9311,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -8556,6 +9326,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } @@ -8564,13 +9335,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/inquirer/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -8580,6 +9353,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -8589,6 +9363,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -8598,6 +9373,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, + "license": "MIT", "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -8611,6 +9387,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^3.0.0" }, @@ -8623,6 +9400,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -8635,6 +9413,7 @@ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", @@ -8648,7 +9427,7 @@ "version": "10.1.0", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", - "optional": true, + "license": "MIT", "engines": { "node": ">= 12" } @@ -8658,6 +9437,7 @@ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", "integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -8666,6 +9446,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -8674,6 +9455,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-admin/-/is-admin-3.0.0.tgz", "integrity": "sha512-wOa3CXFJAu8BZ2BDtG9xYOOrsq6oiSvc2jFPy4X/HINx5bmJUcW8e+apItVbU2E7GIfBVaFVO7Zit4oAWtTJcw==", + "license": "MIT", "dependencies": { "execa": "^1.0.0" }, @@ -8686,6 +9468,7 @@ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -8702,13 +9485,15 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-async-function": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, + "license": "MIT", "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", @@ -8728,6 +9513,7 @@ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, + "license": "MIT", "dependencies": { "has-bigints": "^1.0.2" }, @@ -8743,6 +9529,7 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -8755,6 +9542,7 @@ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" @@ -8770,13 +9558,15 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -8788,6 +9578,7 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", "dependencies": { "hasown": "^2.0.2" }, @@ -8803,6 +9594,7 @@ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", @@ -8820,6 +9612,7 @@ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" @@ -8835,6 +9628,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", "bin": { "is-docker": "cli.js" }, @@ -8849,6 +9643,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-elevated/-/is-elevated-3.0.0.tgz", "integrity": "sha512-wjcp6RkouU9jpg55zERl+BglvV5j4jx5c/EMvQ+d12j/+nIEenNWPu+qc0tCg3JkLodbKZMg1qhJzEwG4qjclg==", + "license": "MIT", "dependencies": { "is-admin": "^3.0.0", "is-root": "^2.1.0" @@ -8862,6 +9657,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8871,6 +9667,7 @@ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3" }, @@ -8885,6 +9682,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "engines": { "node": ">=8" } @@ -8894,6 +9692,7 @@ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", @@ -8913,6 +9712,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -8924,6 +9724,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", "dependencies": { "is-docker": "^3.0.0" }, @@ -8942,6 +9743,7 @@ "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-2.0.0.tgz", "integrity": "sha512-9MTn0dteHETtyUx8pxqMwg5hMBi3pvlyglJ+b79KOCca0po23337LbVV2Hl4xmMvfw++ljnO0/+5G6G+0Szh6g==", "dev": true, + "license": "MIT", "dependencies": { "ip-regex": "^2.0.0" }, @@ -8953,6 +9755,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", "optional": true }, "node_modules/is-map": { @@ -8960,6 +9763,7 @@ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -8972,6 +9776,7 @@ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -8984,6 +9789,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -8992,6 +9798,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", + "license": "ISC", "dependencies": { "lodash.isfinite": "^3.3.2" } @@ -9001,6 +9808,7 @@ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" @@ -9017,6 +9825,7 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9025,18 +9834,21 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "license": "MIT" }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", @@ -9054,12 +9866,14 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/is-root": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "license": "MIT", "engines": { "node": ">=6" } @@ -9069,6 +9883,7 @@ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -9081,6 +9896,7 @@ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3" }, @@ -9095,6 +9911,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9104,6 +9921,7 @@ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" @@ -9120,6 +9938,7 @@ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", @@ -9137,6 +9956,7 @@ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, + "license": "MIT", "dependencies": { "which-typed-array": "^1.1.16" }, @@ -9151,13 +9971,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -9169,6 +9991,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "license": "MIT", "optional": true }, "node_modules/is-weakmap": { @@ -9176,6 +9999,7 @@ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -9188,6 +10012,7 @@ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3" }, @@ -9203,6 +10028,7 @@ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" @@ -9219,14 +10045,16 @@ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "license": "MIT", "dependencies": { "is-inside-container": "^1.0.0" }, @@ -9241,6 +10069,7 @@ "version": "2.0.9", "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz", "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==", + "license": "MIT", "optional": true, "dependencies": { "deep-is": "^0.1.3", @@ -9255,6 +10084,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "license": "MIT", "optional": true, "engines": { "node": ">=8" @@ -9263,17 +10093,20 @@ "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" }, "node_modules/isomorphic-ws": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "license": "MIT", "peerDependencies": { "ws": "*" } @@ -9282,13 +10115,15 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } @@ -9298,6 +10133,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "append-transform": "^2.0.0" }, @@ -9310,6 +10146,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.7.5", "@istanbuljs/schema": "^0.1.2", @@ -9325,6 +10162,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -9334,6 +10172,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, + "license": "ISC", "dependencies": { "archy": "^1.0.0", "cross-spawn": "^7.0.3", @@ -9346,24 +10185,65 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-processinfo/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "node_modules/istanbul-lib-processinfo/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" @@ -9374,6 +10254,7 @@ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -9389,6 +10270,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -9403,6 +10285,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -9419,13 +10302,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/istanbul-reports": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -9438,6 +10323,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -9452,6 +10338,7 @@ "version": "10.9.4", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "license": "Apache-2.0", "dependencies": { "async": "^3.2.6", "filelist": "^1.0.4", @@ -9468,6 +10355,7 @@ "version": "4.15.9", "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } @@ -9477,6 +10365,7 @@ "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", "integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==", "dev": true, + "license": "MIT", "dependencies": { "config-chain": "^1.1.13", "editorconfig": "^1.0.4", @@ -9493,20 +10382,12 @@ "node": ">=14" } }, - "node_modules/js-beautify/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/js-beautify/node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" @@ -9522,7 +10403,9 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -9538,35 +10421,12 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/js-beautify/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/js-beautify/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/js-beautify/node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -9579,6 +10439,7 @@ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" } @@ -9587,24 +10448,28 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/js-md4/-/js-md4-0.3.2.tgz", "integrity": "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-sha512": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/js-sha512/-/js-sha512-0.9.0.tgz", "integrity": "sha512-mirki9WS/SUahm+1TbAPkqvbCiCfOAAsyXeHxK1UkullnJVVqoJG2pL9ObvT05CN+tM7fxhfYm0NbXn+1hWoZg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -9616,12 +10481,14 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsep": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", + "license": "MIT", "engines": { "node": ">= 10.16.0" } @@ -9631,6 +10498,7 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -9642,6 +10510,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", "dependencies": { "bignumber.js": "^9.0.0" } @@ -9650,42 +10519,49 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "license": "MIT" }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -9698,6 +10574,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -9710,14 +10587,16 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, "node_modules/jsonpath-plus": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz", - "integrity": "sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.4.0.tgz", + "integrity": "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==", + "license": "MIT", "dependencies": { "@jsep-plugin/assignment": "^1.3.0", "@jsep-plugin/regex": "^1.0.4", @@ -9735,6 +10614,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", + "license": "MIT", "engines": { "node": "*" } @@ -9743,6 +10623,7 @@ "version": "9.0.3", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", "dependencies": { "jws": "^4.0.1", "lodash.includes": "^4.3.0", @@ -9763,7 +10644,8 @@ "node_modules/jsonwebtoken/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/jsprim": { "version": "2.0.2", @@ -9773,6 +10655,7 @@ "engines": [ "node >=0.6.0" ], + "license": "MIT", "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -9785,6 +10668,7 @@ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", "integrity": "sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.1", "object.assign": "^4.1.0" @@ -9797,12 +10681,14 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jwa": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", @@ -9813,6 +10699,7 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/jwk-to-pem/-/jwk-to-pem-2.0.7.tgz", "integrity": "sha512-cSVphrmWr6reVchuKQZdfSs4U9c5Y4hwZggPoz6cbVnTpAVgGRpEuQng86IyqLeGZlhTh+c4MAreB6KbdQDKHQ==", + "license": "Apache-2.0", "dependencies": { "asn1.js": "^5.3.0", "elliptic": "^6.6.1", @@ -9823,6 +10710,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" @@ -9832,6 +10720,7 @@ "version": "26.1.1", "resolved": "https://registry.npmjs.org/keycloak-connect/-/keycloak-connect-26.1.1.tgz", "integrity": "sha512-2wvNJXldB9Em+mp6liJ+AnftcJovFEvNhUgv3hblNDmVihBoBqn4zFlwLIN41lo0H8CicB2T86xZ5U2MiQ9FFA==", + "license": "Apache-2.0", "dependencies": { "jwk-to-pem": "^2.0.0" }, @@ -9847,6 +10736,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -9856,6 +10746,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -9869,6 +10760,7 @@ "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", "dev": true, + "license": "MIT", "dependencies": { "immediate": "~3.0.5" } @@ -9878,19 +10770,21 @@ "resolved": "https://registry.npmjs.org/liquid-json/-/liquid-json-0.3.1.tgz", "integrity": "sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } }, "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha512-3p6ZOGNbiX4CdvEd1VcE6yi78UrGNpjHO33noGwHCnT/o2fyllJDepsm8+mFFv/DvtwFHht5HIHSyOy5a+ChVQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", + "parse-json": "^2.2.0", + "pify": "^2.0.0", "strip-bom": "^3.0.0" }, "engines": { @@ -9902,6 +10796,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -9911,6 +10806,7 @@ "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "lie": "3.1.1" } @@ -9920,6 +10816,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -9933,70 +10830,83 @@ "node_modules/lodash": { "version": "4.17.23", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==" + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" }, "node_modules/lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" }, "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" }, "node_modules/lodash.isfinite": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", - "integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==" + "integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==", + "license": "MIT" }, "node_modules/lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" }, "node_modules/lodash.isnumber": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" }, "node_modules/lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -10011,13 +10921,15 @@ "node_modules/long": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==" + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, + "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -10029,12 +10941,14 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lru-cache": { "version": "8.0.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", + "license": "ISC", "engines": { "node": ">=16.14" } @@ -10044,15 +10958,32 @@ "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", "dev": true, + "license": "MIT", "dependencies": { "es5-ext": "~0.10.2" } }, + "node_modules/lru.min": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", + "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -10068,6 +10999,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -10076,6 +11008,7 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", "optional": true, "dependencies": { "agentkeepalive": "^4.1.3", @@ -10099,10 +11032,21 @@ "node": ">= 10" } }, + "node_modules/make-fetch-happen/node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/make-fetch-happen/node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", "optional": true, "dependencies": { "debug": "4" @@ -10115,6 +11059,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "optional": true, "dependencies": { "ms": "^2.1.3" @@ -10132,6 +11077,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", "optional": true, "dependencies": { "@tootallnate/once": "1", @@ -10146,6 +11092,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", "optional": true, "dependencies": { "agent-base": "6", @@ -10159,6 +11106,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -10167,16 +11115,31 @@ "node": ">=10" } }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/make-fetch-happen/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", "optional": true }, "node_modules/make-fetch-happen/node_modules/socks-proxy-agent": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", "optional": true, "dependencies": { "agent-base": "^6.0.2", @@ -10187,11 +11150,19 @@ "node": ">= 10" } }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^4.0.0" }, @@ -10203,6 +11174,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -10212,6 +11184,7 @@ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "charenc": "0.0.2", "crypt": "0.0.2", @@ -10222,6 +11195,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10231,6 +11205,7 @@ "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", "dev": true, + "license": "ISC", "dependencies": { "d": "^1.0.2", "es5-ext": "^0.10.64", @@ -10249,6 +11224,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -10257,6 +11233,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10265,6 +11242,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -10276,6 +11254,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10285,6 +11264,7 @@ "resolved": "https://registry.npmjs.org/mime-format/-/mime-format-2.0.1.tgz", "integrity": "sha512-XxU3ngPbEnrYnNbIX+lYSaYg0M01v6p2ntd2YaFksTu0vayaw5OJvbdRyWs07EYRlLED5qadUZ+xo+XhOvFhwg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "charset": "^1.0.0" } @@ -10293,6 +11273,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -10305,6 +11286,7 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -10313,6 +11295,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -10323,49 +11306,53 @@ "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "license": "MIT" }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz", + "integrity": "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^5.0.2" }, "engines": { - "node": "*" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minipass-collect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", "optional": true, "dependencies": { "minipass": "^3.0.0" @@ -10374,10 +11361,31 @@ "node": ">= 8" } }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/minipass-fetch": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", "optional": true, "dependencies": { "minipass": "^3.1.0", @@ -10391,10 +11399,31 @@ "encoding": "^0.1.12" } }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", "optional": true, "dependencies": { "minipass": "^3.0.0" @@ -10403,10 +11432,31 @@ "node": ">= 8" } }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", "optional": true, "dependencies": { "minipass": "^3.0.0" @@ -10415,10 +11465,31 @@ "node": ">=8" } }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", "optional": true, "dependencies": { "minipass": "^3.0.0" @@ -10427,10 +11498,31 @@ "node": ">=8" } }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", "optional": true, "dependencies": { "minipass": "^3.0.0", @@ -10440,11 +11532,32 @@ "node": ">= 8" } }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/mkdirp": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true, + "license": "MIT", "bin": { "mkdirp": "dist/cjs/src/bin.js" }, @@ -10458,13 +11571,15 @@ "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" }, "node_modules/mocha": { "version": "10.6.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.6.0.tgz", "integrity": "sha512-hxjt4+EEB0SA0ZDygSS015t65lJw/I2yRCS3Ae+SJ5FrbzrXgfYwJr96f0OvIXdj7h4lv/vLCrH3rkiuizFSvw==", "dev": true, + "license": "MIT", "dependencies": { "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", @@ -10500,6 +11615,7 @@ "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.2.1.tgz", "integrity": "sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4", "md5": "^2.3.0", @@ -10516,6 +11632,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -10532,22 +11649,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } + "license": "MIT" }, "node_modules/mocha/node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -10559,6 +11669,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -10571,29 +11682,19 @@ } } }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mocha/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -10609,6 +11710,7 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -10625,12 +11727,14 @@ "node_modules/module-details-from-path": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", - "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==" + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT" }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", "engines": { "node": "*" } @@ -10639,6 +11743,7 @@ "version": "0.5.48", "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", + "license": "MIT", "dependencies": { "moment": "^2.29.4" }, @@ -10649,13 +11754,15 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/multer": { "version": "1.4.5-lts.1", "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", "deprecated": "Multer 1.x is impacted by a number of vulnerabilities, which have been patched in 2.x. You should upgrade to the latest 2.x version.", + "license": "MIT", "dependencies": { "append-field": "^1.0.0", "busboy": "^1.0.0", @@ -10673,6 +11780,7 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -10684,6 +11792,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10692,12 +11801,14 @@ "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", "integrity": "sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/mysql2": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.10.1.tgz", "integrity": "sha512-6zo1T3GILsXMCex3YEu7hCz2OXLUarxFsxvFcUHWMpkPtmZLeTTWgRdc1gWyNJiYt6AxITmIf9bZDRy/jAfWew==", + "license": "MIT", "dependencies": { "denque": "^2.1.0", "generate-function": "^2.3.1", @@ -10716,6 +11827,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -10724,39 +11836,35 @@ } }, "node_modules/named-placeholders": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", - "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", + "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", + "license": "MIT", "dependencies": { - "lru-cache": "^7.14.1" + "lru.min": "^1.1.0" }, "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/named-placeholders/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" + "node": ">=8.0.0" } }, "node_modules/napi-build-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", - "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==" + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nconf": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.12.1.tgz", "integrity": "sha512-p2cfF+B3XXacQdswUYWZ0w6Vld0832A/tuqjLBu3H1sfUcby4N2oVbGhyuCkZv+t3iY3aiFEj7gZGqax9Q2c1w==", + "license": "MIT", "dependencies": { "async": "^3.0.0", "ini": "^2.0.0", @@ -10771,6 +11879,7 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -10781,6 +11890,7 @@ "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -10798,6 +11908,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10806,22 +11917,25 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/netmask": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "license": "MIT", "optional": true, "engines": { "node": ">= 0.4.0" } }, "node_modules/newman": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/newman/-/newman-6.2.1.tgz", - "integrity": "sha512-Zq8Sr5GFF+OXs5yIbyglLMKMh1WNMjYVV0yZaSBZ+DIgQOIWcxT8QTfbrl/YUGrLyT4rjpu+yZ/Z+kozw79GEA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/newman/-/newman-6.2.2.tgz", + "integrity": "sha512-BmGzMz6f2FLtw/hHAbhEAVqXS+3APJGAWzlxVijSElFaxC37wpHEqsOB09d/2uHMvTyMXGArtbFa+z5m/a68Uw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@postman/tough-cookie": "4.1.3-postman.1", "async": "3.2.5", @@ -10837,7 +11951,7 @@ "mkdirp": "3.0.1", "postman-collection": "4.4.0", "postman-collection-transformer": "4.1.8", - "postman-request": "2.88.1-postman.34", + "postman-request": "2.88.1-postman.48", "postman-runtime": "7.39.1", "pretty-ms": "7.0.1", "semver": "7.6.3", @@ -10857,6 +11971,7 @@ "resolved": "https://registry.npmjs.org/newman-reporter-junitfull/-/newman-reporter-junitfull-1.1.1.tgz", "integrity": "sha512-ET5rU1qkeJ5yvFxcKQFkqGxWia50kdnufm1uzyeNYlUg6T+k07AvOS0mfp/Ejr0njnsiPfFLb9kC48F8pafq9A==", "dev": true, + "license": "Apache-2.0", "dependencies": { "lodash": "^4.17.10", "moment": "^2.22.2", @@ -10874,6 +11989,7 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz", "integrity": "sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0" } @@ -10882,24 +11998,41 @@ "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/newman/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, "node_modules/next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "license": "MIT" }, "node_modules/nise": { "version": "5.1.9", "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0", "@sinonjs/fake-timers": "^11.2.2", @@ -10912,12 +12045,14 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-abi": { - "version": "3.85.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", - "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "version": "3.87.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.87.0.tgz", + "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", + "license": "MIT", "dependencies": { "semver": "^7.3.5" }, @@ -10928,7 +12063,8 @@ "node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" }, "node_modules/node-domexception": { "version": "1.0.0", @@ -10945,25 +12081,29 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "engines": { "node": ">=10.5.0" } }, "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" + "whatwg-url": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "4.x || >=6.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/node-fetch-npm": { @@ -10971,6 +12111,7 @@ "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz", "integrity": "sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==", "deprecated": "This module is not used anymore, npm uses minipass-fetch for its fetch implementation now", + "license": "MIT", "dependencies": { "encoding": "^0.1.11", "json-parse-better-errors": "^1.0.0", @@ -10980,18 +12121,11 @@ "node": ">=4" } }, - "node_modules/node-fetch/node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, "node_modules/node-forge": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==", + "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" } @@ -11000,6 +12134,7 @@ "version": "8.4.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", "optional": true, "dependencies": { "env-paths": "^2.2.0", @@ -11024,13 +12159,15 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", "optional": true }, "node_modules/node-gyp/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", "optional": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -11051,6 +12188,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", "optional": true, "dependencies": { "abbrev": "1" @@ -11062,17 +12200,36 @@ "node": ">=6" } }, + "node_modules/node-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/node-oauth1": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/node-oauth1/-/node-oauth1-1.3.0.tgz", "integrity": "sha512-0yggixNfrA1KcBwvh/Hy2xAS1Wfs9dcg6TdFf2zN7gilcAigMdrtZ4ybrBSXBgLvGDw9V1p2MRnGBMq7XjTWLg==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, + "license": "MIT", "dependencies": { "process-on-spawn": "^1.0.0" }, @@ -11084,13 +12241,15 @@ "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nopt": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", "dev": true, + "license": "ISC", "dependencies": { "abbrev": "^2.0.0" }, @@ -11106,6 +12265,7 @@ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -11118,6 +12278,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -11127,6 +12288,7 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11135,6 +12297,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "license": "MIT", "dependencies": { "path-key": "^2.0.0" }, @@ -11146,6 +12309,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", "engines": { "node": ">=4" } @@ -11155,6 +12319,7 @@ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", "deprecated": "This package is no longer supported.", + "license": "ISC", "optional": true, "dependencies": { "are-we-there-yet": "^3.0.0", @@ -11171,6 +12336,7 @@ "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", @@ -11212,6 +12378,7 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -11223,6 +12390,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -11235,8 +12403,9 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -11257,6 +12426,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -11269,6 +12439,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -11284,6 +12455,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -11296,15 +12468,34 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/nyc/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/nyc/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -11318,13 +12509,15 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/nyc/node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -11347,6 +12540,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -11360,15 +12554,16 @@ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "*" } }, "node_modules/oauth4webapi": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.3.tgz", - "integrity": "sha512-pQ5BsX3QRTgnt5HxgHwgunIRaDXBdkT23tf8dfzmtTIL2LTpdmxgbpbBm0VgFWAIDlezQvQCTgnVIUmHupXHxw==", - "optional": true, + "version": "3.8.5", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.5.tgz", + "integrity": "sha512-A8jmyUckVhRJj5lspguklcl90Ydqk61H3dcU0oLhH3Yv13KpAliKTt5hknpGGPZSSfOwGyraNEFmofDYH+1kSg==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } @@ -11377,23 +12572,25 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.0.1.tgz", "integrity": "sha512-c6legOHWepAbWnp3j5SRUMpxCXBKI4rD7A5Osn9IzZ8w4O/KccXdW0lqdkQKbpk0eHGjNgKihgzY6WuEq99Tfw==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-hash": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", - "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", "engines": { - "node": ">= 0.10.0" + "node": ">= 6" } }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11406,6 +12603,7 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -11415,6 +12613,7 @@ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -11433,12 +12632,14 @@ "node_modules/on-error": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/on-error/-/on-error-2.1.0.tgz", - "integrity": "sha512-wpKXxCW2wXLI+9DB9DDBVuOCN9C5rjyaP4GWwqhgrSd2ys1Vyc9yGaPmC5HSOdQ30x9zCLozi9mHx3lm01E+LQ==" + "integrity": "sha512-wpKXxCW2wXLI+9DB9DDBVuOCN9C5rjyaP4GWwqhgrSd2ys1Vyc9yGaPmC5HSOdQ30x9zCLozi9mHx3lm01E+LQ==", + "license": "MIT" }, "node_modules/on-exit-leak-free": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -11447,6 +12648,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -11458,6 +12660,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -11466,6 +12669,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", "integrity": "sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w==", + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -11475,6 +12679,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^1.0.0" }, @@ -11486,6 +12691,7 @@ "version": "10.2.0", "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "license": "MIT", "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", @@ -11500,13 +12706,13 @@ } }, "node_modules/openid-client": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.8.1.tgz", - "integrity": "sha512-VoYT6enBo6Vj2j3Q5Ec0AezS+9YGzQo1f5Xc42lreMGlfP4ljiXPKVDvCADh+XHCV/bqPu/wWSiCVXbJKvrODw==", - "optional": true, + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.8.2.tgz", + "integrity": "sha512-uOvTCndr4udZsKihJ68H9bUICrriHdUVJ6Az+4Ns6cW55rwM5h0bjVIzDz2SxgOI84LKjFyjOFvERLzdTUROGA==", + "license": "MIT", "dependencies": { - "jose": "^6.1.0", - "oauth4webapi": "^3.8.2" + "jose": "^6.1.3", + "oauth4webapi": "^3.8.4" }, "funding": { "url": "https://github.com/sponsors/panva" @@ -11516,7 +12722,7 @@ "version": "6.1.3", "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", - "optional": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } @@ -11526,6 +12732,7 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -11543,6 +12750,7 @@ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11552,6 +12760,7 @@ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", @@ -11568,6 +12777,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", "engines": { "node": ">=4" } @@ -11577,6 +12787,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -11592,6 +12803,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -11607,6 +12819,7 @@ "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, + "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -11619,6 +12832,7 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -11627,6 +12841,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "license": "MIT", "optional": true, "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", @@ -11646,6 +12861,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "optional": true, "dependencies": { "ms": "^2.1.3" @@ -11663,12 +12879,14 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", "optional": true }, "node_modules/pac-resolver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "license": "MIT", "optional": true, "dependencies": { "degenerator": "^5.0.0", @@ -11683,6 +12901,7 @@ "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, + "license": "ISC", "dependencies": { "graceful-fs": "^4.1.15", "hasha": "^5.0.0", @@ -11696,13 +12915,15 @@ "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -11711,16 +12932,16 @@ } }, "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", "dev": true, + "license": "MIT", "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "error-ex": "^1.2.0" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, "node_modules/parse-ms": { @@ -11728,6 +12949,7 @@ "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -11736,6 +12958,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -11745,6 +12968,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11754,6 +12978,7 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "devOptional": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11762,12 +12987,14 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", - "dev": true + "dev": true, + "license": "(WTFPL OR MIT)" }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", "engines": { "node": ">=8" } @@ -11775,12 +13002,14 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -11795,26 +13024,21 @@ "node_modules/path-scurry/node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" - }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "engines": { - "node": ">=16 || 14 >=14.17" - } + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha512-dUnb5dXUf+kzhC/W/F4e5/SkluXIFf5VUHolW1Eg1irn1hGWjPGdsRcvYJ1nD6lhk8Ir7VM0bHJKsYTx8Jx9OQ==", "dev": true, + "license": "MIT", "dependencies": { "pify": "^2.0.0" }, @@ -11822,20 +13046,12 @@ "node": ">=4" } }, - "node_modules/path-type/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/pathval": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 14.16" } @@ -11844,18 +13060,21 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT", "optional": true }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/pg": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/pg/-/pg-8.12.0.tgz", "integrity": "sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==", + "license": "MIT", "dependencies": { "pg-connection-string": "^2.6.4", "pg-pool": "^3.6.2", @@ -11879,41 +13098,47 @@ } }, "node_modules/pg-cloudflare": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz", - "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz", + "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==", + "license": "MIT", "optional": true }, "node_modules/pg-connection-string": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz", - "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==" + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.11.0.tgz", + "integrity": "sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ==", + "license": "MIT" }, "node_modules/pg-int8": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", "engines": { "node": ">=4.0.0" } }, "node_modules/pg-pool": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz", - "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz", + "integrity": "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==", + "license": "MIT", "peerDependencies": { "pg": ">=8.0" } }, "node_modules/pg-protocol": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz", - "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz", + "integrity": "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==", + "license": "MIT" }, "node_modules/pg-types": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", @@ -11929,6 +13154,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", "dependencies": { "split2": "^4.1.0" } @@ -11936,13 +13162,15 @@ "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -11951,18 +13179,20 @@ } }, "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, "node_modules/pino": { "version": "9.13.1", "resolved": "https://registry.npmjs.org/pino/-/pino-9.13.1.tgz", "integrity": "sha512-Szuj+ViDTjKPQYiKumGmEn3frdl+ZPSdosHyt9SnUevFosOkMY2b7ipxlEctNKPmMD/VibeBI+ZcZCJK+4DPuw==", + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", @@ -11984,6 +13214,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", "dependencies": { "split2": "^4.0.0" } @@ -11991,13 +13222,15 @@ "node_modules/pino-std-serializers": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", - "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "license": "MIT" }, "node_modules/pkg-conf": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^2.0.0", "load-json-file": "^4.0.0" @@ -12011,6 +13244,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^2.0.0" }, @@ -12018,11 +13252,28 @@ "node": ">=4" } }, + "node_modules/pkg-conf/node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/pkg-conf/node_modules/locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -12036,6 +13287,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^1.0.0" }, @@ -12048,6 +13300,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^1.1.0" }, @@ -12060,6 +13313,21 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, "engines": { "node": ">=4" } @@ -12069,6 +13337,27 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -12078,6 +13367,7 @@ "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", "integrity": "sha512-ft/WI9YK6FuTuw4Ql+QUaNXtm/ASQNqDUUsZEgFZKyFpW6amyP8Gx01xrRs8KdiNbbqXfYxkOXplpq1euWbOjw==", "dev": true, + "license": "MIT", "dependencies": { "debug-log": "^1.0.0", "find-root": "^1.0.0", @@ -12092,6 +13382,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -12104,6 +13395,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -12117,6 +13409,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -12129,6 +13422,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -12144,6 +13438,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -12156,6 +13451,7 @@ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -12164,6 +13460,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz", "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==", + "license": "MIT", "dependencies": { "async": "^2.6.0", "is-number-like": "^1.0.3" @@ -12177,6 +13474,7 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "license": "MIT", "dependencies": { "lodash": "^4.17.14" } @@ -12186,6 +13484,7 @@ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -12194,14 +13493,16 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", + "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12210,6 +13511,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12218,6 +13520,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", "dependencies": { "xtend": "^4.0.0" }, @@ -12230,6 +13533,7 @@ "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.4.0.tgz", "integrity": "sha512-2BGDFcUwlK08CqZFUlIC8kwRJueVzPjZnnokWPtJCd9f2J06HBQpGL7t2P1Ud1NEsK9NHq9wdipUhWLOPj5s/Q==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@faker-js/faker": "5.5.3", "file-type": "3.9.0", @@ -12252,6 +13556,7 @@ "resolved": "https://registry.npmjs.org/postman-collection-transformer/-/postman-collection-transformer-4.1.8.tgz", "integrity": "sha512-smJ6X7Z7kbg6hp7JZPFixrSN3J3WkQed7DrWCC5tF7IxOMpFLqhtTtGssY8nD1inP8+mJf+N72Pf2ttUAHgBKw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "commander": "8.3.0", "inherits": "2.0.4", @@ -12271,6 +13576,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12" } @@ -12280,6 +13586,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -12292,6 +13599,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -12302,11 +13610,19 @@ "node": ">=10" } }, + "node_modules/postman-collection-transformer/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/postman-collection/node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -12319,6 +13635,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -12331,6 +13648,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -12346,50 +13664,48 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, + "node_modules/postman-collection/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/postman-request": { - "version": "2.88.1-postman.34", - "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.34.tgz", - "integrity": "sha512-GkolJ4cIzgamcwHRDkeZc/taFWO1u2HuGNML47K9ZAsFH2LdEkS5Yy8QanpzhjydzV3WWthl9v60J8E7SjKodQ==", + "version": "2.88.1-postman.48", + "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.48.tgz", + "integrity": "sha512-E32FGh8ig2KDvzo4Byi7Ibr+wK2gNKPSqXoNsvjdCHgDBxSK4sCUwv+aa3zOBUwfiibPImHMy0WdlDSSCTqTuw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@postman/form-data": "~3.1.1", "@postman/tough-cookie": "~4.1.3-postman.1", - "@postman/tunnel-agent": "^0.6.3", + "@postman/tunnel-agent": "^0.6.8", "aws-sign2": "~0.7.0", "aws4": "^1.12.0", - "brotli": "^1.3.3", "caseless": "~0.12.0", "combined-stream": "~1.0.6", "extend": "~3.0.2", "forever-agent": "~0.6.1", - "har-validator": "~5.1.3", - "http-signature": "~1.3.1", + "http-signature": "~1.4.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", "mime-types": "^2.1.35", "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.3", + "qs": "~6.14.1", "safe-buffer": "^5.1.2", + "socks-proxy-agent": "^8.0.5", "stream-length": "^1.0.2", "uuid": "^8.3.2" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/postman-request/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, - "engines": { - "node": ">=0.6" + "node": ">= 16" } }, "node_modules/postman-request/node_modules/uuid": { @@ -12397,6 +13713,7 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -12406,6 +13723,7 @@ "resolved": "https://registry.npmjs.org/postman-runtime/-/postman-runtime-7.39.1.tgz", "integrity": "sha512-IRNrBE0l1K3ZqQhQVYgF6MPuqOB9HqYncal+a7RpSS+sysKLhJMkC9SfUn1HVuOpokdPkK92ykvPzj8kCOLYAg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@postman/tough-cookie": "4.1.3-postman.1", "async": "3.2.5", @@ -12435,30 +13753,93 @@ "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/postman-runtime/node_modules/aws4": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/postman-runtime/node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" + } }, "node_modules/postman-runtime/node_modules/jose": { "version": "4.14.4", "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } }, - "node_modules/postman-runtime/node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "node_modules/postman-runtime/node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/postman-runtime/node_modules/postman-request": { + "version": "2.88.1-postman.34", + "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.34.tgz", + "integrity": "sha512-GkolJ4cIzgamcwHRDkeZc/taFWO1u2HuGNML47K9ZAsFH2LdEkS5Yy8QanpzhjydzV3WWthl9v60J8E7SjKodQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@postman/form-data": "~3.1.1", + "@postman/tough-cookie": "~4.1.3-postman.1", + "@postman/tunnel-agent": "^0.6.3", + "aws-sign2": "~0.7.0", + "aws4": "^1.12.0", + "brotli": "^1.3.3", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "har-validator": "~5.1.3", + "http-signature": "~1.3.1", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "^2.1.35", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.3", + "safe-buffer": "^5.1.2", + "stream-length": "^1.0.2", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postman-runtime/node_modules/qs": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.5.tgz", + "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==", "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">= 6.13.0" + "node": ">=0.6" } }, "node_modules/postman-runtime/node_modules/uuid": { @@ -12466,6 +13847,7 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -12475,6 +13857,7 @@ "resolved": "https://registry.npmjs.org/postman-sandbox/-/postman-sandbox-4.7.1.tgz", "integrity": "sha512-H2wYSLK0mB588IaxoLrLoPbpmxsIcwFtgaK2c8gAsAQ+TgYFePwb4qdeVcYDMqmwrLd77/ViXkjasP/sBMz1sQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "lodash": "4.17.21", "postman-collection": "4.4.0", @@ -12490,6 +13873,7 @@ "resolved": "https://registry.npmjs.org/postman-url-encoder/-/postman-url-encoder-3.0.5.tgz", "integrity": "sha512-jOrdVvzUXBC7C+9gkIkpDJ3HIxOHTIqjpQ4C1EMt1ZGeMvSEpbFCKq23DEfgsj46vMnDgyQf+1ZLp2Wm+bKSsA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "punycode": "^2.1.1" }, @@ -12501,6 +13885,8 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", @@ -12522,11 +13908,63 @@ "node": ">=10" } }, + "node_modules/prebuild-install/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prebuild-install/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/prebuild-install/node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/prebuild-install/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -12536,6 +13974,7 @@ "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", "dev": true, + "license": "MIT", "dependencies": { "parse-ms": "^2.1.0" }, @@ -12549,13 +13988,15 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" }, "node_modules/process-on-spawn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.1.0.tgz", "integrity": "sha512-JOnOPQ/8TZgjs1JIH/m9ni7FfimjNa/PRx7y/Wb5qdItsnhO0jE4AT7fC0HjC28DUQWDr50dwSYZLdRMlqDq3Q==", "dev": true, + "license": "MIT", "dependencies": { "fromentries": "^1.2.0" }, @@ -12576,13 +14017,15 @@ "type": "opencollective", "url": "https://opencollective.com/fastify" } - ] + ], + "license": "MIT" }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -12591,17 +14034,20 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", "optional": true }, "node_modules/promise-polyfill": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-2.1.4.tgz", - "integrity": "sha512-/DVUJXyaiYr7Pu0q2qPV/OtABpiukAHswJb9VV/tUVFsvC5iZUTyVPxfEr8cIVatGa5/Mxeli8QMyzAMBmoiYg==" + "integrity": "sha512-/DVUJXyaiYr7Pu0q2qPV/OtABpiukAHswJb9VV/tUVFsvC5iZUTyVPxfEr8cIVatGa5/Mxeli8QMyzAMBmoiYg==", + "license": "MIT" }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", "optional": true, "dependencies": { "err-code": "^2.0.2", @@ -12616,6 +14062,7 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dev": true, + "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -12627,6 +14074,7 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12635,12 +14083,14 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/proto3-json-serializer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-3.0.4.tgz", "integrity": "sha512-E1sbAYg3aEbXrq0n1ojJkRHQJGE1kaE/O6GLA94y8rnJBfgvOPTOd1b9hOceQK1FFZI9qMh1vBERCyO2ifubcw==", + "license": "Apache-2.0", "dependencies": { "protobufjs": "^7.4.0" }, @@ -12653,6 +14103,7 @@ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -12675,6 +14126,7 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -12687,6 +14139,7 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "license": "MIT", "optional": true, "dependencies": { "agent-base": "^7.1.2", @@ -12706,6 +14159,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "optional": true, "dependencies": { "ms": "^2.1.3" @@ -12723,6 +14177,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", "optional": true, "engines": { "node": ">=12" @@ -12732,18 +14187,21 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", "optional": true }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" }, "node_modules/psl": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", "dev": true, + "license": "MIT", "dependencies": { "punycode": "^2.3.1" }, @@ -12755,6 +14213,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -12765,14 +14224,16 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" }, @@ -12787,7 +14248,8 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -12807,17 +14269,20 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/quick-format-unescaped": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" }, "node_modules/random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -12827,6 +14292,7 @@ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -12835,6 +14301,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -12843,6 +14310,7 @@ "version": "2.5.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", @@ -12857,6 +14325,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -12870,12 +14339,14 @@ "node_modules/rc/node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12884,13 +14355,15 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha512-eFIBOPW7FGjzBuk3hdXEuNSiTZS/xEMlH49HxMyzb0hyPfu4EhVjT2DH32K1hSSmVq4sebAWnZuuY5auISUTGA==", "dev": true, + "license": "MIT", "dependencies": { "load-json-file": "^2.0.0", "normalize-package-data": "^2.3.2", @@ -12905,6 +14378,7 @@ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha512-1orxQfbWGUiTn9XsPlChs6rLie/AV9jwZTGmu2NZw/CUDJQchXJFYE0Fq5j7+n558T1JhDWLdhyd1Zj+wLY//w==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^2.0.0", "read-pkg": "^2.0.0" @@ -12918,6 +14392,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^2.0.0" }, @@ -12930,6 +14405,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -12943,6 +14419,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^1.0.0" }, @@ -12955,6 +14432,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^1.1.0" }, @@ -12967,6 +14445,7 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -12976,51 +14455,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg/node_modules/load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha512-3p6ZOGNbiX4CdvEd1VcE6yi78UrGNpjHO33noGwHCnT/o2fyllJDepsm8+mFFv/DvtwFHht5HIHSyOy5a+ChVQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg/node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -13029,6 +14464,7 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -13041,6 +14477,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -13052,6 +14489,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", "engines": { "node": ">= 12.13.0" } @@ -13061,6 +14499,7 @@ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", @@ -13083,6 +14522,7 @@ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", @@ -13103,6 +14543,7 @@ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.5.0" } @@ -13112,6 +14553,7 @@ "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", "dev": true, + "license": "ISC", "dependencies": { "es6-error": "^4.0.1" }, @@ -13119,14 +14561,11 @@ "node": ">=4" } }, - "node_modules/request": { - "resolved": "node_modules/@kubernetes/client-node/@cypress/request@3.0.8", - "link": true - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -13135,6 +14574,7 @@ "version": "7.5.2", "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "license": "MIT", "dependencies": { "debug": "^4.3.5", "module-details-from-path": "^1.0.3", @@ -13148,6 +14588,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -13163,19 +14604,22 @@ "node_modules/require-in-the-middle/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha512-Xct+41K3twrbBHdxAgMoOS+cNcoqIjfM2/VxBF4LL2hVph7YsF8VSKyQ3BDFZwEVbok9yeDl2le/qo0S77WG2w==", "dev": true, + "license": "MIT", "dependencies": { "caller-path": "^0.1.0", "resolve-from": "^1.0.0" @@ -13189,6 +14633,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", "integrity": "sha512-kT10v4dhrlLNcnO084hEjvXCI1wUG9qZLoz2RogxqDQQYy7IxjI/iMUkOtQTNEh6rzHxvdQWHsJyel1pKOVCxg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -13197,12 +14642,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/resolve": { "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", @@ -13223,6 +14670,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -13232,6 +14680,7 @@ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", "dev": true, + "license": "MIT", "dependencies": { "onetime": "^2.0.0", "signal-exit": "^3.0.2" @@ -13244,6 +14693,7 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", "optional": true, "engines": { "node": ">= 4" @@ -13252,12 +14702,14 @@ "node_modules/retry-as-promised": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.1.1.tgz", - "integrity": "sha512-hMD7odLOt3LkTjcif8aRZqi/hybjpLNgSk5oF5FCowfCjok6LukpN2bDX7R5wDmbgBQFn7YoBxSagmtXHaJYJw==" + "integrity": "sha512-hMD7odLOt3LkTjcif8aRZqi/hybjpLNgSk5oF5FCowfCjok6LukpN2bDX7R5wDmbgBQFn7YoBxSagmtXHaJYJw==", + "license": "MIT" }, "node_modules/retry-request": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-8.0.2.tgz", "integrity": "sha512-JzFPAfklk1kjR1w76f0QOIhoDkNkSqW8wYKT08n9yysTmZfB+RQ2QoXoTAeOi1HD9ZipTyTAZg3c4pM/jeqgSw==", + "license": "MIT", "dependencies": { "extend": "^3.0.2", "teeny-request": "^10.0.0" @@ -13269,12 +14721,14 @@ "node_modules/rfc4648": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.4.tgz", - "integrity": "sha512-rRg/6Lb+IGfJqO05HZkN50UtY7K/JhxJag1kP23+zyMfrvoB0B7RWv06MbOzoc79RgCdNTiUaNsTT1AJZ7Z+cg==" + "integrity": "sha512-rRg/6Lb+IGfJqO05HZkN50UtY7K/JhxJag1kP23+zyMfrvoB0B7RWv06MbOzoc79RgCdNTiUaNsTT1AJZ7Z+cg==", + "license": "MIT" }, "node_modules/rhea": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/rhea/-/rhea-3.0.4.tgz", "integrity": "sha512-n3kw8syCdrsfJ72w3rohpoHHlmv/RZZEP9VY5BVjjo0sEGIt4YSKypBgaiA+OUSgJAzLjOECYecsclG5xbYtZw==", + "license": "Apache-2.0", "dependencies": { "debug": "^4.3.3" } @@ -13283,6 +14737,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -13298,40 +14753,68 @@ "node_modules/rhea/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "devOptional": true, + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", "dependencies": { - "glob": "^7.1.3" + "glob": "^10.3.7" }, "bin": { - "rimraf": "bin.js" + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "devOptional": true, + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", "engines": { - "node": "*" + "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -13342,6 +14825,7 @@ "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", @@ -13358,6 +14842,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "license": "MIT", "engines": { "node": ">=18" }, @@ -13370,6 +14855,7 @@ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -13393,6 +14879,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -13402,6 +14889,7 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "symbol-observable": "1.0.1" }, @@ -13414,6 +14902,7 @@ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", @@ -13432,7 +14921,8 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/safe-buffer": { "version": "5.2.1", @@ -13451,13 +14941,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" @@ -13473,13 +14965,15 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -13496,6 +14990,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", "engines": { "node": ">=10" } @@ -13503,17 +14998,20 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/secure-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz", - "integrity": "sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg==" + "integrity": "sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg==", + "license": "MIT" }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -13525,58 +15023,38 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "range-parser": "~1.2.1", - "statuses": "2.0.1" + "statuses": "~2.0.2" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/seq-queue": { "version": "0.0.5", @@ -13593,6 +15071,7 @@ "url": "https://opencollective.com/sequelize" } ], + "license": "MIT", "dependencies": { "@types/debug": "^4.1.8", "@types/validator": "^13.7.17", @@ -13649,6 +15128,7 @@ "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.6.2.tgz", "integrity": "sha512-V8Oh+XMz2+uquLZltZES6MVAD+yEnmMfwfn+gpXcDiwE3jyQygLt4xoI0zG8gKt6cRcs84hsKnXAKDQjG/JAgg==", "dev": true, + "license": "MIT", "dependencies": { "cli-color": "^2.0.3", "fs-extra": "^9.1.0", @@ -13671,6 +15151,7 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -13682,6 +15163,7 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -13699,6 +15181,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -13707,6 +15190,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -13722,12 +15206,14 @@ "node_modules/sequelize/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/sequelize/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -13737,18 +15223,30 @@ "resolved": "https://registry.npmjs.org/serialised-error/-/serialised-error-1.1.3.tgz", "integrity": "sha512-vybp3GItaR1ZtO2nxZZo8eOo7fnVaNtP3XE2vJKgzkKR2bagCkdJ1EpYYhEMd3qu/80DwQk9KjsNSxE3fXWq0g==", "dev": true, + "license": "Apache-2.0", "dependencies": { "object-hash": "^1.1.2", "stack-trace": "0.0.9", "uuid": "^3.0.0" } }, + "node_modules/serialised-error/node_modules/object-hash": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", + "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/serialised-error/node_modules/uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", "dev": true, + "license": "MIT", "bin": { "uuid": "bin/uuid" } @@ -13758,6 +15256,7 @@ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.13.1" }, @@ -13773,6 +15272,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -13785,19 +15285,21 @@ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.19.0" + "send": "~0.19.1" }, "engines": { "node": ">= 0.8.0" @@ -13807,13 +15309,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "devOptional": true + "devOptional": true, + "license": "ISC" }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -13831,6 +15335,7 @@ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -13846,6 +15351,7 @@ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "dev": true, + "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", @@ -13858,17 +15364,20 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, "node_modules/shallow-copy": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", - "integrity": "sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw==" + "integrity": "sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw==", + "license": "MIT" }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -13880,6 +15389,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", "engines": { "node": ">=8" } @@ -13887,12 +15397,14 @@ "node_modules/shimmer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause" }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", @@ -13911,6 +15423,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" @@ -13926,6 +15439,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -13943,6 +15457,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -13960,7 +15475,8 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" }, "node_modules/simple-concat": { "version": "1.0.1", @@ -13979,7 +15495,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/simple-get": { "version": "4.0.1", @@ -13999,6 +15516,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", @@ -14010,6 +15528,7 @@ "resolved": "https://registry.npmjs.org/sinon/-/sinon-17.0.1.tgz", "integrity": "sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0", "@sinonjs/fake-timers": "^11.2.2", @@ -14028,6 +15547,7 @@ "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", "dev": true, + "license": "(BSD-2-Clause OR WTFPL)", "peerDependencies": { "chai": "^4.0.0", "sinon": ">=4.0.0" @@ -14038,6 +15558,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, + "license": "MIT", "dependencies": { "is-fullwidth-code-point": "^2.0.0" }, @@ -14050,6 +15571,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -14057,24 +15579,26 @@ "node_modules/slow-redact": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/slow-redact/-/slow-redact-0.3.2.tgz", - "integrity": "sha512-MseHyi2+E/hBRqdOi5COy6wZ7j7DxXRz9NkseavNYSvvWC06D8a5cidVZX3tcG5eCW3NIyVU4zT63hw0Q486jw==" + "integrity": "sha512-MseHyi2+E/hBRqdOi5COy6wZ7j7DxXRz9NkseavNYSvvWC06D8a5cidVZX3tcG5eCW3NIyVU4zT63hw0Q486jw==", + "license": "MIT" }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true, + "license": "MIT", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" } }, "node_modules/snyk": { - "version": "1.1301.0", - "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.1301.0.tgz", - "integrity": "sha512-kTb8F9L1PlI3nYWlp60wnSGWGmcRs6bBtSBl9s8YYhAiFZNseIZfXolQXBSCaya5QlcxzfH1pb4aqCNMbi0tgg==", + "version": "1.1302.1", + "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.1302.1.tgz", + "integrity": "sha512-RT85Pz4N36xma7Mcob0Jno5TXu22VbVoT+7mWHk2TVkBHqsMZ8sKW55X+r+LMaT8GwlC5+cYjzw2iuv1VcPZOg==", "dev": true, "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { "@sentry/node": "^7.36.0", "global-agent": "^3.0.0" @@ -14090,7 +15614,7 @@ "version": "2.8.7", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "optional": true, + "license": "MIT", "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" @@ -14104,7 +15628,7 @@ "version": "8.0.5", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "optional": true, + "license": "MIT", "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", @@ -14118,7 +15642,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "optional": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -14135,12 +15659,13 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "optional": true + "license": "MIT" }, "node_modules/sonic-boom": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", - "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", + "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0" } @@ -14150,6 +15675,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "devOptional": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -14159,6 +15685,7 @@ "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^2.0.0", "is-windows": "^1.0.2", @@ -14171,11 +15698,51 @@ "node": ">=8" } }, + "node_modules/spawn-wrap/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/spawn-wrap/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -14185,28 +15752,32 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true + "dev": true, + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", - "dev": true + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", "engines": { "node": ">= 10.x" } @@ -14215,13 +15786,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/sqlite3": { "version": "5.1.7", "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^7.0.0", @@ -14244,6 +15817,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -14253,6 +15827,7 @@ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, + "license": "MIT", "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -14273,10 +15848,18 @@ "node": ">=0.10.0" } }, + "node_modules/sshpk/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "license": "Unlicense" + }, "node_modules/ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", "optional": true, "dependencies": { "minipass": "^3.1.1" @@ -14285,6 +15868,26 @@ "node": ">= 8" } }, + "node_modules/ssri/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ssri/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/stack-trace": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", @@ -14299,6 +15902,7 @@ "resolved": "https://registry.npmjs.org/standard/-/standard-12.0.1.tgz", "integrity": "sha512-UqdHjh87OG2gUrNCSM4QRLF5n9h3TFPwrCNyVlkqu31Hej0L/rc8hzKqVvkb2W3x0WMq7PzZdkLfEcBhVOR6lg==", "dev": true, + "license": "MIT", "dependencies": { "eslint": "~5.4.0", "eslint-config-standard": "12.0.0", @@ -14322,6 +15926,7 @@ "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-9.0.0.tgz", "integrity": "sha512-ZfNfCWZ2Xq67VNvKMPiVMKHnMdvxYzvZkf1AH8/cw2NLDBm5LRsxMqvEJpsjLI/dUosZ3Z1d6JlHDp5rAvvk2w==", "dev": true, + "license": "MIT", "dependencies": { "deglob": "^2.1.0", "get-stdin": "^6.0.0", @@ -14334,6 +15939,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -14346,6 +15952,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -14355,6 +15962,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -14367,6 +15975,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } @@ -14376,6 +15985,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -14390,6 +16000,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } @@ -14398,13 +16009,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/standard/node_modules/cross-spawn": { "version": "6.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "dev": true, + "license": "MIT", "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -14416,11 +16029,35 @@ "node": ">=4.8" } }, + "node_modules/standard/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/standard/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/standard/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -14431,6 +16068,7 @@ "integrity": "sha512-UIpL91XGex3qtL6qwyCQJar2j3osKxK9e3ano3OcGEIRM4oWIpCkDg9x95AXEC2wMs7PnxzOkPZ2gq+tsMS9yg==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.5.0", "babel-code-frame": "^6.26.0", @@ -14478,90 +16116,12 @@ "node": "^6.14.0 || ^8.10.0 || >=9.10.0" } }, - "node_modules/standard/node_modules/eslint-config-standard": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz", - "integrity": "sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ==", - "dev": true, - "peerDependencies": { - "eslint": ">=5.0.0", - "eslint-plugin-import": ">=2.13.0", - "eslint-plugin-node": ">=7.0.0", - "eslint-plugin-promise": ">=4.0.0", - "eslint-plugin-standard": ">=4.0.0" - } - }, - "node_modules/standard/node_modules/eslint-config-standard-jsx": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-6.0.2.tgz", - "integrity": "sha512-D+YWAoXw+2GIdbMBRAzWwr1ZtvnSf4n4yL0gKGg7ShUOGXkSOLerI17K4F6LdQMJPNMoWYqepzQD/fKY+tXNSg==", - "dev": true, - "peerDependencies": { - "eslint": ">=5.0.0", - "eslint-plugin-react": ">=7.11.1" - } - }, - "node_modules/standard/node_modules/eslint-plugin-import": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", - "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", - "dev": true, - "dependencies": { - "contains-path": "^0.1.0", - "debug": "^2.6.8", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.2.0", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", - "read-pkg-up": "^2.0.0", - "resolve": "^1.6.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "2.x - 5.x" - } - }, - "node_modules/standard/node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha512-lsGyRuYr4/PIB0txi+Fy2xOMI2dGaTguCaotzFGkVZuKR5usKfcRWIFKNM3QNrU7hh/+w2bwTW+ZeXPK5l8uVg==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/standard/node_modules/eslint-plugin-react": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz", - "integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==", - "dev": true, - "dependencies": { - "array-includes": "^3.0.3", - "doctrine": "^2.1.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.0.1", - "prop-types": "^15.6.2" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0" - } - }, "node_modules/standard/node_modules/eslint-scope": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" @@ -14575,24 +16135,17 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } }, - "node_modules/standard/node_modules/eslint/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/standard/node_modules/espree": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^6.0.2", "acorn-jsx": "^5.0.0", @@ -14607,6 +16160,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -14616,6 +16170,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", "integrity": "sha512-uXP/zGzxxFvFfcZGgBIwotm+Tdc55ddPAzF7iHshP4YGaXMww7rSF9peD9D1sui5ebONg5UobsZv+FfgEpGv/w==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^1.2.1", "object-assign": "^4.0.1" @@ -14629,6 +16184,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", "dev": true, + "license": "MIT", "dependencies": { "circular-json": "^0.3.1", "graceful-fs": "^4.1.2", @@ -14643,8 +16199,9 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -14665,6 +16222,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -14674,6 +16232,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -14683,21 +16242,17 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, - "node_modules/standard/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, "node_modules/standard/node_modules/js-yaml": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -14711,6 +16266,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -14724,6 +16280,7 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -14735,13 +16292,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/standard/node_modules/optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -14759,6 +16318,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -14778,6 +16338,7 @@ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -14790,6 +16351,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -14799,6 +16361,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^1.0.0" }, @@ -14811,6 +16374,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -14819,13 +16383,15 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/standard/node_modules/strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^3.0.0" }, @@ -14838,6 +16404,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -14847,6 +16414,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -14859,6 +16427,7 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2" }, @@ -14871,6 +16440,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -14879,9 +16449,10 @@ } }, "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -14891,6 +16462,7 @@ "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" @@ -14903,6 +16475,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.3.tgz", "integrity": "sha512-pqMqwQCso0PBJt2PQmDO0cFj0lyqmiwOMiMSkVtRokl7e+ZTRYgDHKnuZNbqjiJXgsg4nuqtD/zxuo9KqTp0Yw==", + "license": "Unlicense", "engines": { "node": ">= 0.10.0" } @@ -14911,6 +16484,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "license": "MIT", "dependencies": { "stubs": "^3.0.0" } @@ -14920,6 +16494,7 @@ "resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz", "integrity": "sha512-aI+qKFiwoDV4rsXiS7WRoCt+v2RX1nUj17+KJC5r2gfh5xoSJIfP6Y3Do/HtvesFcTSWthIuJ3l1cvKQY/+nZg==", "dev": true, + "license": "WTFPL", "dependencies": { "bluebird": "^2.6.2" } @@ -14927,7 +16502,8 @@ "node_modules/stream-shift": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", - "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "license": "MIT" }, "node_modules/streamsearch": { "version": "1.1.0", @@ -14937,20 +16513,34 @@ "node": ">=10.0.0" } }, + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, "node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "license": "MIT" }, "node_modules/string-format": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", - "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==" + "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", + "license": "WTFPL OR MIT" }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -14965,6 +16555,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -14979,6 +16570,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", @@ -15000,6 +16592,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", @@ -15018,6 +16611,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -15034,6 +16628,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -15046,6 +16641,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -15058,6 +16654,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -15066,6 +16663,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -15075,6 +16673,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -15091,12 +16690,14 @@ "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" } - ] + ], + "license": "MIT" }, "node_modules/stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==" + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "license": "MIT" }, "node_modules/superagent": { "version": "8.1.2", @@ -15104,6 +16705,7 @@ "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net", "dev": true, + "license": "MIT", "dependencies": { "component-emitter": "^1.3.0", "cookiejar": "^2.1.4", @@ -15125,6 +16727,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -15142,6 +16745,7 @@ "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.5.tgz", "integrity": "sha512-Oz5Hwvwak/DCaXVVUtPn4oLMLLy1CdclLKO1LFgU7XzDpVMUU5UjlSLpGMocyQNNk8F6IJW9M/YdooSn2MRI+Q==", "dev": true, + "license": "MIT", "dependencies": { "@paralleldrive/cuid2": "^2.2.2", "dezalgo": "^1.0.4", @@ -15157,6 +16761,7 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -15168,13 +16773,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/superagent/node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -15183,6 +16790,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -15194,6 +16802,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -15206,6 +16815,7 @@ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", "integrity": "sha512-Kb3PrPYz4HanVF1LVGuAdW6LoVgIwjUYJGzFe7NDrBLCN4lsV/5J0MFurV+ygS4bRVwrCEt2c7MQ1R2a72oJDw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -15215,6 +16825,7 @@ "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "ajv": "^6.0.1", "ajv-keywords": "^3.0.0", @@ -15231,6 +16842,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-4.1.1.tgz", "integrity": "sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==", + "license": "MIT", "dependencies": { "array-back": "^6.2.2", "wordwrapjs": "^5.1.0" @@ -15243,6 +16855,7 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "license": "MIT", "engines": { "node": ">=12.17" } @@ -15252,6 +16865,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -15261,6 +16875,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -15273,6 +16888,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -15287,6 +16903,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } @@ -15295,13 +16912,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/table/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -15311,6 +16930,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -15320,6 +16940,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -15329,6 +16950,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, + "license": "MIT", "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -15342,6 +16964,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^3.0.0" }, @@ -15354,6 +16977,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -15362,9 +16986,10 @@ } }, "node_modules/tar": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", - "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.9.tgz", + "integrity": "sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", @@ -15377,77 +17002,44 @@ } }, "node_modules/tar-fs": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", - "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", + "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", + "license": "MIT", "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-fs/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar-stream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "tar-stream": "^3.1.5" }, - "engines": { - "node": ">= 6" + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" } }, - "node_modules/tar-stream/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "license": "MIT", "dependencies": { - "safe-buffer": "~5.2.0" + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" } }, "node_modules/tar/node_modules/chownr": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", "engines": { "node": ">=18" } }, - "node_modules/tar/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/tar/node_modules/minizlib": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", "dependencies": { "minipass": "^7.1.2" }, @@ -15459,6 +17051,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", "engines": { "node": ">=18" } @@ -15467,6 +17060,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", + "license": "MIT", "optional": true, "dependencies": { "debug": "4.3.1", @@ -15477,6 +17071,7 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "license": "MIT", "optional": true, "dependencies": { "ms": "2.1.2" @@ -15494,12 +17089,14 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT", "optional": true }, "node_modules/teeny-request": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-10.1.0.tgz", "integrity": "sha512-3ZnLvgWF29jikg1sAQ1g0o+lr5JX6sVgYvfUJazn7ZjJroDBUTWp44/+cFVX0bULjv4vci+rBD+oGVAkWqhUbw==", + "license": "Apache-2.0", "dependencies": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", @@ -15510,18 +17107,11 @@ "node": ">=18" } }, - "node_modules/teeny-request/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, "node_modules/teeny-request/node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", "dependencies": { "debug": "4" }, @@ -15529,10 +17119,20 @@ "node": ">= 6.0.0" } }, + "node_modules/teeny-request/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/teeny-request/node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -15549,6 +17149,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "license": "MIT", "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -15562,6 +17163,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -15573,19 +17175,50 @@ "node_modules/teeny-request/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/teeny-request/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "license": "MIT", + "optional": true, + "dependencies": { + "streamx": "^2.12.5" + } }, "node_modules/teleport-javascript": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/teleport-javascript/-/teleport-javascript-1.0.0.tgz", "integrity": "sha512-j1llvWVFyEn/6XIFDfX5LAU43DXe0GCt3NfXDwJ8XpRRMkS+i50SAkonAONBy+vxwPFBd50MFU8a2uj8R/ccLg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -15599,8 +17232,9 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -15616,16 +17250,27 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/thread-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "license": "MIT", "dependencies": { "real-require": "^0.2.0" } @@ -15634,13 +17279,15 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/timers-ext": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", "dev": true, + "license": "ISC", "dependencies": { "es5-ext": "^0.10.64", "next-tick": "^1.1.0" @@ -15654,6 +17301,7 @@ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, + "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -15666,6 +17314,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -15677,6 +17326,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -15684,17 +17334,26 @@ "node_modules/toposort-class": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==", + "license": "MIT" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" }, @@ -15703,22 +17362,24 @@ } }, "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "license": "Unlicense" }, "node_modules/type": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -15731,6 +17392,7 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -15740,6 +17402,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } @@ -15748,6 +17411,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -15761,6 +17425,7 @@ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -15775,6 +17440,7 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", @@ -15794,6 +17460,7 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", @@ -15815,6 +17482,7 @@ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -15833,13 +17501,15 @@ "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, + "license": "MIT", "dependencies": { "is-typedarray": "^1.0.0" } @@ -15848,6 +17518,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "license": "MIT", "engines": { "node": ">=8" } @@ -15857,6 +17528,7 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, + "license": "BSD-2-Clause", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -15869,6 +17541,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "license": "MIT", "dependencies": { "random-bytes": "~1.0.0" }, @@ -15881,6 +17554,7 @@ "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", "dev": true, + "license": "MIT", "dependencies": { "bluebird": "^3.7.2" }, @@ -15892,13 +17566,15 @@ "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", @@ -15916,23 +17592,27 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/undici-types": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" }, "node_modules/uniq": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", "optional": true, "dependencies": { "unique-slug": "^2.0.0" @@ -15942,6 +17622,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", "optional": true, "dependencies": { "imurmurhash": "^0.1.4" @@ -15952,6 +17633,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.0.0" } @@ -15960,14 +17642,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/update-browserslist-db": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", - "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -15983,6 +17666,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" @@ -15999,6 +17683,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -16008,6 +17693,7 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, + "license": "MIT", "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -16016,12 +17702,14 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -16034,6 +17722,7 @@ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], + "license": "MIT", "bin": { "uuid": "dist/esm/bin/uuid" } @@ -16043,6 +17732,7 @@ "resolved": "https://registry.npmjs.org/uvm/-/uvm-2.1.1.tgz", "integrity": "sha512-BZ5w8adTpNNr+zczOBRpaX/hH8UPKAf7fmCnidrcsqt3bn8KT9bDIfuS7hgRU9RXgiN01su2pwysBONY6w8W5w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "flatted": "3.2.6" }, @@ -16054,22 +17744,25 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "node_modules/validator": { - "version": "13.15.23", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.23.tgz", - "integrity": "sha512-4yoz1kEWqUjzi5zsPbAS/903QXSYp0UOtHsPpp7p9rHAw/W+dkInskAE386Fat3oKRROwO98d9ZB0G4cObgUyw==", + "version": "13.15.26", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz", + "integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==", + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -16078,6 +17771,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -16090,6 +17784,7 @@ "engines": [ "node >=0.6.0" ], + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -16100,20 +17795,39 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/web-streams-polyfill": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", "engines": { "node": ">= 8" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -16129,6 +17843,7 @@ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, + "license": "MIT", "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", @@ -16148,6 +17863,7 @@ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", @@ -16174,13 +17890,15 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/which-collection": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, + "license": "MIT", "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", @@ -16198,13 +17916,15 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", @@ -16225,6 +17945,7 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", "optional": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" @@ -16234,6 +17955,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -16243,6 +17965,7 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -16251,12 +17974,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wordwrapjs": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.1.tgz", "integrity": "sha512-0yweIbkINJodk27gX9LBGMzyQdBDan3s/dEAiwBOj+Mf0PPyWL6/rikalkv8EeD0E8jm4o5RXEOrFTP3NXbhJg==", + "license": "MIT", "engines": { "node": ">=12.17" } @@ -16265,12 +17990,14 @@ "version": "6.5.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -16288,6 +18015,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -16303,13 +18031,15 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" }, "node_modules/write": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha512-CJ17OoULEKXpA5pef3qLj5AxTJ6mSt7g84he2WIskKwqFO4T97d5V7Tadl0DYDk7qyUOQD5WlUlOMChaYrhxeA==", "dev": true, + "license": "MIT", "dependencies": { "mkdirp": "^0.5.1" }, @@ -16322,6 +18052,7 @@ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -16334,6 +18065,7 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -16342,9 +18074,10 @@ } }, "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -16365,6 +18098,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "license": "MIT", "dependencies": { "is-wsl": "^3.1.0" }, @@ -16379,13 +18113,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0" } @@ -16394,6 +18130,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", "integrity": "sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==", + "license": "MIT", "engines": { "node": "*" } @@ -16403,6 +18140,7 @@ "resolved": "https://registry.npmjs.org/xss-clean/-/xss-clean-0.1.1.tgz", "integrity": "sha512-On99yydxoAEkHpraR7Wjg9cD6UmKfbtH2HXO1it2djid32osHL7Qr8bIu+dGYoOeKzf3ZszLfz1gwR/D7whZ2A==", "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", "dependencies": { "xss-filters": "1.2.6" } @@ -16416,6 +18154,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", "engines": { "node": ">=0.4" } @@ -16424,20 +18163,23 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "devOptional": true + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -16455,6 +18197,7 @@ "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "license": "ISC", "engines": { "node": ">=10" } @@ -16464,6 +18207,7 @@ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, + "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -16479,6 +18223,7 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -16491,6 +18236,7 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -16502,6 +18248,7 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", "engines": { "node": ">=12" } @@ -16510,6 +18257,7 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", "optional": true, "dependencies": { "buffer-crc32": "~0.2.3", @@ -16521,6 +18269,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index e47c67156..b6cfeae52 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@datasance/iofogcontroller", - "version": "3.6.0", + "version": "3.7.0", "description": "ioFog Controller project for Datasance PoT @ datasance.com \\nCopyright (c) 2023 Datasance Teknoloji A.S.", "main": "./src/main.js", "author": "Emirhan Durmus", @@ -9,13 +9,17 @@ "Alpaslan Doğan " ], "license": "EPL-2.0", + "engines": { + "node": "^24.0.0" + }, "bugs": { "email": "support@datasance.com" }, "standard": { "ignore": [ "test/**/*.js", - "src/lib/**/*.js" + "src/lib/**/*.js", + "src/utils/k8s-client.js" ] }, "homepage": "https://www.datasance.com", @@ -41,6 +45,7 @@ "snyk": "./node_modules/.bin/snyk monitor", "pretest": "npm run lint", "test": "node scripts/run-test.js test", + "test:k8s-client": "node scripts/run-test.js test --grep 'k8s-client'", "prepostman_test": "npm run lint", "postman_test": "node scripts/run-test.js postmantest", "precli-tests": "npm run lint", @@ -55,20 +60,22 @@ "iofog-controller": "src/main.js" }, "dependencies": { - "@aws-sdk/client-secrets-manager": "^3.981.0", - "@azure/keyvault-secrets": "^4.10.0", + "@aws-sdk/client-secrets-manager": "^3.999.0", "@azure/identity": "^4.13.0", - "@datasance/ecn-viewer": "1.3.0", + "@azure/keyvault-secrets": "^4.10.0", + "@datasance/ecn-viewer": "1.4.2", "@google-cloud/secret-manager": "^6.1.1", - "@kubernetes/client-node": "^0.22.3", + "@kubernetes/client-node": "^1.4.0", "@msgpack/msgpack": "^3.1.2", + "@nats-io/jwt": "^0.0.10-5", + "@nats-io/nkeys": "^2.0.3", "@opentelemetry/api": "^1.9.0", "@opentelemetry/exporter-trace-otlp-http": "^0.200.0", "@opentelemetry/instrumentation-express": "^0.48.1", "@opentelemetry/instrumentation-http": "^0.200.0", "@opentelemetry/resources": "^1.8.0", "@opentelemetry/sdk-node": "^0.200.0", - "axios": "1.12.2", + "axios": "1.13.5", "bignumber.js": "^9.3.0", "body-parser": "^1.20.4", "command-line-args": "5.2.1", @@ -99,10 +106,10 @@ "pino": "9.13.1", "pino-std-serializers": "7.0.0", "portscanner": "2.2.0", - "qs": "6.14.1", + "sqlite3": "^5.1.7", + "qs": "6.14.2", "rhea": "^3.0.4", "sequelize": "6.37.7", - "sqlite3": "^5.1.7", "string-format": "2.0.0", "uuid": "11.1.0", "ws": "^8.18.0", @@ -139,18 +146,23 @@ ], "type": "commonjs", "overrides": { - "@kubernetes/client-node": { - "request": "@cypress/request@3.0.8" + "sequelize": { + "validator": "^13.15.22" }, "sqlite3": { "prebuild-install": { "tar-fs": "^2.1.4" } }, - "sequelize": { - "validator": "^13.15.22" + "@aws-sdk/client-secrets-manager": { + "@aws-sdk/core": { + "fast-xml-parser": "^5.3.8" + } }, - "tar": "^7.5.7", - "lodash": "^4.17.23" + "tar": "^7.5.8", + "lodash": "^4.17.23", + "bn.js": "^5.2.3", + "minimatch": "10.2.3", + "dottie": "^2.0.7" } } diff --git a/scripts/run-test.js b/scripts/run-test.js index 14f1e5e30..e6eb8230c 100644 --- a/scripts/run-test.js +++ b/scripts/run-test.js @@ -17,10 +17,13 @@ const { coverage } = require('./coverage') const { postmanTest } = require('./postmantest') switch (process.argv[2]) { - case 'test': - test(process.argv[3] === 'junit') + case 'test': { + const useReporter = process.argv[3] === 'junit' + const extraArgs = process.argv.slice(useReporter ? 4 : 3).filter(Boolean) + test(useReporter, extraArgs) cliTest() break + } case 'cli-tests': cliTest() break diff --git a/scripts/test.js b/scripts/test.js index b53c9beff..3236bbd3b 100644 --- a/scripts/test.js +++ b/scripts/test.js @@ -16,7 +16,7 @@ const path = require('path') const { setDbEnvVars } = require('./util') -function test (useReporter) { +function test (useReporter, extraArgs) { const options = { env: { 'NODE_ENV': 'test', @@ -30,8 +30,13 @@ function test (useReporter) { const mochaBin = path.join(__dirname, '..', 'node_modules', 'mocha', 'bin', 'mocha') const mochaReporterOptions = '--reporter mocha-junit-reporter --reporter-options mochaFile=./unit-results.xml' - const mocha = useReporter ? [mochaBin, mochaReporterOptions].join(' ') : mochaBin - execSync(mocha, options) + let mochaCmd = useReporter ? [mochaBin, mochaReporterOptions].join(' ') : mochaBin + if (extraArgs && extraArgs.length) { + mochaCmd += ' ' + extraArgs.map(a => (a.includes(' ') ? `"${a}"` : a)).join(' ') + execSync(`node "${mochaBin}" ${mochaCmd.slice(mochaBin.length).trim()}`, options) + } else { + execSync(mochaCmd, options) + } } module.exports = { diff --git a/src/cli/microservice.js b/src/cli/microservice.js index 589b0cde8..59a7002b3 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -53,9 +53,6 @@ const JSON_SCHEMA_ADD = AppHelper.stringifyCliJsonSchema( publicMode: true } ], - routes: [ - 'string' - ], env: [ { key: 'string', @@ -264,21 +261,6 @@ class Microservice extends BaseCLIHandler { description: 'Container port mapping', group: [constants.CMD_PORT_MAPPING_CREATE, constants.CMD_VOLUME_MAPPING_CREATE] }, - { - name: 'routes', - alias: 't', - type: String, - description: 'Microservice route(s) (receiving microservices)', - multiple: true, - group: [constants.CMD_ADD] - }, - { - name: 'route', - alias: 'T', - type: String, - description: 'Microservice route (receiving microservices)', - group: [constants.CMD_ROUTE_CREATE, constants.CMD_ROUTE_REMOVE] - }, { name: 'internal-port', alias: 'b', @@ -378,8 +360,6 @@ class Microservice extends BaseCLIHandler { [constants.CMD_REMOVE]: 'Delete a microservice.', [constants.CMD_LIST]: 'List all microservices.', [constants.CMD_INFO]: 'Get microservice settings.', - [constants.CMD_ROUTE_CREATE]: 'Create microservice route.', - [constants.CMD_ROUTE_REMOVE]: 'Remove microservice route.', [constants.CMD_PORT_MAPPING_CREATE]: 'Create microservice port mapping.', [constants.CMD_PORT_MAPPING_REMOVE]: 'Remove microservice port mapping.', [constants.CMD_PORT_MAPPING_LIST]: 'List microservice port mapping.', @@ -413,12 +393,6 @@ class Microservice extends BaseCLIHandler { case constants.CMD_INFO: await _executeCase(microserviceCommand, constants.CMD_INFO, _getMicroservice) break - case constants.CMD_ROUTE_CREATE: - await _executeCase(microserviceCommand, constants.CMD_ROUTE_CREATE, _createRoute) - break - case constants.CMD_ROUTE_REMOVE: - await _executeCase(microserviceCommand, constants.CMD_ROUTE_REMOVE, _removeRoute) - break case constants.CMD_PORT_MAPPING_CREATE: await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_CREATE, _createPortMapping) break @@ -479,19 +453,7 @@ class Microservice extends BaseCLIHandler { example: '$ iofog-controller microservice add [other required options] --ports 80:8080:false 443:5443:false' }, { - desc: '4. Add routes (ABC:DEF - source microservice uuid : dest microservice uuid)', - example: '$ iofog-controller microservice add [other required options] --routes ABC:DEF RFG:HJK' - }, - { - desc: '5. Add route (ABC:DEF - source microservice uuid : dest microservice uuid)', - example: '$ iofog-controller microservice route-create --route ABC:DEF' - }, - { - desc: '6. Delete route (ABC:DEF - source microservice uuid : dest microservice uuid)', - example: '$ iofog-controller microservice route-remove --route ABC:DEF' - }, - { - desc: '7. Create port mapping (80:8080:false - internal port : external port : public mode, ABC - microservice)', + desc: '4. Create port mapping (80:8080:false - internal port : external port : public mode, ABC - microservice)', example: '$ iofog-controller microservice port-mapping-create --mapping 80:8080:false -i ABC' }, { @@ -521,34 +483,6 @@ async function _executeCase (commands, commandName, f) { } } -const _createRoute = async function (obj) { - try { - const arr = obj.route.split(':') - const sourceMicroserviceUuid = arr[0] - const destMicroserviceUuid = arr[1] - logger.cliReq('microservice route-create', { args: { source: sourceMicroserviceUuid, dest: destMicroserviceUuid } }) - await MicroserviceService.createRouteEndPoint(sourceMicroserviceUuid, destMicroserviceUuid, true) - logger.cliRes(`Microservice route with source microservice ${sourceMicroserviceUuid} and dest microservice - ${destMicroserviceUuid} has been created successfully.`) - } catch (e) { - logger.error(ErrorMessages.CLI.INVALID_ROUTE) - } -} - -const _removeRoute = async function (obj) { - try { - const arr = obj.route.split(':') - const sourceMicroserviceUuid = arr[0] - const destMicroserviceUuid = arr[1] - logger.cliReq('microservice route-remove', { args: { source: sourceMicroserviceUuid, dest: destMicroserviceUuid } }) - await MicroserviceService.deleteRouteEndPoint(sourceMicroserviceUuid, destMicroserviceUuid, true) - logger.cliRes('Microservice route with source microservice ' + sourceMicroserviceUuid + - ' and dest microservice ' + destMicroserviceUuid + 'has been removed successfully.') - } catch (e) { - logger.error(ErrorMessages.CLI.INVALID_ROUTE) - } -} - const _createPortMapping = async function (obj) { const mapping = parsePortMappingObject(obj.mapping, ErrorMessages.CLI.INVALID_PORT_MAPPING) logger.cliReq('microservice port-mapping-create', { args: mapping }) @@ -737,7 +671,6 @@ const _createMicroserviceObject = function (obj) { hostNetworkMode: obj.hostNetworkMode, isPrivileged: obj.isPrivileged, logSize: (obj.logSize || constants.MICROSERVICE_DEFAULT_LOG_SIZE) * 1, - routes: obj.routes, cmd: obj.cmd, cdiDevices: obj.cdiDevices, capAdd: obj.capAdd, diff --git a/src/config/config.yaml b/src/config/config.yaml index 558464dd7..b63884151 100644 --- a/src/config/config.yaml +++ b/src/config/config.yaml @@ -60,6 +60,9 @@ settings: controllerHeartbeatInterval: 30 # Controller heartbeat interval in seconds (default: 30) controllerInactiveThreshold: 300 # Mark controller inactive after N seconds without heartbeat (default: 300 = 5 minutes) controllerCleanupInterval: 600 # Controller cleanup job interval in seconds (default: 600 = 10 minutes) + natsReconcileChunkSize: 1 # NATS reconcile task chunk size in fogs per task (default: 1) + natsReconcileTaskStalenessSeconds: 900 # NATS reconcile task staleness for reclaim (default: 900 = 15 minutes) + natsReconcileWorkerIntervalSeconds: 3 # NATS reconcile worker poll interval in seconds (default: 3) # Database Configuration database: @@ -81,7 +84,7 @@ database: # useSSL: false # Use SSL for PostgreSQL connection # sslCA: "" # PostgreSQL SSL CA in base64 encoded string sqlite: - databaseName: dev_database.sqlite # SQLite database file name + databaseName: controller_db.sqlite # SQLite database file name logging: false # Enable SQLite query logging transactionType: IMMEDIATE # SQLite transaction type pool: @@ -113,6 +116,13 @@ systemImages: debug: "1": "ghcr.io/datasance/node-debugger:latest" "2": "ghcr.io/datasance/node-debugger:latest" + nats: + "1": "ghcr.io/datasance/nats:latest" + "2": "ghcr.io/datasance/nats:latest" + +# NATS Configuration +nats: + enabled: true # Diagnostics Configuration diagnostics: @@ -124,13 +134,13 @@ diagnostics: # in the configured vault provider instead of encrypted in the database # vault: # enabled: false # Enable/disable vault integration -# provider: hashicorp # Provider: hashicorp, aws, azure, google +# provider: hashicorp # Provider: hashicorp, openbao, vault, aws, aws-secrets-manager, azure, azure-key-vault, google, google-secret-manager # basePath: "pot/$namespace/secrets" # Base path for secrets in vault ($namespace will be replaced with app.namespace) # # HashiCorp Vault configuration # hashicorp: # address: "http://localhost:8200" # Vault server address (can also be set via VAULT_HASHICORP_ADDRESS env var) # token: "" # Vault token (can also be set via VAULT_HASHICORP_TOKEN env var) -# mount: "secret" # Vault mount point (can also be set via VAULT_HASHICORP_MOUNT env var) +# mount: "kv" # Vault mount point (can also be set via VAULT_HASHICORP_MOUNT env var) # # AWS Secrets Manager configuration # aws: # region: "us-east-1" # AWS region (can also be set via VAULT_AWS_REGION or AWS_REGION env var) diff --git a/src/config/env-mapping.js b/src/config/env-mapping.js index 9f4e255af..df23535dd 100644 --- a/src/config/env-mapping.js +++ b/src/config/env-mapping.js @@ -91,6 +91,11 @@ module.exports = { 'ROUTER_IMAGE_2': 'systemImages.router.2', 'DEBUG_IMAGE_1': 'systemImages.debug.1', 'DEBUG_IMAGE_2': 'systemImages.debug.2', + 'NATS_IMAGE_1': 'systemImages.nats.1', + 'NATS_IMAGE_2': 'systemImages.nats.2', + + // NATS Configuration + 'NATS_ENABLED': 'nats.enabled', // Diagnostics Configuration 'DIAGNOSTICS_DIRECTORY': 'diagnostics.directory', diff --git a/src/config/nats-system-rules.js b/src/config/nats-system-rules.js new file mode 100644 index 000000000..8bcd63e0d --- /dev/null +++ b/src/config/nats-system-rules.js @@ -0,0 +1,146 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2023 Datasance Teknoloji A.S. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +'use strict' + +const SYSTEM_ACCOUNT_RULE_NAME = 'default-system-account' +const APPLICATION_ACCOUNT_RULE_NAME = 'default-account' +const MICROSERVICE_USER_RULE_NAME = 'default-user' +const MQTT_BEARER_USER_RULE_NAME = 'default-mqtt-user' +const DEFAULT_LEAF_USER_RULE_NAME = 'default-leaf-user' + +const SYS_ACCOUNT_EXPORTS_INLINE = Object.freeze([ + Object.freeze({ + name: 'account-monitoring-streams', + subject: '$SYS.ACCOUNT.*.>', + type: 'stream', + account_token_position: 3, + description: 'Account specific monitoring stream', + info_url: 'https://docs.nats.io/nats-server/configuration/sys_accounts' + }), + Object.freeze({ + name: 'account-monitoring-services', + subject: '$SYS.REQ.ACCOUNT.*.*', + type: 'service', + response_type: 'Stream', + account_token_position: 4, + description: 'Request account specific monitoring services for: SUBSZ, CONNZ, LEAFZ, JSZ and INFO', + info_url: 'https://docs.nats.io/nats-server/configuration/sys_accounts' + }) +]) + +const ACCOUNT_RULES = Object.freeze([ + Object.freeze({ + name: SYSTEM_ACCOUNT_RULE_NAME, + description: 'Default system account rule', + exports: SYS_ACCOUNT_EXPORTS_INLINE, + maxLeafNodeConnections: -1, + maxImports: -1, + maxExports: -1, + maxConnections: -1, + maxData: -1, + maxMsgPayload: -1, + maxSubscriptions: -1, + exportsAllowWildcards: true + }), + Object.freeze({ + name: APPLICATION_ACCOUNT_RULE_NAME, + description: 'Default application account rule', + memStorage: -1, + diskStorage: -1, + streams: -1, + maxAckPending: -1, + memMaxStreamBytes: -1, + diskMaxStreamBytes: -1, + consumer: -1, + maxLeafNodeConnections: -1, + maxImports: -1, + maxExports: -1, + maxConnections: -1, + maxData: -1, + maxMsgPayload: -1, + maxSubscriptions: -1, + exportsAllowWildcards: true + }) +]) + +const USER_RULES = Object.freeze([ + Object.freeze({ + name: MICROSERVICE_USER_RULE_NAME, + description: 'Default microservice user rule', + bearerToken: false, + allowedConnectionTypes: ['STANDARD', 'WEBSOCKET'], + maxData: -1, + maxSubscriptions: -1, + maxPayload: -1 + }), + Object.freeze({ + name: MQTT_BEARER_USER_RULE_NAME, + description: 'Default MQTT bearer user rule', + bearerToken: true, + maxData: -1, + maxSubscriptions: -1, + maxPayload: -1, + allowedConnectionTypes: ['MQTT', 'STANDARD'] + }), + Object.freeze({ + name: DEFAULT_LEAF_USER_RULE_NAME, + description: 'Default leaf node user rule for remote connection from leaf to server', + bearerToken: false, + maxData: -1, + maxSubscriptions: -1, + maxPayload: -1, + allowedConnectionTypes: ['LEAFNODE', 'WEBSOCKET'] + }) +]) + +const RESERVED_RULE_NAMES = new Set([ + ...ACCOUNT_RULES.map((rule) => rule.name), + ...USER_RULES.map((rule) => rule.name) +]) + +function isReservedRuleName (name) { + return RESERVED_RULE_NAMES.has(name) +} + +function getSystemAccountRuleDefinitions () { + return ACCOUNT_RULES.map((rule) => ({ ...rule })) +} + +function getSystemUserRuleDefinitions () { + return USER_RULES.map((rule) => ({ ...rule })) +} + +function getSystemAccountRuleByName (name) { + const rule = ACCOUNT_RULES.find((item) => item.name === name) + return rule ? { ...rule } : null +} + +function getSystemUserRuleByName (name) { + const rule = USER_RULES.find((item) => item.name === name) + return rule ? { ...rule } : null +} + +module.exports = { + SYSTEM_ACCOUNT_RULE_NAME, + SYS_ACCOUNT_EXPORTS_INLINE, + APPLICATION_ACCOUNT_RULE_NAME, + MICROSERVICE_USER_RULE_NAME, + MQTT_BEARER_USER_RULE_NAME, + DEFAULT_LEAF_USER_RULE_NAME, + isReservedRuleName, + getSystemAccountRuleDefinitions, + getSystemUserRuleDefinitions, + getSystemAccountRuleByName, + getSystemUserRuleByName +} diff --git a/src/config/rbac-resources.yaml b/src/config/rbac-resources.yaml index 84b735930..bd6696215 100644 --- a/src/config/rbac-resources.yaml +++ b/src/config/rbac-resources.yaml @@ -24,14 +24,6 @@ resources: PUT: [update] DELETE: [delete] resourceNameParam: uuid - - path: /api/v3/microservices/pub/:tag - methods: - GET: [get] - resourceNameParam: tag - - path: /api/v3/microservices/sub/:tag - methods: - GET: [get] - resourceNameParam: tag - path: /api/v3/microservices/:uuid/rebuild methods: PATCH: [patch] @@ -46,11 +38,6 @@ resources: PATCH: [patch] DELETE: [delete] resourceNameParam: uuid - - path: /api/v3/microservices/:uuid/routes/:receiverUuid - methods: - POST: [patch] - DELETE: [patch] - resourceNameParam: uuid - path: /api/v3/microservices/:uuid/port-mapping methods: GET: [get] @@ -270,29 +257,120 @@ resources: DELETE: [delete] resourceNameParam: uuid - # Routings - routings: - basePath: /api/v3/routes + # Router + router: + basePath: /api/v3/router + routes: + - path: /api/v3/router + methods: + GET: [get] + PUT: [update] + + # NATS (granular resources) + natsOperator: + basePath: /api/v3/nats + routes: + - path: /api/v3/nats/operator + methods: + GET: [get] + - path: /api/v3/nats/operator/rotate + methods: + POST: [update] + + natsBootstrap: + basePath: /api/v3/nats + routes: + - path: /api/v3/nats/bootstrap + methods: + GET: [get] + + natsHub: + basePath: /api/v3/nats + routes: + - path: /api/v3/nats/hub + methods: + GET: [get] + PUT: [update] + + natsAccounts: + basePath: /api/v3/nats + routes: + - path: /api/v3/nats/accounts + methods: + GET: [list] + - path: /api/v3/nats/accounts/:appName + methods: + GET: [get] + POST: [create] + resourceNameParam: appName + + natsUsers: + basePath: /api/v3/nats routes: - - path: /api/v3/routes + - path: /api/v3/nats/users + methods: + GET: [list] + - path: /api/v3/nats/accounts/:appName/users methods: GET: [list] POST: [create] - - path: /api/v3/routes/:appName/:name + resourceNameParam: appName + - path: /api/v3/nats/accounts/:appName/users/:userName + methods: + DELETE: [delete] + resourceNameParam: appName + - path: /api/v3/nats/accounts/:appName/users/:userName/creds methods: GET: [get] + resourceNameParam: appName + - path: /api/v3/nats/accounts/:appName/mqtt-bearer + methods: + POST: [create] + resourceNameParam: appName + - path: /api/v3/nats/accounts/:appName/mqtt-bearer/:userName + methods: + DELETE: [delete] + resourceNameParam: appName + + natsAccountRules: + basePath: /api/v3/nats/account-rules + routes: + - path: /api/v3/nats/account-rules + methods: + GET: [list] + POST: [create] + - path: /api/v3/nats/account-rules/:ruleName + methods: PATCH: [patch] DELETE: [delete] - resourceNameParam: name + resourceNameParam: ruleName + - path: /api/v3/nats/account-rules/yaml + methods: + POST: [create] + - path: /api/v3/nats/account-rules/yaml/:ruleName + methods: + PATCH: [patch] + resourceNameParam: ruleName - # Router - router: - basePath: /api/v3/router + natsUserRules: + basePath: /api/v3/nats/user-rules routes: - - path: /api/v3/router + - path: /api/v3/nats/user-rules methods: - GET: [get] - PUT: [update] + GET: [list] + POST: [create] + - path: /api/v3/nats/user-rules/:ruleName + methods: + PATCH: [patch] + DELETE: [delete] + resourceNameParam: ruleName + - path: /api/v3/nats/user-rules/yaml + methods: + POST: [create] + - path: /api/v3/nats/user-rules/yaml/:ruleName + methods: + PATCH: [patch] + resourceNameParam: ruleName # Services services: @@ -543,6 +621,9 @@ resources: - path: /api/v3/capabilities/applicationTemplates methods: HEAD: [get] + - path: /api/v3/capabilities/nats + methods: + HEAD: [get] # Events events: @@ -745,11 +826,11 @@ resources: - path: /api/v3/serviceaccounts/yaml methods: POST: [create] - - path: /api/v3/serviceaccounts/yaml/:name + - path: /api/v3/serviceaccounts/yaml/:appName/:name methods: PATCH: [patch] resourceNameParam: name - - path: /api/v3/serviceaccounts/:name + - path: /api/v3/serviceaccounts/:appName/:name methods: GET: [get] PATCH: [patch] diff --git a/src/config/rbac-system-roles.js b/src/config/rbac-system-roles.js index f15237cc1..cbbc24faa 100644 --- a/src/config/rbac-system-roles.js +++ b/src/config/rbac-system-roles.js @@ -48,12 +48,12 @@ module.exports = { rules: [ { apiGroups: [''], - resources: ['microservices', 'systemMicroservices', 'fogs', 'applications', 'systemApplications', 'applicationTemplates', 'services', 'routings', 'router', 'flows', 'catalog', 'registries', 'secrets', 'configMaps', 'volumeMounts', 'tunnels', 'certificates', 'edgeResources', 'capabilities', 'diagnostics', 'serviceAccounts', 'events', 'users', 'config', 'controller', 'execSessions', 'systemExecSessions', 'logs', 'systemLogs'], + resources: ['microservices', 'systemMicroservices', 'fogs', 'applications', 'systemApplications', 'applicationTemplates', 'services', 'router', 'natsAccounts', 'natsUsers', 'natsAccountRules', 'natsUserRules', 'flows', 'catalog', 'registries', 'secrets', 'configMaps', 'volumeMounts', 'tunnels', 'certificates', 'edgeResources', 'capabilities', 'diagnostics', 'serviceAccounts', 'events', 'users', 'config', 'controller', 'execSessions', 'systemExecSessions', 'logs', 'systemLogs'], verbs: ['*'] }, { apiGroups: [''], - resources: ['roles', 'roleBindings'], + resources: ['roles', 'roleBindings', 'natsOperator', 'natsHub'], verbs: ['get', 'list'] } ] @@ -68,12 +68,12 @@ module.exports = { rules: [ { apiGroups: [''], - resources: ['microservices', 'applications', 'applicationTemplates', 'services', 'routings', 'flows', 'catalog', 'registries', 'secrets', 'configMaps', 'volumeMounts', 'certificates', 'edgeResources', 'capabilities', 'diagnostics', 'serviceAccounts', 'controller', 'execSessions', 'logs'], + resources: ['microservices', 'applications', 'applicationTemplates', 'services', 'natsAccounts', 'natsUsers', 'natsAccountRules', 'natsUserRules', 'flows', 'catalog', 'registries', 'secrets', 'configMaps', 'volumeMounts', 'certificates', 'edgeResources', 'capabilities', 'diagnostics', 'serviceAccounts', 'controller', 'execSessions', 'logs'], verbs: ['get', 'list', 'create', 'update', 'patch', 'delete'] }, { apiGroups: [''], - resources: ['fogs', 'router', 'tunnels', 'users', 'config', 'roles', 'roleBindings', 'systemMicroservices', 'systemApplications'], + resources: ['fogs', 'router', 'tunnels', 'users', 'config', 'roles', 'roleBindings', 'systemMicroservices', 'systemApplications', 'natsOperator', 'natsHub'], verbs: ['get', 'list'] } ] @@ -88,7 +88,7 @@ module.exports = { rules: [ { apiGroups: [''], - resources: ['microservices', 'fogs', 'applications', 'systemMicroservices', 'systemApplications', 'applicationTemplates', 'services', 'routings', 'router', 'flows', 'catalog', 'registries', 'secrets', 'configMaps', 'volumeMounts', 'certificates', 'edgeResources', 'capabilities', 'diagnostics', 'serviceAccounts', 'config', 'controller', 'roles', 'roleBindings'], + resources: ['microservices', 'fogs', 'applications', 'systemMicroservices', 'systemApplications', 'applicationTemplates', 'services', 'router', 'natsOperator', 'natsHub', 'natsAccounts', 'natsUsers', 'natsAccountRules', 'natsUserRules', 'flows', 'catalog', 'registries', 'secrets', 'configMaps', 'volumeMounts', 'certificates', 'edgeResources', 'capabilities', 'diagnostics', 'serviceAccounts', 'config', 'controller', 'roles', 'roleBindings'], verbs: ['get', 'list'] } ] @@ -135,12 +135,6 @@ module.exports = { resources: ['config'], verbs: ['get'] }, - { - apiGroups: ['agent.datasance.com/v3'], - resources: ['message'], - verbs: ['post'] - // Note: WebSocket 'get' for message is handled separately by agent - }, { apiGroups: ['agent.datasance.com/v3'], resources: ['log'], diff --git a/src/controllers/microservices-controller.js b/src/controllers/microservices-controller.js index 7fa9b677c..daf1659b1 100644 --- a/src/controllers/microservices-controller.js +++ b/src/controllers/microservices-controller.js @@ -37,16 +37,6 @@ const getSystemMicroserviceEndPoint = async function (req) { return MicroservicesService.getSystemMicroserviceEndPoint(microserviceUuid, false) } -const listMicroserviceByPubTagEndPoint = async function (req) { - const pubTag = req.params.tag - return MicroservicesService.listMicroserviceByPubTagEndPoint(pubTag) -} - -const listMicroserviceBySubTagEndPoint = async function (req) { - const subTag = req.params.tag - return MicroservicesService.listMicroserviceBySubTagEndPoint(subTag) -} - const updateMicroserviceEndPoint = async function (req) { const microservice = req.body const microserviceUuid = req.params.uuid @@ -139,18 +129,6 @@ const getSystemMicroservicesByApplicationEndPoint = async function (req) { return MicroservicesService.listSystemMicroservicesEndPoint({ applicationName, flowId }, false) } -const createMicroserviceRouteEndPoint = async function (req) { - const sourceUuid = req.params.uuid - const destUuid = req.params.receiverUuid - return MicroservicesService.createRouteEndPoint(sourceUuid, destUuid, false) -} - -const deleteMicroserviceRouteEndPoint = async function (req) { - const sourceUuid = req.params.uuid - const destUuid = req.params.receiverUuid - return MicroservicesService.deleteRouteEndPoint(sourceUuid, destUuid, false) -} - const createMicroservicePortMappingEndPoint = async function (req) { const uuid = req.params.uuid const portMappingData = req.body @@ -255,8 +233,6 @@ module.exports = { createMicroserviceOnFogEndPoint: (createMicroserviceOnFogEndPoint), getMicroserviceEndPoint: (getMicroserviceEndPoint), getSystemMicroserviceEndPoint: (getSystemMicroserviceEndPoint), - listMicroserviceByPubTagEndPoint: (listMicroserviceByPubTagEndPoint), - listMicroserviceBySubTagEndPoint: (listMicroserviceBySubTagEndPoint), updateMicroserviceEndPoint: (updateMicroserviceEndPoint), updateSystemMicroserviceEndPoint: (updateSystemMicroserviceEndPoint), rebuildMicroserviceEndPoint: (rebuildMicroserviceEndPoint), @@ -264,8 +240,6 @@ module.exports = { deleteMicroserviceEndPoint: (deleteMicroserviceEndPoint), getMicroservicesByApplicationEndPoint: (getMicroservicesByApplicationEndPoint), getSystemMicroservicesByApplicationEndPoint: (getSystemMicroservicesByApplicationEndPoint), - createMicroserviceRouteEndPoint: (createMicroserviceRouteEndPoint), - deleteMicroserviceRouteEndPoint: (deleteMicroserviceRouteEndPoint), createMicroservicePortMappingEndPoint: (createMicroservicePortMappingEndPoint), createSystemMicroservicePortMappingEndPoint: (createSystemMicroservicePortMappingEndPoint), deleteMicroservicePortMappingEndPoint: (deleteMicroservicePortMappingEndPoint), diff --git a/src/controllers/nats-controller.js b/src/controllers/nats-controller.js new file mode 100644 index 000000000..3b55605f8 --- /dev/null +++ b/src/controllers/nats-controller.js @@ -0,0 +1,167 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2023 Datasance Teknoloji A.S. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const NatsApiService = require('../services/nats-api-service') +const YamlParserService = require('../services/yaml-parser-service') + +const getOperatorEndPoint = async function () { + return NatsApiService.getOperator() +} + +const rotateOperatorEndPoint = async function () { + return NatsApiService.rotateOperator() +} + +const getBootstrapEndPoint = async function () { + return NatsApiService.getBootstrap() +} + +const getHubEndPoint = async function () { + return NatsApiService.getHub() +} + +const upsertHubEndPoint = async function (req) { + return NatsApiService.upsertHub(req.body || {}) +} + +const listAccountsEndPoint = async function () { + return NatsApiService.listAccounts() +} + +const getAccountEndPoint = async function (req) { + return NatsApiService.getAccount(req.params.appName) +} + +const ensureAccountEndPoint = async function (req) { + return NatsApiService.ensureAccount(req.params.appName, req.body || {}) +} + +const listAllUsersEndPoint = async function () { + return NatsApiService.listAllUsers() +} + +const listUsersEndPoint = async function (req) { + return NatsApiService.listUsers(req.params.appName) +} + +const createUserEndPoint = async function (req) { + return NatsApiService.createUser(req.params.appName, req.body || {}) +} + +const getUserCredsEndPoint = async function (req) { + return NatsApiService.getUserCreds(req.params.appName, req.params.userName) +} + +const deleteUserEndPoint = async function (req) { + await NatsApiService.deleteUser(req.params.appName, req.params.userName) +} + +const createMqttBearerEndPoint = async function (req) { + return NatsApiService.createMqttBearer(req.params.appName, req.body || {}) +} + +const deleteMqttBearerEndPoint = async function (req) { + await NatsApiService.deleteMqttBearer(req.params.appName, req.params.userName) +} + +const listAccountRulesEndPoint = async function () { + return NatsApiService.listAccountRules() +} + +const createAccountRuleEndPoint = async function (req) { + return NatsApiService.createAccountRule(req.body || {}) +} + +const updateAccountRuleEndPoint = async function (req) { + return NatsApiService.updateAccountRule(req.params.ruleName, req.body || {}) +} + +const deleteAccountRuleEndPoint = async function (req) { + await NatsApiService.deleteAccountRule(req.params.ruleName) +} + +const listUserRulesEndPoint = async function () { + return NatsApiService.listUserRules() +} + +const createUserRuleEndPoint = async function (req) { + return NatsApiService.createUserRule(req.body || {}) +} + +const updateUserRuleEndPoint = async function (req) { + return NatsApiService.updateUserRule(req.params.ruleName, req.body || {}) +} + +const deleteUserRuleEndPoint = async function (req) { + await NatsApiService.deleteUserRule(req.params.ruleName) +} + +const createAccountRuleFromYamlEndPoint = async function (req) { + const fileContent = req.file.buffer.toString() + const ruleData = await YamlParserService.parseNatsAccountRuleFile(fileContent) + return NatsApiService.createAccountRule(ruleData) +} + +const updateAccountRuleFromYamlEndPoint = async function (req) { + const fileContent = req.file.buffer.toString() + const ruleData = await YamlParserService.parseNatsAccountRuleFile(fileContent, { + isUpdate: true, + ruleName: req.params.ruleName + }) + return NatsApiService.updateAccountRule(req.params.ruleName, ruleData) +} + +const createUserRuleFromYamlEndPoint = async function (req) { + const fileContent = req.file.buffer.toString() + const ruleData = await YamlParserService.parseNatsUserRuleFile(fileContent) + return NatsApiService.createUserRule(ruleData) +} + +const updateUserRuleFromYamlEndPoint = async function (req) { + const fileContent = req.file.buffer.toString() + const ruleData = await YamlParserService.parseNatsUserRuleFile(fileContent, { + isUpdate: true, + ruleName: req.params.ruleName + }) + return NatsApiService.updateUserRule(req.params.ruleName, ruleData) +} + +module.exports = { + getOperatorEndPoint, + rotateOperatorEndPoint, + getBootstrapEndPoint, + getHubEndPoint, + upsertHubEndPoint, + listAccountsEndPoint, + getAccountEndPoint, + ensureAccountEndPoint, + listAllUsersEndPoint, + listUsersEndPoint, + createUserEndPoint, + getUserCredsEndPoint, + deleteUserEndPoint, + createMqttBearerEndPoint, + deleteMqttBearerEndPoint, + listAccountRulesEndPoint, + createAccountRuleEndPoint, + updateAccountRuleEndPoint, + deleteAccountRuleEndPoint, + createAccountRuleFromYamlEndPoint, + updateAccountRuleFromYamlEndPoint, + listUserRulesEndPoint, + createUserRuleEndPoint, + updateUserRuleEndPoint, + deleteUserRuleEndPoint, + createUserRuleFromYamlEndPoint, + updateUserRuleFromYamlEndPoint +} diff --git a/src/controllers/rbac-controller.js b/src/controllers/rbac-controller.js index 4760f55fb..fbfe25b85 100644 --- a/src/controllers/rbac-controller.js +++ b/src/controllers/rbac-controller.js @@ -68,12 +68,14 @@ const deleteRoleBindingEndpoint = async function (req) { // ServiceAccount Endpoints const listServiceAccountsEndpoint = async function (req) { - return RbacService.listServiceAccountsEndpoint() + const applicationName = req.query.applicationName + return RbacService.listServiceAccountsEndpoint(applicationName) } const getServiceAccountEndpoint = async function (req) { + const appName = req.params.appName const name = req.params.name - return RbacService.getServiceAccountEndpoint(name) + return RbacService.getServiceAccountEndpoint(appName, name) } const createServiceAccountEndpoint = async function (req) { @@ -82,14 +84,16 @@ const createServiceAccountEndpoint = async function (req) { } const updateServiceAccountEndpoint = async function (req) { + const appName = req.params.appName const name = req.params.name const saData = req.body - return RbacService.updateServiceAccountEndpoint(name, saData) + return RbacService.updateServiceAccountEndpoint(appName, name, saData) } const deleteServiceAccountEndpoint = async function (req) { + const appName = req.params.appName const name = req.params.name - return RbacService.deleteServiceAccountEndpoint(name) + return RbacService.deleteServiceAccountEndpoint(appName, name) } // YAML Endpoints @@ -126,10 +130,11 @@ const createServiceAccountFromYamlEndpoint = async function (req) { } const updateServiceAccountFromYamlEndpoint = async function (req) { + const appName = req.params.appName const name = req.params.name const fileContent = req.file.buffer.toString() const saData = await YamlParserService.parseServiceAccountFile(fileContent) - return RbacService.updateServiceAccountEndpoint(name, saData) + return RbacService.updateServiceAccountEndpoint(appName, name, saData) } module.exports = { diff --git a/src/controllers/routing-controller.js b/src/controllers/routing-controller.js deleted file mode 100644 index 8d6df8bc4..000000000 --- a/src/controllers/routing-controller.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ******************************************************************************* - * * Copyright (c) 2023 Datasance Teknoloji A.S. - * * - * * This program and the accompanying materials are made available under the - * * terms of the Eclipse Public License v. 2.0 which is available at - * * http://www.eclipse.org/legal/epl-2.0 - * * - * * SPDX-License-Identifier: EPL-2.0 - * ******************************************************************************* - * - */ - -const RoutingService = require('../services/routing-service') - -const createRoutingEndpoint = async function (req) { - const routerData = req.body - return RoutingService.createRouting(routerData, false) -} - -const getRoutingsEndPoint = async function (req) { - return RoutingService.getRoutings(false) -} - -const getRoutingEndPoint = async function (req) { - const routeName = req.params.name - const appName = req.params.appName - return RoutingService.getRouting(appName, routeName, false) -} - -const updateRoutingEndpoint = async function (req) { - const routeName = req.params.name - const appName = req.params.appName - const routeData = req.body - return RoutingService.updateRouting(appName, routeName, routeData, false) -} - -const deleteRoutingEndpoint = async function (req) { - const routeName = req.params.name - const appName = req.params.appName - return RoutingService.deleteRouting(appName, routeName, false) -} - -module.exports = { - deleteRoutingEndpoint: (deleteRoutingEndpoint), - updateRoutingEndpoint: (updateRoutingEndpoint), - createRoutingEndpoint: (createRoutingEndpoint), - getRoutingEndPoint: (getRoutingEndPoint), - getRoutingsEndPoint: (getRoutingsEndPoint) -} diff --git a/src/data/constants.js b/src/data/constants.js index 4c75fdb28..63e82bcbd 100644 --- a/src/data/constants.js +++ b/src/data/constants.js @@ -1,4 +1,5 @@ module.exports = { ROUTER_CATALOG_NAME: 'Router', - DEBUG_CATALOG_NAME: 'Debug' + DEBUG_CATALOG_NAME: 'Debug', + NATS_CATALOG_NAME: 'NATs' } diff --git a/src/data/managers/application-manager.js b/src/data/managers/application-manager.js index 84f62e0ba..3b546e007 100644 --- a/src/data/managers/application-manager.js +++ b/src/data/managers/application-manager.js @@ -15,8 +15,6 @@ const BaseManager = require('./base-manager') const models = require('../models') const Application = models.Application const Microservice = models.Microservice -const Routing = models.Routing -const flatMap = require('lodash/flatMap') class ApplicationManager extends BaseManager { getEntity () { @@ -41,32 +39,6 @@ class ApplicationManager extends BaseManager { return application.microservices || [] } - async findApplicationRoutes (where, transaction) { - const application = await Application.findOne({ - include: [ - { - model: Microservice, - as: 'microservices', - required: false, - include: [ - { - model: Routing, - as: 'routes', - required: false, - attributes: ['name'] - } - ] - } - ], - where: where, - attributes: ['id'] - }, { transaction: transaction }) - if (!application) { - return undefined - } - return flatMap(application.microservices || [], m => m.routes).map(r => r.get({ plain: true })) - } - async findAllWithAttributes (where, attributes, transaction) { return Application.findAll({ where: where, @@ -88,22 +60,7 @@ class ApplicationManager extends BaseManager { { model: Microservice, as: 'microservices', - required: false, - include: [ - { - model: Routing, - as: 'routes', - required: false, - include: [ - { - model: Microservice, - as: 'destMicroservice', - attributes: ['name'] - } - ], - attributes: ['name'] - } - ] + required: false } ], where, @@ -113,21 +70,9 @@ class ApplicationManager extends BaseManager { return null } const msvcs = application.microservices || [] - const routes = flatMap(msvcs, m => m.routes.map(r => { - const route = r.get({ plain: true }) - return { - name: route.name, - from: m.name, - to: route.destMicroservice.name - } - })) return { ...application.get({ plain: true }), - microservices: msvcs.map(m => { - delete m.routes - return m - }), - routes + microservices: msvcs.map(m => m.get({ plain: true })) } } @@ -137,47 +82,16 @@ class ApplicationManager extends BaseManager { { model: Microservice, as: 'microservices', - required: false, - include: [ - { - model: Routing, - as: 'routes', - required: false, - include: [ - { - model: Microservice, - as: 'destMicroservice', - attributes: ['name'] - } - ], - attributes: ['name'] - } - ] + required: false } ], where, attributes }, { transaction: transaction }) - return applications.map(application => { - const msvcs = application.microservices || [] - const routes = flatMap(msvcs, m => m.routes.map(r => { - const route = r.get({ plain: true }) - return { - name: route.name, - from: m.name, - to: route.destMicroservice.name - } - })) - return { - ...application.get({ plain: true }), - microservices: msvcs.map(m => { - const msvc = m.get({ plain: true }) - delete msvc.routes - return msvc - }), - routes - } - }) + return applications.map(application => ({ + ...application.get({ plain: true }), + microservices: (application.microservices || []).map(m => m.get({ plain: true })) + })) } } diff --git a/src/data/managers/microservice-manager.js b/src/data/managers/microservice-manager.js index a5d62abf3..c39d1a449 100644 --- a/src/data/managers/microservice-manager.js +++ b/src/data/managers/microservice-manager.js @@ -26,9 +26,7 @@ const StraceDiagnostics = models.StraceDiagnostics const CatalogItem = models.CatalogItem const CatalogItemImage = models.CatalogItemImage const Fog = models.Fog -const Tags = models.Tags const Application = models.Application -const Routing = models.Routing const Registry = models.Registry const MicroserviceStatus = models.MicroserviceStatus const MicroserviceExecStatus = models.MicroserviceExecStatus @@ -138,18 +136,6 @@ class MicroserviceManager extends BaseManager { required: false, attributes: ['daemonStatus'] }, - { - model: Routing, - as: 'routes', - required: false, - include: [{ - model: Microservice, - as: 'destMicroservice', - attributes: ['uuid'] - }], - attributes: { exclude: ['id', 'source_microservice_uuid', - 'sourceMicroserviceUuid', 'destMicroserviceUuid'] } - }, { model: MicroserviceHealthCheck, as: 'healthCheck', @@ -255,18 +241,6 @@ class MicroserviceManager extends BaseManager { required: false, attributes: ['isActivated'] }, - { - model: Tags, - as: 'pubTags', - attributes: ['value'], - through: { attributes: [] } - }, - { - model: Tags, - as: 'subTags', - attributes: ['value'], - through: { attributes: [] } - }, { model: MicroserviceHealthCheck, as: 'healthCheck', @@ -384,18 +358,6 @@ class MicroserviceManager extends BaseManager { required: false, attributes: ['daemonStatus'] }, - { - model: Routing, - as: 'routes', - required: false, - include: [{ - model: Microservice, - as: 'destMicroservice', - attributes: ['uuid'] - }], - attributes: { exclude: ['id', - 'sourceMicroserviceUuid', 'destMicroserviceUuid'] } - }, { model: MicroserviceHealthCheck, as: 'healthCheck', @@ -486,18 +448,6 @@ class MicroserviceManager extends BaseManager { async findOneExcludeFields (where, transaction) { return Microservice.findOne({ include: [ - { - model: Tags, - as: 'pubTags', - attributes: ['value'], - through: { attributes: [] } - }, - { - model: Tags, - as: 'subTags', - attributes: ['value'], - through: { attributes: [] } - }, { model: RbacServiceAccount, as: 'serviceAccount', @@ -520,18 +470,6 @@ class MicroserviceManager extends BaseManager { required: true, where: { isSystem: false } }, - { - model: Tags, - as: 'pubTags', - attributes: ['value'], - through: { attributes: [] } - }, - { - model: Tags, - as: 'subTags', - attributes: ['value'], - through: { attributes: [] } - }, { model: RbacServiceAccount, as: 'serviceAccount', @@ -555,18 +493,6 @@ class MicroserviceManager extends BaseManager { required: true, where: { isSystem: true } }, - { - model: Tags, - as: 'pubTags', - attributes: ['value'], - through: { attributes: [] } - }, - { - model: Tags, - as: 'subTags', - attributes: ['value'], - through: { attributes: [] } - }, { model: RbacServiceAccount, as: 'serviceAccount', diff --git a/src/data/managers/nats-account-manager.js b/src/data/managers/nats-account-manager.js new file mode 100644 index 000000000..b9f659272 --- /dev/null +++ b/src/data/managers/nats-account-manager.js @@ -0,0 +1,18 @@ +const BaseManager = require('./base-manager') +const models = require('../models') +const NatsAccount = models.NatsAccount + +class NatsAccountManager extends BaseManager { + getEntity () { + return NatsAccount + } + + findByApplicationId (applicationId, transaction) { + return NatsAccount.findOne({ + where: { applicationId }, + include: [{ model: models.Application, as: 'application' }] + }, { transaction }) + } +} + +module.exports = new NatsAccountManager() diff --git a/src/data/managers/nats-account-rule-manager.js b/src/data/managers/nats-account-rule-manager.js new file mode 100644 index 000000000..564a6cc6c --- /dev/null +++ b/src/data/managers/nats-account-rule-manager.js @@ -0,0 +1,11 @@ +const BaseManager = require('./base-manager') +const models = require('../models') +const NatsAccountRule = models.NatsAccountRule + +class NatsAccountRuleManager extends BaseManager { + getEntity () { + return NatsAccountRule + } +} + +module.exports = new NatsAccountRuleManager() diff --git a/src/data/managers/nats-connection-manager.js b/src/data/managers/nats-connection-manager.js new file mode 100644 index 000000000..83ec7fae5 --- /dev/null +++ b/src/data/managers/nats-connection-manager.js @@ -0,0 +1,30 @@ +const BaseManager = require('./base-manager') +const models = require('../models') +const NatsConnection = models.NatsConnection +const NatsInstance = models.NatsInstance + +class NatsConnectionManager extends BaseManager { + getEntity () { + return NatsConnection + } + + findAllWithNats (where, transaction) { + return NatsConnection.findAll({ + include: [ + { + model: NatsInstance, + as: 'source', + required: true + }, + { + model: NatsInstance, + as: 'dest', + required: true + } + ], + where: where + }, { transaction: transaction }) + } +} + +module.exports = new NatsConnectionManager() diff --git a/src/data/managers/nats-instance-manager.js b/src/data/managers/nats-instance-manager.js new file mode 100644 index 000000000..2703185ef --- /dev/null +++ b/src/data/managers/nats-instance-manager.js @@ -0,0 +1,15 @@ +const BaseManager = require('./base-manager') +const models = require('../models') +const NatsInstance = models.NatsInstance + +class NatsInstanceManager extends BaseManager { + getEntity () { + return NatsInstance + } + + findByFog (iofogUuid, transaction) { + return NatsInstance.findOne({ where: { iofogUuid } }, { transaction }) + } +} + +module.exports = new NatsInstanceManager() diff --git a/src/data/managers/nats-operator-manager.js b/src/data/managers/nats-operator-manager.js new file mode 100644 index 000000000..4112161cf --- /dev/null +++ b/src/data/managers/nats-operator-manager.js @@ -0,0 +1,11 @@ +const BaseManager = require('./base-manager') +const models = require('../models') +const NatsOperator = models.NatsOperator + +class NatsOperatorManager extends BaseManager { + getEntity () { + return NatsOperator + } +} + +module.exports = new NatsOperatorManager() diff --git a/src/data/managers/nats-reconcile-task-manager.js b/src/data/managers/nats-reconcile-task-manager.js new file mode 100644 index 000000000..5e23d2aa4 --- /dev/null +++ b/src/data/managers/nats-reconcile-task-manager.js @@ -0,0 +1,50 @@ +const BaseManager = require('./base-manager') +const models = require('../models') +const config = require('../../config') +const databaseProvider = require('../providers/database-factory') +const { Op } = require('sequelize') + +class NatsReconcileTaskManager extends BaseManager { + getEntity () { + return models.NatsReconcileTask + } + + async claimNext (controllerUuid, stalenessSeconds) { + const sequelize = databaseProvider.sequelize + const T = stalenessSeconds != null ? stalenessSeconds : config.get('settings.natsReconcileTaskStalenessSeconds', 900) + const staleThreshold = new Date(Date.now() - T * 1000) + const Entity = this.getEntity() + return sequelize.transaction(async (transaction) => { + const task = await Entity.findOne({ + where: { + status: { [Op.in]: ['pending', 'in_progress'] }, + [Op.or]: [ + { leaderUuid: null }, + { claimedAt: { [Op.lt]: staleThreshold } } + ] + }, + order: [['id', 'ASC']], + limit: 1, + transaction + }) + if (!task) return null + const [affected] = await Entity.update( + { leaderUuid: controllerUuid, claimedAt: new Date(), status: 'in_progress' }, + { + where: { + id: task.id, + [Op.or]: [ + { leaderUuid: null }, + { claimedAt: { [Op.lt]: staleThreshold } } + ] + }, + transaction + } + ) + if (affected === 0) return null + return this.findOne({ id: task.id }, transaction) + }) + } +} + +module.exports = new NatsReconcileTaskManager() diff --git a/src/data/managers/nats-user-manager.js b/src/data/managers/nats-user-manager.js new file mode 100644 index 000000000..9543700a2 --- /dev/null +++ b/src/data/managers/nats-user-manager.js @@ -0,0 +1,30 @@ +const BaseManager = require('./base-manager') +const models = require('../models') +const NatsUser = models.NatsUser + +class NatsUserManager extends BaseManager { + getEntity () { + return NatsUser + } + + findByMicroserviceUuid (microserviceUuid, transaction) { + return NatsUser.findOne({ + where: { microserviceUuid }, + include: [{ model: models.NatsAccount, as: 'account' }] + }, { transaction }) + } + + findAllWithAccountAndApplication (transaction) { + return NatsUser.findAll({ + include: [ + { + model: models.NatsAccount, + as: 'account', + include: [{ model: models.Application, as: 'application' }] + } + ] + }, { transaction }) + } +} + +module.exports = new NatsUserManager() diff --git a/src/data/managers/nats-user-rule-manager.js b/src/data/managers/nats-user-rule-manager.js new file mode 100644 index 000000000..7e2adee3d --- /dev/null +++ b/src/data/managers/nats-user-rule-manager.js @@ -0,0 +1,11 @@ +const BaseManager = require('./base-manager') +const models = require('../models') +const NatsUserRule = models.NatsUserRule + +class NatsUserRuleManager extends BaseManager { + getEntity () { + return NatsUserRule + } +} + +module.exports = new NatsUserRuleManager() diff --git a/src/data/managers/rbac-service-account-manager.js b/src/data/managers/rbac-service-account-manager.js index 21280e307..c7ce0294b 100644 --- a/src/data/managers/rbac-service-account-manager.js +++ b/src/data/managers/rbac-service-account-manager.js @@ -14,9 +14,29 @@ const BaseManager = require('./base-manager') const models = require('../models') const RbacServiceAccount = models.RbacServiceAccount +const Application = models.Application const RbacRoleManager = require('./rbac-role-manager') +const ApplicationManager = require('./application-manager') const Errors = require('../../helpers/errors') const RbacCacheVersionManager = require('./rbac-cache-version-manager') +const AppHelper = require('../../helpers/app-helper') + +const serviceAccountIncludeApplication = [ + { + model: Application, + as: 'application', + required: false, + attributes: ['name'] + } +] + +function mapToResponse (sa) { + if (!sa) return null + const plain = sa.get ? sa.get({ plain: true }) : sa + const applicationName = (plain.application && plain.application.name) || + (sa.application && sa.application.get ? sa.application.get({ plain: true }).name : null) + return Object.assign({}, plain, { applicationName }) +} class RbacServiceAccountManager extends BaseManager { getEntity () { @@ -24,138 +44,196 @@ class RbacServiceAccountManager extends BaseManager { } /** - * Create a ServiceAccount - * roleRef is required + * Find a ServiceAccount by microservice UUID (for microservice flow) */ - async createServiceAccount (saData, transaction) { - // Check if ServiceAccount already exists - const existingServiceAccount = await this.findOne({ name: saData.name }, transaction) - if (existingServiceAccount) { - throw new Errors.ConflictError(`ServiceAccount '${saData.name}' already exists`) + async findOneByMicroserviceUuid (microserviceUuid, transaction) { + return this.findOne({ microserviceUuid }, transaction) + } + + /** + * Find a ServiceAccount by application ID and name + */ + async findOneByApplicationAndName (applicationId, name, transaction) { + return this.findOne({ applicationId, name }, transaction) + } + + /** + * Get a ServiceAccount by application name and service account name (for API). + * Returns SA with applicationName in response shape. + */ + async getServiceAccount (appName, name, transaction) { + AppHelper.checkTransaction(transaction) + const application = await ApplicationManager.findOne({ name: appName }, transaction) + if (!application) { + throw new Errors.NotFoundError(`Application '${appName}' not found`) } + const options = transaction.fakeTransaction + ? { where: { applicationId: application.id, name }, include: serviceAccountIncludeApplication } + : { where: { applicationId: application.id, name }, include: serviceAccountIncludeApplication, transaction } + const sa = await RbacServiceAccount.findOne(options) + return sa ? mapToResponse(sa) : null + } - // Validate roleRef is provided + /** + * Create a ServiceAccount + * - If saData.microserviceUuid is set (microservice flow): find or create by microserviceUuid; set applicationId from microservice. + * - Otherwise (API flow): require saData.applicationName; create with applicationId, name, roleRef; microservice_uuid null. + */ + async createServiceAccount (saData, transaction) { if (!saData.roleRef || !saData.roleRef.name) { throw new Errors.ValidationError('ServiceAccount must have a roleRef with a name.') } - // Validate role reference exists - use findOne to get the actual model with id - // System roles don't exist in DB, so we can't set roleId for them const role = await RbacRoleManager.findOne({ name: saData.roleRef.name }, transaction) if (!role) { - // Check if it's a system role const roleWithRules = await RbacRoleManager.getRoleWithRules(saData.roleRef.name, transaction) if (!roleWithRules) { throw new Errors.ValidationError(`Referenced role '${saData.roleRef.name}' does not exist`) } - // System role - roleId will be null (system roles don't have DB ids) } - let serviceAccount - try { - serviceAccount = await this.create({ + if (saData.microserviceUuid) { + const existing = await this.findOneByMicroserviceUuid(saData.microserviceUuid, transaction) + if (existing) { + const updateData = { roleRef: saData.roleRef, name: saData.name || existing.name } + if (role) updateData.roleId = role.id + await this.update({ id: existing.id }, updateData, transaction) + await RbacCacheVersionManager.incrementVersion(transaction) + return this.findOne({ id: existing.id }, transaction) + } + const createData = { + microserviceUuid: saData.microserviceUuid, + applicationId: saData.applicationId, name: saData.name, - // namespace removed (controller manages single namespace) roleRef: saData.roleRef, roleId: role ? role.id : null - }, transaction) - } catch (error) { - // Handle SequelizeUniqueConstraintError as a safety net - if (error.name === 'SequelizeUniqueConstraintError') { - throw new Errors.ConflictError(`ServiceAccount '${saData.name}' already exists`) } - throw error + const created = await this.create(createData, transaction) + await RbacCacheVersionManager.incrementVersion(transaction) + return created } - // Increment cache version to invalidate caches on all instances - await RbacCacheVersionManager.incrementVersion(transaction) + if (!saData.applicationName) { + throw new Errors.ValidationError('ServiceAccount must have applicationName when creating via API.') + } + const application = await ApplicationManager.findOne({ name: saData.applicationName }, transaction) + if (!application) { + throw new Errors.NotFoundError(`Application '${saData.applicationName}' not found`) + } + const existingByAppAndName = await this.findOneByApplicationAndName(application.id, saData.name, transaction) + if (existingByAppAndName) { + throw new Errors.ConflictError(`ServiceAccount '${saData.name}' already exists in application '${saData.applicationName}'`) + } - return serviceAccount + const createData = { + applicationId: application.id, + name: saData.name, + roleRef: saData.roleRef, + roleId: role ? role.id : null + } + const created = await this.create(createData, transaction) + await RbacCacheVersionManager.incrementVersion(transaction) + return created } /** - * Update a ServiceAccount + * Update a ServiceAccount by appName and name (API) */ - async updateServiceAccount (name, saData, transaction) { - const sa = await this.findOne({ name }, transaction) + async updateServiceAccount (appName, name, saData, transaction) { + const application = await ApplicationManager.findOne({ name: appName }, transaction) + if (!application) { + throw new Errors.NotFoundError(`Application '${appName}' not found`) + } + const sa = await this.findOneByApplicationAndName(application.id, name, transaction) if (!sa) { - throw new Errors.NotFoundError(`ServiceAccount '${name}' not found`) + throw new Errors.NotFoundError(`ServiceAccount '${name}' not found in application '${appName}'`) } - // Validate roleRef is provided if updating and get role ID let roleId = null if (saData.roleRef !== undefined) { if (!saData.roleRef || !saData.roleRef.name) { throw new Errors.ValidationError('ServiceAccount roleRef must have a name.') } - - // Validate role reference exists - use findOne to get the actual model with id const role = await RbacRoleManager.findOne({ name: saData.roleRef.name }, transaction) if (!role) { - // Check if it's a system role const roleWithRules = await RbacRoleManager.getRoleWithRules(saData.roleRef.name, transaction) if (!roleWithRules) { throw new Errors.ValidationError(`Referenced role '${saData.roleRef.name}' does not exist`) } - // System role - roleId will be null (system roles don't have DB ids) } else { roleId = role.id } } else { - // If roleRef is not provided, keep existing roleId const existingRoleRef = sa.roleRef if (existingRoleRef && existingRoleRef.name) { const role = await RbacRoleManager.findOne({ name: existingRoleRef.name }, transaction) - if (role) { - roleId = role.id - } - // If not found in DB, it might be a system role - keep roleId as null + if (role) roleId = role.id } } const updateData = {} - if (saData.name) updateData.name = saData.name - // namespace removed (not stored in database) + if (saData.name !== undefined) updateData.name = saData.name if (saData.roleRef !== undefined) updateData.roleRef = saData.roleRef if (roleId !== null) updateData.roleId = roleId - await this.update({ name }, updateData, transaction) - - // Increment cache version to invalidate caches on all instances + await this.update({ id: sa.id }, updateData, transaction) await RbacCacheVersionManager.incrementVersion(transaction) - return this.findOne({ name: saData.name || name }, transaction) + const updated = await RbacServiceAccount.findByPk(sa.id, { + include: serviceAccountIncludeApplication, + transaction: transaction.fakeTransaction ? undefined : transaction + }) + return mapToResponse(updated) } /** - * Delete a ServiceAccount + * Delete a ServiceAccount by appName and name (API) */ - async deleteServiceAccount (name, transaction) { - const sa = await this.findOne({ name }, transaction) + async deleteServiceAccount (appName, name, transaction) { + const application = await ApplicationManager.findOne({ name: appName }, transaction) + if (!application) { + throw new Errors.NotFoundError(`Application '${appName}' not found`) + } + const sa = await this.findOneByApplicationAndName(application.id, name, transaction) if (!sa) { - throw new Errors.NotFoundError(`ServiceAccount '${name}' not found`) + throw new Errors.NotFoundError(`ServiceAccount '${name}' not found in application '${appName}'`) } - - await this.delete({ name }, transaction) - - // Increment cache version to invalidate caches on all instances + await this.delete({ id: sa.id }, transaction) await RbacCacheVersionManager.incrementVersion(transaction) - return { message: `ServiceAccount '${name}' deleted successfully` } } /** - * Get a ServiceAccount by name + * Delete ServiceAccount by microservice UUID (microservice flow) */ - async getServiceAccount (name, transaction) { - return this.findOne({ name }, transaction) + async deleteByMicroserviceUuid (microserviceUuid, transaction) { + const sa = await this.findOneByMicroserviceUuid(microserviceUuid, transaction) + if (!sa) { + return { message: 'ServiceAccount not found for microservice, skipping' } + } + await this.delete({ id: sa.id }, transaction) + await RbacCacheVersionManager.incrementVersion(transaction) + return { message: 'ServiceAccount deleted successfully' } } /** - * List all ServiceAccounts + * List ServiceAccounts, optionally filtered by applicationName. Each item includes applicationName. */ - async listServiceAccounts (transaction) { - return this.findAll({}, transaction) + async listServiceAccounts (transaction, options = {}) { + AppHelper.checkTransaction(transaction) + let where = {} + if (options.applicationName) { + const application = await ApplicationManager.findOne({ name: options.applicationName }, transaction) + if (!application) { + return [] + } + where.applicationId = application.id + } + const findOptions = transaction.fakeTransaction + ? { where, include: serviceAccountIncludeApplication } + : { where, include: serviceAccountIncludeApplication, transaction } + const list = await RbacServiceAccount.findAll(findOptions) + return list.map(sa => mapToResponse(sa)) } } diff --git a/src/data/managers/routing-manager.js b/src/data/managers/routing-manager.js deleted file mode 100644 index 1d82e1fce..000000000 --- a/src/data/managers/routing-manager.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * ******************************************************************************* - * * Copyright (c) 2023 Datasance Teknoloji A.S. - * * - * * This program and the accompanying materials are made available under the - * * terms of the Eclipse Public License v. 2.0 which is available at - * * http://www.eclipse.org/legal/epl-2.0 - * * - * * SPDX-License-Identifier: EPL-2.0 - * ******************************************************************************* - * - */ - -const BaseManager = require('./base-manager') -const models = require('../models') -const Routing = models.Routing - -class RoutingManager extends BaseManager { - getEntity () { - return Routing - } - - findOnePopulated (where, transaction) { - return Routing.findOne({ - include: [ - { - model: models.Microservice, - as: 'sourceMicroservice', - required: true, - attributes: ['name', 'uuid', 'iofogUuid'] - }, - { - model: models.Microservice, - as: 'destMicroservice', - required: true, - attributes: ['name', 'uuid', 'iofogUuid'] - }, - { - model: models.Application, - as: 'application', - required: true, - attributes: ['name', 'id'] - } - ], - where - }) - } - - findAllPopulated (where, transaction) { - return Routing.findAll({ - include: [ - { - model: models.Microservice, - as: 'sourceMicroservice', - required: true, - attributes: ['name', 'uuid', 'iofogUuid'] - }, - { - model: models.Microservice, - as: 'destMicroservice', - required: true, - attributes: ['name', 'uuid', 'iofogUuid'] - }, - { - model: models.Application, - as: 'application', - required: true, - attributes: ['name', 'id'] - } - ], - where - }) - } -} - -const instance = new RoutingManager() -module.exports = instance diff --git a/src/data/migrations/mysql/db_migration_mysql_v1.1.0.sql b/src/data/migrations/mysql/db_migration_mysql_v1.1.0.sql index 36d9ba363..d9886e815 100644 --- a/src/data/migrations/mysql/db_migration_mysql_v1.1.0.sql +++ b/src/data/migrations/mysql/db_migration_mysql_v1.1.0.sql @@ -94,7 +94,7 @@ CREATE TABLE IF NOT EXISTS Fogs ( network_interface VARCHAR(36) DEFAULT 'dynamic', docker_url VARCHAR(255) DEFAULT 'unix:///var/run/docker.sock', disk_limit FLOAT DEFAULT 50, - disk_directory VARCHAR(255) DEFAULT '/var/lib/iofog/', + disk_directory VARCHAR(255) DEFAULT '/var/lib/iofog-agent/', memory_limit FLOAT DEFAULT 4096, cpu_limit FLOAT DEFAULT 80, log_limit FLOAT DEFAULT 10, @@ -132,7 +132,6 @@ CREATE TABLE IF NOT EXISTS ChangeTrackings ( version BOOLEAN DEFAULT false, microservice_list BOOLEAN DEFAULT false, config BOOLEAN DEFAULT false, - routing BOOLEAN DEFAULT false, registries BOOLEAN DEFAULT false, tunnel BOOLEAN DEFAULT false, diagnostics BOOLEAN DEFAULT false, @@ -392,21 +391,6 @@ CREATE TABLE IF NOT EXISTS CatalogItemOutputTypes ( CREATE INDEX idx_catalog_item_output_type_catalog_item_id ON CatalogItemOutputTypes (catalog_item_id); -CREATE TABLE IF NOT EXISTS Routings ( - id INT AUTO_INCREMENT PRIMARY KEY NOT NULL, - name TEXT NOT NULL, - source_microservice_uuid VARCHAR(36), - dest_microservice_uuid VARCHAR(36), - application_id INT, - FOREIGN KEY (source_microservice_uuid) REFERENCES Microservices (uuid) ON DELETE CASCADE, - FOREIGN KEY (dest_microservice_uuid) REFERENCES Microservices (uuid) ON DELETE CASCADE, - FOREIGN KEY (application_id) REFERENCES Flows (id) ON DELETE CASCADE -); - -CREATE INDEX idx_routing_sourceMicroserviceUuid ON Routings (source_microservice_uuid); -CREATE INDEX idx_routing_destMicroserviceUuid ON Routings (dest_microservice_uuid); -CREATE INDEX idx_routing_applicationId ON Routings (application_id); - CREATE TABLE IF NOT EXISTS Routers ( id INT AUTO_INCREMENT PRIMARY KEY NOT NULL, is_edge BOOLEAN DEFAULT true, @@ -915,11 +899,16 @@ CREATE TABLE IF NOT EXISTS RbacRoleBindings ( CREATE TABLE IF NOT EXISTS RbacServiceAccounts ( id INT AUTO_INCREMENT PRIMARY KEY, - name TEXT UNIQUE NOT NULL, + name TEXT NOT NULL, role_ref TEXT, + role_id INT, + microservice_uuid VARCHAR(36), + application_id INT, created_at DATETIME, updated_at DATETIME, - UNIQUE KEY unique_name (name(255)) + FOREIGN KEY (role_id) REFERENCES RbacRoles (id), + FOREIGN KEY (microservice_uuid) REFERENCES Microservices (uuid) ON DELETE CASCADE, + FOREIGN KEY (application_id) REFERENCES Flows (id) ON DELETE SET NULL ); CREATE INDEX idx_rbac_role_rules_role_id ON RbacRoleRules (role_id); @@ -936,17 +925,15 @@ CREATE TABLE IF NOT EXISTS RbacCacheVersion ( ); -ALTER TABLE Microservices ADD COLUMN service_account_id INT; -CREATE INDEX idx_microservices_service_account_id ON Microservices (service_account_id); -ALTER TABLE Microservices ADD CONSTRAINT fk_microservices_service_account_id FOREIGN KEY (service_account_id) REFERENCES RbacServiceAccounts (id); ALTER TABLE RbacRoleBindings ADD COLUMN role_id INT; CREATE INDEX idx_rbac_role_bindings_role_id ON RbacRoleBindings (role_id); ALTER TABLE RbacRoleBindings ADD CONSTRAINT fk_rbac_role_bindings_role_id FOREIGN KEY (role_id) REFERENCES RbacRoles (id); -ALTER TABLE RbacServiceAccounts ADD COLUMN role_id INT; CREATE INDEX idx_rbac_service_accounts_role_id ON RbacServiceAccounts (role_id); -ALTER TABLE RbacServiceAccounts ADD CONSTRAINT fk_rbac_service_accounts_role_id FOREIGN KEY (role_id) REFERENCES RbacRoles (id); +CREATE UNIQUE INDEX idx_rbac_service_accounts_microservice_uuid_unique ON RbacServiceAccounts (microservice_uuid); +CREATE UNIQUE INDEX idx_rbac_service_accounts_application_id_name_unique ON RbacServiceAccounts (application_id, name); + CREATE TABLE IF NOT EXISTS ClusterControllers ( uuid VARCHAR(36) PRIMARY KEY NOT NULL, @@ -962,4 +949,187 @@ CREATE INDEX idx_cluster_controllers_uuid ON ClusterControllers (uuid); CREATE INDEX idx_cluster_controllers_host ON ClusterControllers (host); CREATE INDEX idx_cluster_controllers_active ON ClusterControllers (is_active, last_heartbeat); +ALTER TABLE Fogs ADD COLUMN nats_id INT; + +CREATE TABLE IF NOT EXISTS NatsOperators ( + id INT AUTO_INCREMENT PRIMARY KEY, + name TEXT NOT NULL, + public_key TEXT NOT NULL, + jwt TEXT NOT NULL, + seed_secret_name TEXT NOT NULL, + created_at DATETIME, + updated_at DATETIME, + UNIQUE KEY nats_operators_name (name(255)) +); + +CREATE TABLE IF NOT EXISTS NatsAccounts ( + id INT AUTO_INCREMENT PRIMARY KEY, + name TEXT NOT NULL, + public_key TEXT NOT NULL, + jwt TEXT NOT NULL, + seed_secret_name TEXT NOT NULL, + is_system BOOLEAN DEFAULT false, + is_leaf_system BOOLEAN DEFAULT false, + operator_id INT NOT NULL, + application_id INT, + created_at DATETIME, + updated_at DATETIME, + FOREIGN KEY (operator_id) REFERENCES NatsOperators (id) ON DELETE CASCADE, + FOREIGN KEY (application_id) REFERENCES Flows (id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS NatsUsers ( + id INT AUTO_INCREMENT PRIMARY KEY, + name TEXT NOT NULL, + public_key TEXT NOT NULL, + jwt TEXT NOT NULL, + creds_secret_name TEXT NOT NULL, + is_bearer BOOLEAN DEFAULT false, + account_id INT NOT NULL, + microservice_uuid VARCHAR(36), + created_at DATETIME, + updated_at DATETIME, + FOREIGN KEY (account_id) REFERENCES NatsAccounts (id) ON DELETE CASCADE, + FOREIGN KEY (microservice_uuid) REFERENCES Microservices (uuid) ON DELETE SET NULL +); + +CREATE TABLE IF NOT EXISTS NatsInstances ( + id INT AUTO_INCREMENT PRIMARY KEY, + iofog_uuid VARCHAR(36), + is_leaf BOOLEAN DEFAULT true, + is_hub BOOLEAN DEFAULT false, + host TEXT, + server_port INT, + leaf_port INT, + cluster_port INT, + mqtt_port INT, + http_port INT, + configmap_name TEXT, + jwt_dir_mount_name TEXT, + cert_secret_name TEXT, + js_storage_size TEXT, + js_memory_store_size TEXT, + created_at DATETIME, + updated_at DATETIME, + FOREIGN KEY (iofog_uuid) REFERENCES Fogs (uuid) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS NatsConnections ( + id INT AUTO_INCREMENT PRIMARY KEY, + source_nats INT NOT NULL, + dest_nats INT NOT NULL, + created_at DATETIME, + updated_at DATETIME, + FOREIGN KEY (source_nats) REFERENCES NatsInstances (id) ON DELETE CASCADE, + FOREIGN KEY (dest_nats) REFERENCES NatsInstances (id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS NatsReconcileTasks ( + id INT AUTO_INCREMENT PRIMARY KEY, + reason VARCHAR(64) NOT NULL, + application_id INT, + account_rule_id INT, + user_rule_id INT, + fog_uuids TEXT, + status VARCHAR(32) NOT NULL DEFAULT 'pending', + leader_uuid VARCHAR(36), + claimed_at DATETIME, + created_at DATETIME, + updated_at DATETIME +); + +CREATE TABLE IF NOT EXISTS NatsAccountRules ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) UNIQUE NOT NULL, + description TEXT, + info_url TEXT, + max_connections INT, + max_leaf_node_connections INT, + max_data BIGINT, + max_exports INT, + max_imports INT, + max_msg_payload INT, + max_subscriptions INT, + exports_allow_wildcards BOOLEAN DEFAULT true, + disallow_bearer BOOLEAN, + response_permissions TEXT, + resp_max INT, + resp_ttl BIGINT, + imports TEXT, + exports TEXT, + mem_storage BIGINT, + disk_storage BIGINT, + streams INT, + consumer INT, + max_ack_pending INT, + mem_max_stream_bytes BIGINT, + disk_max_stream_bytes BIGINT, + max_bytes_required BOOLEAN, + tiered_limits TEXT, + pub_allow TEXT, + pub_deny TEXT, + sub_allow TEXT, + sub_deny TEXT, + created_at DATETIME, + updated_at DATETIME +); + +CREATE TABLE IF NOT EXISTS NatsUserRules ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) UNIQUE NOT NULL, + description TEXT, + max_subscriptions INT, + max_payload INT, + max_data BIGINT, + bearer_token BOOLEAN DEFAULT false, + proxy_required BOOLEAN, + allowed_connection_types TEXT, + src TEXT, + times TEXT, + times_location TEXT, + resp_max INT, + resp_ttl BIGINT, + pub_allow TEXT, + pub_deny TEXT, + sub_allow TEXT, + sub_deny TEXT, + tags TEXT, + created_at DATETIME, + updated_at DATETIME +); + +CREATE UNIQUE INDEX idx_nats_accounts_application_id_unique ON NatsAccounts (application_id); +CREATE INDEX idx_nats_accounts_application_id ON NatsAccounts (application_id); +CREATE UNIQUE INDEX idx_nats_users_account_id_name ON NatsUsers (account_id, name(255)); +CREATE INDEX idx_nats_users_account_id ON NatsUsers (account_id); +CREATE INDEX idx_nats_users_microservice_uuid ON NatsUsers (microservice_uuid); +ALTER TABLE NatsUsers ADD COLUMN nats_user_rule_id INT NULL; +CREATE INDEX idx_nats_users_nats_user_rule_id ON NatsUsers (nats_user_rule_id); +ALTER TABLE NatsUsers ADD CONSTRAINT fk_nats_users_nats_user_rule_id FOREIGN KEY (nats_user_rule_id) REFERENCES NatsUserRules (id) ON DELETE SET NULL; +CREATE UNIQUE INDEX idx_nats_instances_iofog_uuid_unique ON NatsInstances (iofog_uuid); +CREATE INDEX idx_nats_instances_iofog_uuid ON NatsInstances (iofog_uuid); +CREATE UNIQUE INDEX idx_nats_connections_source_dest_unique ON NatsConnections (source_nats, dest_nats); +CREATE INDEX idx_nats_connections_source_nats ON NatsConnections (source_nats); +CREATE INDEX idx_nats_connections_dest_nats ON NatsConnections (dest_nats); +CREATE INDEX idx_nats_account_rules_name ON NatsAccountRules (name); +CREATE INDEX idx_nats_user_rules_name ON NatsUserRules (name); +CREATE INDEX idx_nats_reconcile_tasks_status_claimed ON NatsReconcileTasks (status, claimed_at); + +ALTER TABLE Flows ADD COLUMN nats_access BOOLEAN DEFAULT false; +ALTER TABLE Flows ADD COLUMN nats_rule_id INT; +ALTER TABLE Microservices ADD COLUMN nats_rule_id INT; +ALTER TABLE Microservices ADD COLUMN nats_access BOOLEAN DEFAULT false; +ALTER TABLE Microservices ADD COLUMN nats_account_id INT; +ALTER TABLE Microservices ADD COLUMN nats_user_id INT; +ALTER TABLE Microservices ADD COLUMN nats_creds_secret_name TEXT; +CREATE INDEX idx_flows_nats_rule_id ON Flows (nats_rule_id); +CREATE INDEX idx_microservices_nats_rule_id ON Microservices (nats_rule_id); +CREATE INDEX idx_microservices_nats_account_id ON Microservices (nats_account_id); +CREATE INDEX idx_microservices_nats_user_id ON Microservices (nats_user_id); +ALTER TABLE Flows ADD CONSTRAINT fk_flows_nats_rule_id FOREIGN KEY (nats_rule_id) REFERENCES NatsAccountRules (id); +ALTER TABLE Microservices ADD CONSTRAINT fk_microservices_nats_rule_id FOREIGN KEY (nats_rule_id) REFERENCES NatsUserRules (id); +ALTER TABLE Microservices ADD CONSTRAINT fk_microservices_nats_account_id FOREIGN KEY (nats_account_id) REFERENCES NatsAccounts (id); +ALTER TABLE Microservices ADD CONSTRAINT fk_microservices_nats_user_id FOREIGN KEY (nats_user_id) REFERENCES NatsUsers (id); + + COMMIT; \ No newline at end of file diff --git a/src/data/migrations/postgres/db_migration_pg_v1.1.0.sql b/src/data/migrations/postgres/db_migration_pg_v1.1.0.sql index b29acc690..98f048f08 100644 --- a/src/data/migrations/postgres/db_migration_pg_v1.1.0.sql +++ b/src/data/migrations/postgres/db_migration_pg_v1.1.0.sql @@ -92,7 +92,7 @@ CREATE TABLE IF NOT EXISTS "Fogs" ( network_interface VARCHAR(36) DEFAULT 'dynamic', docker_url VARCHAR(255) DEFAULT 'unix:///var/run/docker.sock', disk_limit DOUBLE PRECISION DEFAULT 50, - disk_directory VARCHAR(255) DEFAULT '/var/lib/iofog/', + disk_directory VARCHAR(255) DEFAULT '/var/lib/iofog-agent/', memory_limit DOUBLE PRECISION DEFAULT 4096, cpu_limit DOUBLE PRECISION DEFAULT 80, log_limit DOUBLE PRECISION DEFAULT 10, @@ -130,7 +130,6 @@ CREATE TABLE IF NOT EXISTS "ChangeTrackings" ( version BOOLEAN DEFAULT false, microservice_list BOOLEAN DEFAULT false, config BOOLEAN DEFAULT false, - routing BOOLEAN DEFAULT false, registries BOOLEAN DEFAULT false, tunnel BOOLEAN DEFAULT false, diagnostics BOOLEAN DEFAULT false, @@ -390,21 +389,6 @@ CREATE TABLE IF NOT EXISTS "CatalogItemOutputTypes" ( CREATE INDEX idx_catalog_item_output_type_catalog_item_id ON "CatalogItemOutputTypes" (catalog_item_id); -CREATE TABLE IF NOT EXISTS "Routings" ( - id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY NOT NULL, - name TEXT NOT NULL, - source_microservice_uuid VARCHAR(36), - dest_microservice_uuid VARCHAR(36), - application_id INT, - FOREIGN KEY (source_microservice_uuid) REFERENCES "Microservices" (uuid) ON DELETE CASCADE, - FOREIGN KEY (dest_microservice_uuid) REFERENCES "Microservices" (uuid) ON DELETE CASCADE, - FOREIGN KEY (application_id) REFERENCES "Flows" (id) ON DELETE CASCADE -); - -CREATE INDEX idx_routing_sourceMicroserviceUuid ON "Routings" (source_microservice_uuid); -CREATE INDEX idx_routing_destMicroserviceUuid ON "Routings" (dest_microservice_uuid); -CREATE INDEX idx_routing_applicationId ON "Routings" (application_id); - CREATE TABLE IF NOT EXISTS "Routers" ( id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY NOT NULL, is_edge BOOLEAN DEFAULT true, @@ -913,8 +897,11 @@ CREATE TABLE IF NOT EXISTS "RbacRoleBindings" ( CREATE TABLE IF NOT EXISTS "RbacServiceAccounts" ( id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, - name TEXT UNIQUE NOT NULL, + name TEXT NOT NULL, role_ref TEXT, + role_id INT REFERENCES "RbacRoles" (id), + microservice_uuid VARCHAR(36) REFERENCES "Microservices" (uuid) ON DELETE CASCADE, + application_id INT REFERENCES "Flows" (id) ON DELETE SET NULL, created_at TIMESTAMP(0), updated_at TIMESTAMP(0) ); @@ -932,17 +919,15 @@ CREATE TABLE IF NOT EXISTS "RbacCacheVersion" ( CONSTRAINT single_row CHECK (id = 1) ); -ALTER TABLE "Microservices" ADD COLUMN service_account_id INT; -CREATE INDEX idx_microservices_service_account_id ON "Microservices" (service_account_id); -ALTER TABLE "Microservices" ADD CONSTRAINT fk_microservices_service_account_id FOREIGN KEY (service_account_id) REFERENCES "RbacServiceAccounts" (id); ALTER TABLE "RbacRoleBindings" ADD COLUMN role_id INT; CREATE INDEX idx_rbac_role_bindings_role_id ON "RbacRoleBindings" (role_id); ALTER TABLE "RbacRoleBindings" ADD CONSTRAINT fk_rbac_role_bindings_role_id FOREIGN KEY (role_id) REFERENCES "RbacRoles" (id); -ALTER TABLE "RbacServiceAccounts" ADD COLUMN role_id INT; CREATE INDEX idx_rbac_service_accounts_role_id ON "RbacServiceAccounts" (role_id); -ALTER TABLE "RbacServiceAccounts" ADD CONSTRAINT fk_rbac_service_accounts_role_id FOREIGN KEY (role_id) REFERENCES "RbacRoles" (id); +CREATE UNIQUE INDEX idx_rbac_service_accounts_microservice_uuid_unique ON "RbacServiceAccounts" (microservice_uuid) WHERE microservice_uuid IS NOT NULL; +CREATE UNIQUE INDEX idx_rbac_service_accounts_application_id_name_unique ON "RbacServiceAccounts" (application_id, name); + CREATE TABLE IF NOT EXISTS "ClusterControllers" ( uuid VARCHAR(36) PRIMARY KEY NOT NULL, @@ -956,4 +941,185 @@ CREATE TABLE IF NOT EXISTS "ClusterControllers" ( CREATE INDEX idx_cluster_controllers_uuid ON "ClusterControllers" (uuid); CREATE INDEX idx_cluster_controllers_host ON "ClusterControllers" (host); -CREATE INDEX idx_cluster_controllers_active ON "ClusterControllers" (is_active, last_heartbeat); \ No newline at end of file +CREATE INDEX idx_cluster_controllers_active ON "ClusterControllers" (is_active, last_heartbeat); + +ALTER TABLE "Fogs" ADD COLUMN nats_id INT; + +CREATE TABLE IF NOT EXISTS "NatsOperators" ( + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY NOT NULL, + name TEXT UNIQUE NOT NULL, + public_key TEXT NOT NULL, + jwt TEXT NOT NULL, + seed_secret_name TEXT NOT NULL, + created_at TIMESTAMP(0), + updated_at TIMESTAMP(0) +); + +CREATE TABLE IF NOT EXISTS "NatsAccounts" ( + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY NOT NULL, + name TEXT NOT NULL, + public_key TEXT NOT NULL, + jwt TEXT NOT NULL, + seed_secret_name TEXT NOT NULL, + is_system BOOLEAN DEFAULT false, + is_leaf_system BOOLEAN DEFAULT false, + operator_id INT NOT NULL, + application_id INT, + created_at TIMESTAMP(0), + updated_at TIMESTAMP(0), + FOREIGN KEY (operator_id) REFERENCES "NatsOperators" (id) ON DELETE CASCADE, + FOREIGN KEY (application_id) REFERENCES "Flows" (id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS "NatsUsers" ( + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY NOT NULL, + name TEXT NOT NULL, + public_key TEXT NOT NULL, + jwt TEXT NOT NULL, + creds_secret_name TEXT NOT NULL, + is_bearer BOOLEAN DEFAULT false, + account_id INT NOT NULL, + microservice_uuid VARCHAR(36), + created_at TIMESTAMP(0), + updated_at TIMESTAMP(0), + FOREIGN KEY (account_id) REFERENCES "NatsAccounts" (id) ON DELETE CASCADE, + FOREIGN KEY (microservice_uuid) REFERENCES "Microservices" (uuid) ON DELETE SET NULL +); + +CREATE TABLE IF NOT EXISTS "NatsInstances" ( + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY NOT NULL, + iofog_uuid VARCHAR(36), + is_leaf BOOLEAN DEFAULT true, + is_hub BOOLEAN DEFAULT false, + host TEXT, + server_port INT, + leaf_port INT, + cluster_port INT, + mqtt_port INT, + http_port INT, + configmap_name TEXT, + jwt_dir_mount_name TEXT, + cert_secret_name TEXT, + js_storage_size TEXT, + js_memory_store_size TEXT, + created_at TIMESTAMP(0), + updated_at TIMESTAMP(0), + FOREIGN KEY (iofog_uuid) REFERENCES "Fogs" (uuid) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS "NatsConnections" ( + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY NOT NULL, + source_nats INT NOT NULL, + dest_nats INT NOT NULL, + created_at TIMESTAMP(0), + updated_at TIMESTAMP(0), + FOREIGN KEY (source_nats) REFERENCES "NatsInstances" (id) ON DELETE CASCADE, + FOREIGN KEY (dest_nats) REFERENCES "NatsInstances" (id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS "NatsReconcileTasks" ( + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY NOT NULL, + reason VARCHAR(64) NOT NULL, + application_id INT, + account_rule_id INT, + user_rule_id INT, + fog_uuids TEXT, + status VARCHAR(32) NOT NULL DEFAULT 'pending', + leader_uuid VARCHAR(36), + claimed_at TIMESTAMP(0), + created_at TIMESTAMP(0), + updated_at TIMESTAMP(0) +); + +CREATE TABLE IF NOT EXISTS "NatsAccountRules" ( + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY NOT NULL, + name TEXT UNIQUE NOT NULL, + description TEXT, + info_url TEXT, + max_connections INT, + max_leaf_node_connections INT, + max_data BIGINT, + max_exports INT, + max_imports INT, + max_msg_payload INT, + max_subscriptions INT, + exports_allow_wildcards BOOLEAN DEFAULT true, + disallow_bearer BOOLEAN, + response_permissions TEXT, + resp_max INT, + resp_ttl BIGINT, + imports TEXT, + exports TEXT, + mem_storage BIGINT, + disk_storage BIGINT, + streams INT, + consumer INT, + max_ack_pending INT, + mem_max_stream_bytes BIGINT, + disk_max_stream_bytes BIGINT, + max_bytes_required BOOLEAN, + tiered_limits TEXT, + pub_allow TEXT, + pub_deny TEXT, + sub_allow TEXT, + sub_deny TEXT, + created_at TIMESTAMP(0), + updated_at TIMESTAMP(0) +); + +CREATE TABLE IF NOT EXISTS "NatsUserRules" ( + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY NOT NULL, + name TEXT UNIQUE NOT NULL, + description TEXT, + max_subscriptions INT, + max_payload INT, + max_data BIGINT, + bearer_token BOOLEAN DEFAULT false, + proxy_required BOOLEAN, + allowed_connection_types TEXT, + src TEXT, + times TEXT, + times_location TEXT, + resp_max INT, + resp_ttl BIGINT, + pub_allow TEXT, + pub_deny TEXT, + sub_allow TEXT, + sub_deny TEXT, + tags TEXT, + created_at TIMESTAMP(0), + updated_at TIMESTAMP(0) +); + +CREATE UNIQUE INDEX idx_nats_accounts_application_id_unique ON "NatsAccounts" (application_id) WHERE application_id IS NOT NULL; +CREATE INDEX idx_nats_accounts_application_id ON "NatsAccounts" (application_id); +CREATE UNIQUE INDEX idx_nats_users_account_id_name ON "NatsUsers" (account_id, name); +CREATE INDEX idx_nats_users_account_id ON "NatsUsers" (account_id); +CREATE INDEX idx_nats_users_microservice_uuid ON "NatsUsers" (microservice_uuid); +ALTER TABLE "NatsUsers" ADD COLUMN nats_user_rule_id INT NULL; +CREATE INDEX idx_nats_users_nats_user_rule_id ON "NatsUsers" (nats_user_rule_id); +ALTER TABLE "NatsUsers" ADD CONSTRAINT fk_nats_users_nats_user_rule_id FOREIGN KEY (nats_user_rule_id) REFERENCES "NatsUserRules" (id) ON DELETE SET NULL; +CREATE UNIQUE INDEX idx_nats_instances_iofog_uuid_unique ON "NatsInstances" (iofog_uuid); +CREATE INDEX idx_nats_instances_iofog_uuid ON "NatsInstances" (iofog_uuid); +CREATE UNIQUE INDEX idx_nats_connections_source_dest_unique ON "NatsConnections" (source_nats, dest_nats); +CREATE INDEX idx_nats_connections_source_nats ON "NatsConnections" (source_nats); +CREATE INDEX idx_nats_connections_dest_nats ON "NatsConnections" (dest_nats); +CREATE INDEX idx_nats_account_rules_name ON "NatsAccountRules" (name); +CREATE INDEX idx_nats_user_rules_name ON "NatsUserRules" (name); +CREATE INDEX idx_nats_reconcile_tasks_status_claimed ON "NatsReconcileTasks" (status, claimed_at); + +ALTER TABLE "Flows" ADD COLUMN nats_access BOOLEAN DEFAULT false; +ALTER TABLE "Flows" ADD COLUMN nats_rule_id INT; +ALTER TABLE "Microservices" ADD COLUMN nats_rule_id INT; +ALTER TABLE "Microservices" ADD COLUMN nats_access BOOLEAN DEFAULT false; +ALTER TABLE "Microservices" ADD COLUMN nats_account_id INT; +ALTER TABLE "Microservices" ADD COLUMN nats_user_id INT; +ALTER TABLE "Microservices" ADD COLUMN nats_creds_secret_name TEXT; +CREATE INDEX idx_flows_nats_rule_id ON "Flows" (nats_rule_id); +CREATE INDEX idx_microservices_nats_rule_id ON "Microservices" (nats_rule_id); +CREATE INDEX idx_microservices_nats_account_id ON "Microservices" (nats_account_id); +CREATE INDEX idx_microservices_nats_user_id ON "Microservices" (nats_user_id); +ALTER TABLE "Flows" ADD CONSTRAINT fk_flows_nats_rule_id FOREIGN KEY (nats_rule_id) REFERENCES "NatsAccountRules" (id); +ALTER TABLE "Microservices" ADD CONSTRAINT fk_microservices_nats_rule_id FOREIGN KEY (nats_rule_id) REFERENCES "NatsUserRules" (id); +ALTER TABLE "Microservices" ADD CONSTRAINT fk_microservices_nats_account_id FOREIGN KEY (nats_account_id) REFERENCES "NatsAccounts" (id); +ALTER TABLE "Microservices" ADD CONSTRAINT fk_microservices_nats_user_id FOREIGN KEY (nats_user_id) REFERENCES "NatsUsers" (id); diff --git a/src/data/migrations/sqlite/db_migration_sqlite_v1.1.0.sql b/src/data/migrations/sqlite/db_migration_sqlite_v1.1.0.sql index 645114f88..0e1570a67 100644 --- a/src/data/migrations/sqlite/db_migration_sqlite_v1.1.0.sql +++ b/src/data/migrations/sqlite/db_migration_sqlite_v1.1.0.sql @@ -92,11 +92,11 @@ CREATE TABLE IF NOT EXISTS Fogs ( network_interface VARCHAR(36) DEFAULT 'dynamic', docker_url VARCHAR(255) DEFAULT 'unix:///var/run/docker.sock', disk_limit FLOAT DEFAULT 50, - disk_directory VARCHAR(255) DEFAULT '/var/lib/iofog/', + disk_directory VARCHAR(255) DEFAULT '/var/lib/iofog-agent/', memory_limit FLOAT DEFAULT 4096, cpu_limit FLOAT DEFAULT 80, log_limit FLOAT DEFAULT 10, - log_directory VARCHAR(255) DEFAULT '/var/log/iofog/', + log_directory VARCHAR(255) DEFAULT '/var/log/iofog-agent/', bluetooth BOOLEAN DEFAULT FALSE, hal BOOLEAN DEFAULT FALSE, log_file_count BIGINT DEFAULT 10, @@ -130,7 +130,6 @@ CREATE TABLE IF NOT EXISTS ChangeTrackings ( version BOOLEAN DEFAULT false, microservice_list BOOLEAN DEFAULT false, config BOOLEAN DEFAULT false, - routing BOOLEAN DEFAULT false, registries BOOLEAN DEFAULT false, tunnel BOOLEAN DEFAULT false, diagnostics BOOLEAN DEFAULT false, @@ -390,21 +389,6 @@ CREATE TABLE IF NOT EXISTS CatalogItemOutputTypes ( CREATE INDEX idx_catalog_item_output_type_catalog_item_id ON CatalogItemOutputTypes (catalog_item_id); -CREATE TABLE IF NOT EXISTS Routings ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - name TEXT NOT NULL, - source_microservice_uuid VARCHAR(36), - dest_microservice_uuid VARCHAR(36), - application_id INT, - FOREIGN KEY (source_microservice_uuid) REFERENCES Microservices (uuid) ON DELETE CASCADE, - FOREIGN KEY (dest_microservice_uuid) REFERENCES Microservices (uuid) ON DELETE CASCADE, - FOREIGN KEY (application_id) REFERENCES Flows (id) ON DELETE CASCADE -); - -CREATE INDEX idx_routing_sourceMicroserviceUuid ON Routings (source_microservice_uuid); -CREATE INDEX idx_routing_destMicroserviceUuid ON Routings (dest_microservice_uuid); -CREATE INDEX idx_routing_applicationId ON Routings (application_id); - CREATE TABLE IF NOT EXISTS Routers ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, is_edge BOOLEAN DEFAULT true, @@ -901,8 +885,11 @@ CREATE TABLE IF NOT EXISTS RbacRoleBindings ( CREATE TABLE IF NOT EXISTS RbacServiceAccounts ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - name TEXT UNIQUE NOT NULL, + name TEXT NOT NULL, role_ref TEXT, + role_id INTEGER, + microservice_uuid VARCHAR(36), + application_id INTEGER, created_at DATETIME, updated_at DATETIME ); @@ -919,14 +906,14 @@ CREATE TABLE IF NOT EXISTS RbacCacheVersion ( updated_at DATETIME ); -ALTER TABLE Microservices ADD COLUMN service_account_id INTEGER; -CREATE INDEX idx_microservices_service_account_id ON Microservices (service_account_id); ALTER TABLE RbacRoleBindings ADD COLUMN role_id INTEGER; CREATE INDEX idx_rbac_role_bindings_role_id ON RbacRoleBindings (role_id); -ALTER TABLE RbacServiceAccounts ADD COLUMN role_id INTEGER; CREATE INDEX idx_rbac_service_accounts_role_id ON RbacServiceAccounts (role_id); +CREATE UNIQUE INDEX idx_rbac_service_accounts_microservice_uuid_unique ON RbacServiceAccounts (microservice_uuid) WHERE microservice_uuid IS NOT NULL; +CREATE UNIQUE INDEX idx_rbac_service_accounts_application_id_name_unique ON RbacServiceAccounts (application_id, name); + CREATE TABLE IF NOT EXISTS ClusterControllers ( uuid VARCHAR(36) PRIMARY KEY NOT NULL, @@ -940,4 +927,180 @@ CREATE TABLE IF NOT EXISTS ClusterControllers ( CREATE INDEX idx_cluster_controllers_uuid ON ClusterControllers (uuid); CREATE INDEX idx_cluster_controllers_host ON ClusterControllers (host); -CREATE INDEX idx_cluster_controllers_active ON ClusterControllers (is_active, last_heartbeat); \ No newline at end of file +CREATE INDEX idx_cluster_controllers_active ON ClusterControllers (is_active, last_heartbeat); + +ALTER TABLE Fogs ADD COLUMN nats_id INT; + +CREATE TABLE IF NOT EXISTS NatsOperators ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + name TEXT UNIQUE NOT NULL, + public_key TEXT NOT NULL, + jwt TEXT NOT NULL, + seed_secret_name TEXT NOT NULL, + created_at DATETIME, + updated_at DATETIME +); + +CREATE TABLE IF NOT EXISTS NatsAccounts ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + name TEXT NOT NULL, + public_key TEXT NOT NULL, + jwt TEXT NOT NULL, + seed_secret_name TEXT NOT NULL, + is_system BOOLEAN DEFAULT false, + is_leaf_system BOOLEAN DEFAULT false, + operator_id INTEGER NOT NULL, + application_id INTEGER, + created_at DATETIME, + updated_at DATETIME, + FOREIGN KEY (operator_id) REFERENCES NatsOperators (id) ON DELETE CASCADE, + FOREIGN KEY (application_id) REFERENCES Flows (id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS NatsUsers ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + name TEXT NOT NULL, + public_key TEXT NOT NULL, + jwt TEXT NOT NULL, + creds_secret_name TEXT NOT NULL, + is_bearer BOOLEAN DEFAULT false, + account_id INTEGER NOT NULL, + microservice_uuid VARCHAR(36), + created_at DATETIME, + updated_at DATETIME, + FOREIGN KEY (account_id) REFERENCES NatsAccounts (id) ON DELETE CASCADE, + FOREIGN KEY (microservice_uuid) REFERENCES Microservices (uuid) ON DELETE SET NULL +); + +CREATE TABLE IF NOT EXISTS NatsInstances ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + iofog_uuid VARCHAR(36), + is_leaf BOOLEAN DEFAULT true, + is_hub BOOLEAN DEFAULT false, + host TEXT, + server_port INTEGER, + leaf_port INTEGER, + cluster_port INTEGER, + mqtt_port INTEGER, + http_port INTEGER, + configmap_name TEXT, + jwt_dir_mount_name TEXT, + cert_secret_name TEXT, + js_storage_size TEXT, + js_memory_store_size TEXT, + created_at DATETIME, + updated_at DATETIME, + FOREIGN KEY (iofog_uuid) REFERENCES Fogs (uuid) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS NatsConnections ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + source_nats INTEGER NOT NULL, + dest_nats INTEGER NOT NULL, + created_at DATETIME, + updated_at DATETIME, + FOREIGN KEY (source_nats) REFERENCES NatsInstances (id) ON DELETE CASCADE, + FOREIGN KEY (dest_nats) REFERENCES NatsInstances (id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS NatsReconcileTasks ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + reason TEXT NOT NULL, + application_id INTEGER, + account_rule_id INTEGER, + user_rule_id INTEGER, + fog_uuids TEXT, + status TEXT NOT NULL DEFAULT 'pending', + leader_uuid VARCHAR(36), + claimed_at DATETIME, + created_at DATETIME, + updated_at DATETIME +); + +CREATE TABLE IF NOT EXISTS NatsAccountRules ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + name TEXT UNIQUE NOT NULL, + description TEXT, + info_url TEXT, + max_connections INTEGER, + max_leaf_node_connections INTEGER, + max_data BIGINT, + max_exports INTEGER, + max_imports INTEGER, + max_msg_payload INTEGER, + max_subscriptions INTEGER, + exports_allow_wildcards BOOLEAN DEFAULT true, + disallow_bearer BOOLEAN, + response_permissions TEXT, + resp_max INTEGER, + resp_ttl BIGINT, + imports TEXT, + exports TEXT, + mem_storage BIGINT, + disk_storage BIGINT, + streams INTEGER, + consumer INTEGER, + max_ack_pending INTEGER, + mem_max_stream_bytes BIGINT, + disk_max_stream_bytes BIGINT, + max_bytes_required BOOLEAN, + tiered_limits TEXT, + pub_allow TEXT, + pub_deny TEXT, + sub_allow TEXT, + sub_deny TEXT, + created_at DATETIME, + updated_at DATETIME +); + +CREATE TABLE IF NOT EXISTS NatsUserRules ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + name TEXT UNIQUE NOT NULL, + description TEXT, + max_subscriptions INTEGER, + max_payload INTEGER, + max_data BIGINT, + bearer_token BOOLEAN DEFAULT false, + proxy_required BOOLEAN, + allowed_connection_types TEXT, + src TEXT, + times TEXT, + times_location TEXT, + resp_max INTEGER, + resp_ttl BIGINT, + pub_allow TEXT, + pub_deny TEXT, + sub_allow TEXT, + sub_deny TEXT, + tags TEXT, + created_at DATETIME, + updated_at DATETIME +); + +CREATE UNIQUE INDEX idx_nats_accounts_application_id_unique ON NatsAccounts (application_id) WHERE application_id IS NOT NULL; +CREATE INDEX idx_nats_accounts_application_id ON NatsAccounts (application_id); +CREATE UNIQUE INDEX idx_nats_users_account_id_name ON NatsUsers (account_id, name); +CREATE INDEX idx_nats_users_account_id ON NatsUsers (account_id); +CREATE INDEX idx_nats_users_microservice_uuid ON NatsUsers (microservice_uuid); +ALTER TABLE NatsUsers ADD COLUMN nats_user_rule_id INTEGER REFERENCES NatsUserRules (id); +CREATE INDEX idx_nats_users_nats_user_rule_id ON NatsUsers (nats_user_rule_id); +CREATE UNIQUE INDEX idx_nats_instances_iofog_uuid_unique ON NatsInstances (iofog_uuid); +CREATE INDEX idx_nats_instances_iofog_uuid ON NatsInstances (iofog_uuid); +CREATE UNIQUE INDEX idx_nats_connections_source_dest_unique ON NatsConnections (source_nats, dest_nats); +CREATE INDEX idx_nats_connections_source_nats ON NatsConnections (source_nats); +CREATE INDEX idx_nats_connections_dest_nats ON NatsConnections (dest_nats); +CREATE INDEX idx_nats_account_rules_name ON NatsAccountRules (name); +CREATE INDEX idx_nats_user_rules_name ON NatsUserRules (name); +CREATE INDEX idx_nats_reconcile_tasks_status_claimed ON NatsReconcileTasks (status, claimed_at); + +ALTER TABLE Flows ADD COLUMN nats_access BOOLEAN DEFAULT false; +ALTER TABLE Flows ADD COLUMN nats_rule_id INTEGER; +ALTER TABLE Microservices ADD COLUMN nats_rule_id INTEGER; +ALTER TABLE Microservices ADD COLUMN nats_access BOOLEAN DEFAULT false; +ALTER TABLE Microservices ADD COLUMN nats_account_id INTEGER; +ALTER TABLE Microservices ADD COLUMN nats_user_id INTEGER; +ALTER TABLE Microservices ADD COLUMN nats_creds_secret_name TEXT; +CREATE INDEX idx_flows_nats_rule_id ON Flows (nats_rule_id); +CREATE INDEX idx_microservices_nats_rule_id ON Microservices (nats_rule_id); +CREATE INDEX idx_microservices_nats_account_id ON Microservices (nats_account_id); +CREATE INDEX idx_microservices_nats_user_id ON Microservices (nats_user_id); diff --git a/src/data/models/application.js b/src/data/models/application.js index e1fc5504b..51687bc96 100644 --- a/src/data/models/application.js +++ b/src/data/models/application.js @@ -29,6 +29,16 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.BOOLEAN, field: 'is_system', defaultValue: false + }, + natsAccess: { + type: DataTypes.BOOLEAN, + field: 'nats_access', + defaultValue: false + }, + natsRuleId: { + type: DataTypes.INTEGER, + field: 'nats_rule_id', + allowNull: true } }, { tableName: 'Flows', @@ -43,6 +53,15 @@ module.exports = (sequelize, DataTypes) => { }, as: 'microservices' }) + + Application.belongsTo(models.NatsAccountRule, { + foreignKey: { + name: 'natsRuleId', + field: 'nats_rule_id' + }, + as: 'natsRule', + onDelete: 'set null' + }) } return Application } diff --git a/src/data/models/changetracking.js b/src/data/models/changetracking.js index 4b303c01a..77af5d077 100644 --- a/src/data/models/changetracking.js +++ b/src/data/models/changetracking.js @@ -51,11 +51,6 @@ module.exports = (sequelize, DataTypes) => { field: 'config', defaultValue: false }, - routing: { - type: DataTypes.BOOLEAN, - field: 'routing', - defaultValue: false - }, registries: { type: DataTypes.BOOLEAN, field: 'registries', diff --git a/src/data/models/fog.js b/src/data/models/fog.js index 7bd62e3f1..bd0342caf 100644 --- a/src/data/models/fog.js +++ b/src/data/models/fog.js @@ -396,6 +396,11 @@ module.exports = (sequelize, DataTypes) => { as: 'router' }) + Fog.hasOne(models.NatsInstance, { + foreignKey: 'iofog_uuid', + as: 'nats' + }) + Fog.belongsToMany(models.Tags, { through: 'IofogTags', as: 'tags' }) Fog.belongsToMany(models.EdgeResource, { through: 'AgentEdgeResources', as: 'edgeResources' }) Fog.belongsToMany(models.VolumeMount, { through: 'FogVolumeMounts', as: 'volumeMounts' }) diff --git a/src/data/models/index.js b/src/data/models/index.js index 1aa27695b..1cac68d3f 100644 --- a/src/data/models/index.js +++ b/src/data/models/index.js @@ -35,7 +35,14 @@ const initializeModels = (sequelize) => { } const configureImage = async (db, name, fogTypes, images) => { - const catalogItem = await db.CatalogItem.findOne({ where: { name, isPublic: false } }) + const isNats = name === constants.NATS_CATALOG_NAME + const catalogItem = await db.CatalogItem.findOne({ + where: isNats ? { name } : { name, isPublic: false } + }) + if (!catalogItem) { + logger.warn(`Catalog item not found for ${name}, skipping image configuration`) + return + } for (const fogType of fogTypes) { if (fogType.id === 0) { // Skip auto detect type @@ -82,6 +89,7 @@ db.initDB = async (isStart) => { const fogTypes = await db.FogType.findAll({}) await configureImage(db, constants.ROUTER_CATALOG_NAME, fogTypes, config.get('systemImages.router', {})) await configureImage(db, constants.DEBUG_CATALOG_NAME, fogTypes, config.get('systemImages.debug', {})) + await configureImage(db, constants.NATS_CATALOG_NAME, fogTypes, config.get('systemImages.nats', {})) // Initialize controller UUID try { diff --git a/src/data/models/microservice.js b/src/data/models/microservice.js index c8fde4f39..be04c7772 100644 --- a/src/data/models/microservice.js +++ b/src/data/models/microservice.js @@ -119,9 +119,29 @@ module.exports = (sequelize, DataTypes) => { field: 'is_activated', defaultValue: true }, - serviceAccountId: { + natsAccess: { + type: DataTypes.BOOLEAN, + field: 'nats_access', + defaultValue: false + }, + natsAccountId: { type: DataTypes.INTEGER, - field: 'service_account_id', + field: 'nats_account_id', + allowNull: true + }, + natsUserId: { + type: DataTypes.INTEGER, + field: 'nats_user_id', + allowNull: true + }, + natsCredsSecretName: { + type: DataTypes.TEXT, + field: 'nats_creds_secret_name', + allowNull: true + }, + natsRuleId: { + type: DataTypes.INTEGER, + field: 'nats_rule_id', allowNull: true } }, { @@ -187,11 +207,6 @@ module.exports = (sequelize, DataTypes) => { as: 'strace' }) - Microservice.hasMany(models.Routing, { - foreignKey: 'source_microservice_uuid', - as: 'routes' - }) - Microservice.hasOne(models.MicroserviceStatus, { foreignKey: 'microservice_uuid', as: 'microserviceStatus' @@ -237,15 +252,35 @@ module.exports = (sequelize, DataTypes) => { as: 'extraHosts' }) - Microservice.belongsToMany(models.Tags, { as: 'pubTags', through: 'MicroservicePubTags' }) - Microservice.belongsToMany(models.Tags, { as: 'subTags', through: 'MicroserviceSubTags' }) + Microservice.hasOne(models.RbacServiceAccount, { + foreignKey: 'microservice_uuid', + as: 'serviceAccount', + onDelete: 'cascade' + }) - Microservice.belongsTo(models.RbacServiceAccount, { + Microservice.belongsTo(models.NatsAccount, { foreignKey: { - name: 'serviceAccountId', - field: 'service_account_id' + name: 'natsAccountId', + field: 'nats_account_id' }, - as: 'serviceAccount' + as: 'natsAccount' + }) + + Microservice.belongsTo(models.NatsUser, { + foreignKey: { + name: 'natsUserId', + field: 'nats_user_id' + }, + as: 'natsUser' + }) + + Microservice.belongsTo(models.NatsUserRule, { + foreignKey: { + name: 'natsRuleId', + field: 'nats_rule_id' + }, + as: 'natsRule', + onDelete: 'set null' }) } diff --git a/src/data/models/microservicePubTags.js b/src/data/models/microservicePubTags.js deleted file mode 100644 index 1cd759355..000000000 --- a/src/data/models/microservicePubTags.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict' -module.exports = (sequelize, DataTypes) => { - const MicroservicePubTags = sequelize.define('MicroservicePubTags', {}, { - tableName: 'MicroservicePubTags', - timestamps: false, - underscored: true - }) - return MicroservicePubTags -} diff --git a/src/data/models/microserviceSubTags.js b/src/data/models/microserviceSubTags.js deleted file mode 100644 index 7de19bd48..000000000 --- a/src/data/models/microserviceSubTags.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict' -module.exports = (sequelize, DataTypes) => { - const MicroserviceSubTags = sequelize.define('MicroserviceSubTags', {}, { - tableName: 'MicroserviceSubTags', - timestamps: false, - underscored: true - }) - return MicroserviceSubTags -} diff --git a/src/data/models/natsAccount.js b/src/data/models/natsAccount.js new file mode 100644 index 000000000..e9c9b5b16 --- /dev/null +++ b/src/data/models/natsAccount.js @@ -0,0 +1,92 @@ +'use strict' + +module.exports = (sequelize, DataTypes) => { + const NatsAccount = sequelize.define('NatsAccount', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + field: 'id' + }, + name: { + type: DataTypes.TEXT, + allowNull: false, + field: 'name' + }, + publicKey: { + type: DataTypes.TEXT, + allowNull: false, + field: 'public_key' + }, + jwt: { + type: DataTypes.TEXT, + allowNull: false, + field: 'jwt' + }, + seedSecretName: { + type: DataTypes.TEXT, + allowNull: false, + field: 'seed_secret_name' + }, + isSystem: { + type: DataTypes.BOOLEAN, + allowNull: false, + field: 'is_system', + defaultValue: false + }, + isLeafSystem: { + type: DataTypes.BOOLEAN, + allowNull: false, + field: 'is_leaf_system', + defaultValue: false + }, + operatorId: { + type: DataTypes.INTEGER, + allowNull: false, + field: 'operator_id' + }, + applicationId: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'application_id' + } + }, { + tableName: 'NatsAccounts', + timestamps: true, + underscored: true, + indexes: [ + { + unique: true, + fields: ['application_id'] + } + ] + }) + + NatsAccount.associate = function (models) { + NatsAccount.belongsTo(models.NatsOperator, { + foreignKey: { + name: 'operatorId', + field: 'operator_id' + }, + as: 'operator', + onDelete: 'cascade' + }) + + NatsAccount.belongsTo(models.Application, { + foreignKey: { + name: 'applicationId', + field: 'application_id' + }, + as: 'application', + onDelete: 'cascade' + }) + + NatsAccount.hasMany(models.NatsUser, { + foreignKey: 'account_id', + as: 'users' + }) + } + + return NatsAccount +} diff --git a/src/data/models/natsAccountRule.js b/src/data/models/natsAccountRule.js new file mode 100644 index 000000000..896c814c6 --- /dev/null +++ b/src/data/models/natsAccountRule.js @@ -0,0 +1,209 @@ +'use strict' + +const AppHelper = require('../../helpers/app-helper') + +function _bigIntGetter (field) { + return function () { + const raw = this.getDataValue(field) + return AppHelper.convertToInt(raw, null) + } +} + +function _bigIntSetter (field) { + return function (value) { + const n = value == null ? null : parseInt(value, 10) + this.setDataValue(field, (n != null && !isNaN(n)) ? n : null) + } +} + +module.exports = (sequelize, DataTypes) => { + const NatsAccountRule = sequelize.define('NatsAccountRule', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + field: 'id' + }, + name: { + type: DataTypes.TEXT, + allowNull: false, + unique: true, + field: 'name' + }, + description: { + type: DataTypes.TEXT, + allowNull: true, + field: 'description' + }, + infoUrl: { + type: DataTypes.TEXT, + allowNull: true, + field: 'info_url' + }, + maxConnections: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'max_connections' + }, + maxLeafNodeConnections: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'max_leaf_node_connections' + }, + maxData: { + type: DataTypes.BIGINT, + allowNull: true, + field: 'max_data', + get: _bigIntGetter('maxData'), + set: _bigIntSetter('maxData') + }, + maxExports: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'max_exports' + }, + maxImports: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'max_imports' + }, + maxMsgPayload: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'max_msg_payload' + }, + maxSubscriptions: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'max_subscriptions' + }, + exportsAllowWildcards: { + type: DataTypes.BOOLEAN, + allowNull: false, + field: 'exports_allow_wildcards', + defaultValue: true + }, + disallowBearer: { + type: DataTypes.BOOLEAN, + allowNull: true, + field: 'disallow_bearer' + }, + responsePermissions: { + type: DataTypes.TEXT, + allowNull: true, + field: 'response_permissions' + }, + respMax: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'resp_max' + }, + respTtl: { + type: DataTypes.BIGINT, + allowNull: true, + field: 'resp_ttl', + get: _bigIntGetter('respTtl'), + set: _bigIntSetter('respTtl') + }, + imports: { + type: DataTypes.TEXT, + allowNull: true, + field: 'imports' + }, + exports: { + type: DataTypes.TEXT, + allowNull: true, + field: 'exports' + }, + memStorage: { + type: DataTypes.BIGINT, + allowNull: true, + field: 'mem_storage', + get: _bigIntGetter('memStorage'), + set: _bigIntSetter('memStorage') + }, + diskStorage: { + type: DataTypes.BIGINT, + allowNull: true, + field: 'disk_storage', + get: _bigIntGetter('diskStorage'), + set: _bigIntSetter('diskStorage') + }, + streams: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'streams' + }, + consumer: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'consumer' + }, + maxAckPending: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'max_ack_pending' + }, + memMaxStreamBytes: { + type: DataTypes.BIGINT, + allowNull: true, + field: 'mem_max_stream_bytes', + get: _bigIntGetter('memMaxStreamBytes'), + set: _bigIntSetter('memMaxStreamBytes') + }, + diskMaxStreamBytes: { + type: DataTypes.BIGINT, + allowNull: true, + field: 'disk_max_stream_bytes', + get: _bigIntGetter('diskMaxStreamBytes'), + set: _bigIntSetter('diskMaxStreamBytes') + }, + maxBytesRequired: { + type: DataTypes.BOOLEAN, + allowNull: true, + field: 'max_bytes_required' + }, + tieredLimits: { + type: DataTypes.TEXT, + allowNull: true, + field: 'tiered_limits' + }, + pubAllow: { + type: DataTypes.TEXT, + allowNull: true, + field: 'pub_allow' + }, + pubDeny: { + type: DataTypes.TEXT, + allowNull: true, + field: 'pub_deny' + }, + subAllow: { + type: DataTypes.TEXT, + allowNull: true, + field: 'sub_allow' + }, + subDeny: { + type: DataTypes.TEXT, + allowNull: true, + field: 'sub_deny' + } + }, { + tableName: 'NatsAccountRules', + timestamps: true, + underscored: true + }) + + NatsAccountRule.associate = function (models) { + NatsAccountRule.hasMany(models.Application, { + foreignKey: { + name: 'natsRuleId', + field: 'nats_rule_id' + }, + as: 'applications' + }) + } + + return NatsAccountRule +} diff --git a/src/data/models/natsConnection.js b/src/data/models/natsConnection.js new file mode 100644 index 000000000..fb901d82e --- /dev/null +++ b/src/data/models/natsConnection.js @@ -0,0 +1,39 @@ +'use strict' + +module.exports = (sequelize, DataTypes) => { + const NatsConnection = sequelize.define('NatsConnection', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + field: 'id' + } + }, { + tableName: 'NatsConnections', + timestamps: true, + underscored: true + }) + + NatsConnection.associate = function (models) { + NatsConnection.belongsTo(models.NatsInstance, { + foreignKey: { + name: 'sourceNats', + field: 'source_nats' + }, + as: 'source', + onDelete: 'cascade' + }) + + NatsConnection.belongsTo(models.NatsInstance, { + foreignKey: { + name: 'destNats', + field: 'dest_nats' + }, + as: 'dest', + onDelete: 'cascade' + }) + } + + return NatsConnection +} diff --git a/src/data/models/natsInstance.js b/src/data/models/natsInstance.js new file mode 100644 index 000000000..17a9a41a3 --- /dev/null +++ b/src/data/models/natsInstance.js @@ -0,0 +1,108 @@ +'use strict' + +module.exports = (sequelize, DataTypes) => { + const NatsInstance = sequelize.define('NatsInstance', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + field: 'id' + }, + isLeaf: { + type: DataTypes.BOOLEAN, + allowNull: false, + field: 'is_leaf', + defaultValue: true + }, + isHub: { + type: DataTypes.BOOLEAN, + allowNull: false, + field: 'is_hub', + defaultValue: false + }, + host: { + type: DataTypes.TEXT, + allowNull: true, + field: 'host' + }, + serverPort: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'server_port' + }, + leafPort: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'leaf_port' + }, + clusterPort: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'cluster_port' + }, + mqttPort: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'mqtt_port' + }, + httpPort: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'http_port' + }, + configMapName: { + type: DataTypes.TEXT, + allowNull: true, + field: 'configmap_name' + }, + jwtDirMountName: { + type: DataTypes.TEXT, + allowNull: true, + field: 'jwt_dir_mount_name' + }, + certSecretName: { + type: DataTypes.TEXT, + allowNull: true, + field: 'cert_secret_name' + }, + jsStorageSize: { + type: DataTypes.TEXT, + allowNull: true, + field: 'js_storage_size' + }, + jsMemoryStoreSize: { + type: DataTypes.TEXT, + allowNull: true, + field: 'js_memory_store_size' + } + }, { + tableName: 'NatsInstances', + timestamps: true, + underscored: true, + indexes: [ + { + unique: true, + fields: ['iofog_uuid'] + } + ] + }) + + NatsInstance.associate = function (models) { + NatsInstance.belongsTo(models.Fog, { + foreignKey: { + name: 'iofogUuid', + field: 'iofog_uuid' + }, + as: 'iofog', + onDelete: 'cascade' + }) + + NatsInstance.hasMany(models.NatsConnection, { + foreignKey: 'source_nats', + as: 'upstreamNats' + }) + } + + return NatsInstance +} diff --git a/src/data/models/natsOperator.js b/src/data/models/natsOperator.js new file mode 100644 index 000000000..a5465c6e7 --- /dev/null +++ b/src/data/models/natsOperator.js @@ -0,0 +1,47 @@ +'use strict' + +module.exports = (sequelize, DataTypes) => { + const NatsOperator = sequelize.define('NatsOperator', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + field: 'id' + }, + name: { + type: DataTypes.TEXT, + allowNull: false, + unique: true, + field: 'name' + }, + publicKey: { + type: DataTypes.TEXT, + allowNull: false, + field: 'public_key' + }, + jwt: { + type: DataTypes.TEXT, + allowNull: false, + field: 'jwt' + }, + seedSecretName: { + type: DataTypes.TEXT, + allowNull: false, + field: 'seed_secret_name' + } + }, { + tableName: 'NatsOperators', + timestamps: true, + underscored: true + }) + + NatsOperator.associate = function (models) { + NatsOperator.hasMany(models.NatsAccount, { + foreignKey: 'operator_id', + as: 'accounts' + }) + } + + return NatsOperator +} diff --git a/src/data/models/natsReconcileTask.js b/src/data/models/natsReconcileTask.js new file mode 100644 index 000000000..961d2fc00 --- /dev/null +++ b/src/data/models/natsReconcileTask.js @@ -0,0 +1,60 @@ +'use strict' + +module.exports = (sequelize, DataTypes) => { + const NatsReconcileTask = sequelize.define('NatsReconcileTask', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + field: 'id' + }, + reason: { + type: DataTypes.STRING(64), + allowNull: false, + field: 'reason' + }, + applicationId: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'application_id' + }, + accountRuleId: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'account_rule_id' + }, + userRuleId: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'user_rule_id' + }, + fogUuids: { + type: DataTypes.TEXT, + allowNull: true, + field: 'fog_uuids' + }, + status: { + type: DataTypes.STRING(32), + allowNull: false, + field: 'status', + defaultValue: 'pending' + }, + leaderUuid: { + type: DataTypes.STRING(36), + allowNull: true, + field: 'leader_uuid' + }, + claimedAt: { + type: DataTypes.DATE, + allowNull: true, + field: 'claimed_at' + } + }, { + tableName: 'NatsReconcileTasks', + timestamps: true, + underscored: true + }) + + return NatsReconcileTask +} diff --git a/src/data/models/natsUser.js b/src/data/models/natsUser.js new file mode 100644 index 000000000..2f345697c --- /dev/null +++ b/src/data/models/natsUser.js @@ -0,0 +1,89 @@ +'use strict' + +module.exports = (sequelize, DataTypes) => { + const NatsUser = sequelize.define('NatsUser', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + field: 'id' + }, + name: { + type: DataTypes.TEXT, + allowNull: false, + field: 'name' + }, + publicKey: { + type: DataTypes.TEXT, + allowNull: false, + field: 'public_key' + }, + jwt: { + type: DataTypes.TEXT, + allowNull: false, + field: 'jwt' + }, + credsSecretName: { + type: DataTypes.TEXT, + allowNull: false, + field: 'creds_secret_name' + }, + isBearer: { + type: DataTypes.BOOLEAN, + allowNull: false, + field: 'is_bearer', + defaultValue: false + }, + accountId: { + type: DataTypes.INTEGER, + allowNull: false, + field: 'account_id' + }, + microserviceUuid: { + type: DataTypes.STRING(36), + allowNull: true, + field: 'microservice_uuid' + }, + natsUserRuleId: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'nats_user_rule_id' + } + }, { + tableName: 'NatsUsers', + timestamps: true, + underscored: true + }) + + NatsUser.associate = function (models) { + NatsUser.belongsTo(models.NatsAccount, { + foreignKey: { + name: 'accountId', + field: 'account_id' + }, + as: 'account', + onDelete: 'cascade' + }) + + NatsUser.belongsTo(models.Microservice, { + foreignKey: { + name: 'microserviceUuid', + field: 'microservice_uuid' + }, + as: 'microservice', + onDelete: 'set null' + }) + + NatsUser.belongsTo(models.NatsUserRule, { + foreignKey: { + name: 'natsUserRuleId', + field: 'nats_user_rule_id' + }, + as: 'natsUserRule', + onDelete: 'set null' + }) + } + + return NatsUser +} diff --git a/src/data/models/natsUserRule.js b/src/data/models/natsUserRule.js new file mode 100644 index 000000000..c0457b15d --- /dev/null +++ b/src/data/models/natsUserRule.js @@ -0,0 +1,141 @@ +'use strict' + +const AppHelper = require('../../helpers/app-helper') + +function _bigIntGetter (field) { + return function () { + const raw = this.getDataValue(field) + return AppHelper.convertToInt(raw, null) + } +} + +function _bigIntSetter (field) { + return function (value) { + const n = value == null ? null : parseInt(value, 10) + this.setDataValue(field, (n != null && !isNaN(n)) ? n : null) + } +} + +module.exports = (sequelize, DataTypes) => { + const NatsUserRule = sequelize.define('NatsUserRule', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + field: 'id' + }, + name: { + type: DataTypes.TEXT, + allowNull: false, + unique: true, + field: 'name' + }, + description: { + type: DataTypes.TEXT, + allowNull: true, + field: 'description' + }, + maxSubscriptions: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'max_subscriptions' + }, + maxPayload: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'max_payload' + }, + maxData: { + type: DataTypes.BIGINT, + allowNull: true, + field: 'max_data', + get: _bigIntGetter('maxData'), + set: _bigIntSetter('maxData') + }, + bearerToken: { + type: DataTypes.BOOLEAN, + allowNull: false, + field: 'bearer_token', + defaultValue: false + }, + proxyRequired: { + type: DataTypes.BOOLEAN, + allowNull: true, + field: 'proxy_required' + }, + allowedConnectionTypes: { + type: DataTypes.TEXT, + allowNull: true, + field: 'allowed_connection_types' + }, + src: { + type: DataTypes.TEXT, + allowNull: true, + field: 'src' + }, + times: { + type: DataTypes.TEXT, + allowNull: true, + field: 'times' + }, + timesLocation: { + type: DataTypes.TEXT, + allowNull: true, + field: 'times_location' + }, + respMax: { + type: DataTypes.INTEGER, + allowNull: true, + field: 'resp_max' + }, + respTtl: { + type: DataTypes.BIGINT, + allowNull: true, + field: 'resp_ttl', + get: _bigIntGetter('respTtl'), + set: _bigIntSetter('respTtl') + }, + pubAllow: { + type: DataTypes.TEXT, + allowNull: true, + field: 'pub_allow' + }, + pubDeny: { + type: DataTypes.TEXT, + allowNull: true, + field: 'pub_deny' + }, + subAllow: { + type: DataTypes.TEXT, + allowNull: true, + field: 'sub_allow' + }, + subDeny: { + type: DataTypes.TEXT, + allowNull: true, + field: 'sub_deny' + }, + tags: { + type: DataTypes.TEXT, + allowNull: true, + field: 'tags' + } + }, { + tableName: 'NatsUserRules', + timestamps: true, + underscored: true + }) + + NatsUserRule.associate = function (models) { + NatsUserRule.hasMany(models.Microservice, { + foreignKey: { + name: 'natsRuleId', + field: 'nats_rule_id' + }, + as: 'microservices' + }) + } + + return NatsUserRule +} diff --git a/src/data/models/rbacServiceAccount.js b/src/data/models/rbacServiceAccount.js index e693efa55..09c2bde0e 100644 --- a/src/data/models/rbacServiceAccount.js +++ b/src/data/models/rbacServiceAccount.js @@ -12,8 +12,17 @@ module.exports = (sequelize, DataTypes) => { name: { type: DataTypes.TEXT, allowNull: false, - field: 'name', - unique: true + field: 'name' + }, + microserviceUuid: { + type: DataTypes.STRING(36), + field: 'microservice_uuid', + allowNull: true + }, + applicationId: { + type: DataTypes.INTEGER, + field: 'application_id', + allowNull: true }, roleRef: { type: DataTypes.TEXT, @@ -48,7 +57,11 @@ module.exports = (sequelize, DataTypes) => { indexes: [ { unique: true, - fields: ['name'] + fields: ['microserviceUuid'] + }, + { + unique: true, + fields: ['applicationId', 'name'] } ] }) @@ -61,6 +74,14 @@ module.exports = (sequelize, DataTypes) => { }, as: 'role' }) + RbacServiceAccount.belongsTo(models.Microservice, { + foreignKey: 'microserviceUuid', + as: 'microservice' + }) + RbacServiceAccount.belongsTo(models.Application, { + foreignKey: 'applicationId', + as: 'application' + }) } return RbacServiceAccount diff --git a/src/data/models/routing.js b/src/data/models/routing.js deleted file mode 100644 index 3f748ae77..000000000 --- a/src/data/models/routing.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict' -module.exports = (sequelize, DataTypes) => { - const Routing = sequelize.define('Routing', { - id: { - type: DataTypes.INTEGER, - primaryKey: true, - autoIncrement: true, - allowNull: false, - field: 'id' - }, - name: { - type: DataTypes.TEXT, - allowNull: false, - field: 'name' - } - }, { - tableName: 'Routings', - timestamps: false, - underscored: true - }) - Routing.associate = function (models) { - Routing.belongsTo(models.Microservice, { - foreignKey: { - name: 'sourceMicroserviceUuid', - field: 'source_microservice_uuid' - }, - as: 'sourceMicroservice', - onDelete: 'cascade' - }) - - Routing.belongsTo(models.Microservice, { - foreignKey: { - name: 'destMicroserviceUuid', - field: 'dest_microservice_uuid' - }, - as: 'destMicroservice', - onDelete: 'cascade' - }) - - Routing.belongsTo(models.Application, { - foreignKey: { - name: 'applicationId', - field: 'application_id' - }, - as: 'application', - onDelete: 'cascade' - }) - } - return Routing -} diff --git a/src/data/models/tags.js b/src/data/models/tags.js index 9c7957722..16be47f07 100644 --- a/src/data/models/tags.js +++ b/src/data/models/tags.js @@ -22,8 +22,6 @@ module.exports = (sequelize, DataTypes) => { Tags.associate = function (models) { Tags.belongsToMany(models.Fog, { through: 'IofogTags', as: 'iofogs' }) Tags.belongsToMany(models.EdgeResource, { through: 'EdgeResourceOrchestrationTags', as: 'edgeResources' }) - Tags.belongsToMany(models.Microservice, { through: 'MicroservicePubTags', as: 'pubMicroservices' }) - Tags.belongsToMany(models.Microservice, { through: 'MicroserviceSubTags', as: 'subMicroservices' }) Tags.belongsToMany(models.Service, { through: 'ServiceTags', as: 'services' }) } return Tags diff --git a/src/data/providers/database-provider.js b/src/data/providers/database-provider.js index 70b4414cd..2836f2fcf 100644 --- a/src/data/providers/database-provider.js +++ b/src/data/providers/database-provider.js @@ -252,7 +252,7 @@ class DatabaseProvider { // SQLite migration async runMigrationSQLite (dbName) { const migrationSqlPath = path.resolve(__dirname, '../migrations/sqlite/db_migration_sqlite_v1.1.0.sql') - const migrationVersion = '1.0.9' + const migrationVersion = '1.1.0' if (!fs.existsSync(migrationSqlPath)) { logger.error(`Migration file not found: ${migrationSqlPath}`) @@ -325,7 +325,7 @@ class DatabaseProvider { // MySQL migration async runMigrationMySQL (db) { const migrationSqlPath = path.resolve(__dirname, '../migrations/mysql/db_migration_mysql_v1.1.0.sql') - const migrationVersion = '1.0.9' + const migrationVersion = '1.1.0' if (!fs.existsSync(migrationSqlPath)) { logger.error(`Migration file not found: ${migrationSqlPath}`) @@ -386,7 +386,7 @@ class DatabaseProvider { // PostgreSQL migration async runMigrationPostgres (db) { const migrationSqlPath = path.resolve(__dirname, '../migrations/postgres/db_migration_pg_v1.1.0.sql') - const migrationVersion = '1.0.9' + const migrationVersion = '1.1.0' if (!fs.existsSync(migrationSqlPath)) { logger.error(`Migration file not found: ${migrationSqlPath}`) diff --git a/src/data/providers/sqlite.js b/src/data/providers/sqlite.js index 15312e325..10a21d623 100644 --- a/src/data/providers/sqlite.js +++ b/src/data/providers/sqlite.js @@ -11,7 +11,8 @@ class SqliteDatabaseProvider extends DatabaseProvider { const sqliteConfig = config.get('database.sqlite', {}) sqliteConfig.dialect = 'sqlite' - sqliteConfig.databaseName = process.env.DB_NAME || sqliteConfig.databaseName + const envDbName = typeof process.env.DB_NAME === 'string' ? process.env.DB_NAME.trim() : '' + sqliteConfig.databaseName = envDbName || sqliteConfig.databaseName || 'controller_db.sqlite' if (!sqliteConfig.databaseName.endsWith('.sqlite')) { sqliteConfig.databaseName += '.sqlite' } diff --git a/src/data/seeders/mysql/db_seeder_mysql_v1.0.2.sql b/src/data/seeders/mysql/db_seeder_mysql_v1.0.2.sql index d73d393ee..d20573e27 100644 --- a/src/data/seeders/mysql/db_seeder_mysql_v1.0.2.sql +++ b/src/data/seeders/mysql/db_seeder_mysql_v1.0.2.sql @@ -11,7 +11,7 @@ VALUES ('RESTBlue', 'REST API for Bluetooth Low Energy layer.', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, true, 1), ('HAL', 'REST API for Hardware Abstraction layer.', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, true, 1), ('Debug', 'The built-in debugger for Datasance PoT IoFog Agent.', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, false, 1), - ('NATs', 'NATs server microservice for Datasance PoT', 'UTILITIES', 'Datasance', 0, 0, 'none.png', NULL, true, 1); + ('NATs', 'NATs server microservice for Datasance PoT', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, true, 1); INSERT INTO `FogTypes` (id, name, image, description, network_catalog_item_id, hal_catalog_item_id, bluetooth_catalog_item_id) VALUES diff --git a/src/data/seeders/postgres/db_seeder_pg_v1.0.2.sql b/src/data/seeders/postgres/db_seeder_pg_v1.0.2.sql index ca8d08218..8efec9846 100644 --- a/src/data/seeders/postgres/db_seeder_pg_v1.0.2.sql +++ b/src/data/seeders/postgres/db_seeder_pg_v1.0.2.sql @@ -11,7 +11,7 @@ VALUES ('RESTBlue', 'REST API for Bluetooth Low Energy layer.', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, true, 1), ('HAL', 'REST API for Hardware Abstraction layer.', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, true, 1), ('Debug', 'The built-in debugger for Datasance PoT IoFog Agent.', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, false, 1), - ('NATs', 'NATs server microservice for Datasance PoT', 'UTILITIES', 'Datasance', 0, 0, 'none.png', NULL, true, 1); + ('NATs', 'NATs server microservice for Datasance PoT', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, true, 1); INSERT INTO "FogTypes" (id, name, image, description, network_catalog_item_id, hal_catalog_item_id, bluetooth_catalog_item_id) VALUES diff --git a/src/data/seeders/sqlite/db_seeder_sqlite_v1.0.2.sql b/src/data/seeders/sqlite/db_seeder_sqlite_v1.0.2.sql index 80d4ee2ce..1f5b1039b 100644 --- a/src/data/seeders/sqlite/db_seeder_sqlite_v1.0.2.sql +++ b/src/data/seeders/sqlite/db_seeder_sqlite_v1.0.2.sql @@ -9,7 +9,7 @@ VALUES ('RESTBlue', 'REST API for Bluetooth Low Energy layer.', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, true, 1), ('HAL', 'REST API for Hardware Abstraction layer.', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, true, 1), ('Debug', 'The built-in debugger for Datasance PoT IoFog Agent.', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, false, 1), - ('NATs', 'NATs server microservice for Datasance PoT', 'UTILITIES', 'Datasance', 0, 0, 'none.png', NULL, true, 1); + ('NATs', 'NATs server microservice for Datasance PoT', 'SYSTEM', 'Datasance', 0, 0, 'none.png', NULL, true, 1); INSERT INTO `FogTypes` (id, name, image, description, network_catalog_item_id, hal_catalog_item_id, bluetooth_catalog_item_id) VALUES diff --git a/src/decorators/transaction-decorator.js b/src/decorators/transaction-decorator.js index 4940cccc4..a1acea956 100644 --- a/src/decorators/transaction-decorator.js +++ b/src/decorators/transaction-decorator.js @@ -74,10 +74,20 @@ function applyTransaction (resolve, reject, transaction, that, ...args) { }) } -function generateTransaction (f) { +/** + * @param {Function} f - Async function that accepts (..., transaction) as last argument + * @param {{ bypassQueue?: boolean }} [options] - If bypassQueue is true, run without enqueueing (so the call does not wait behind long-running queued transactions, e.g. NATS reconcile) + */ +function generateTransaction (f, options = {}) { + const { bypassQueue = false } = options + const t = transaction(f) return function (...args) { - const t = transaction(f) - + if (isTest()) { + return t.apply(this, args) + } + if (bypassQueue) { + return Promise.resolve().then(() => t.apply(this, args)) + } return new Promise((resolve, reject) => { applyTransaction(resolve, reject, t, this, ...args) }) diff --git a/src/helpers/constants.js b/src/helpers/constants.js index c7f13218a..261c69f50 100644 --- a/src/helpers/constants.js +++ b/src/helpers/constants.js @@ -35,8 +35,6 @@ module.exports = { CMD_CATALOG: 'catalog', CMD_FLOW: 'application', CMD_MICROSERVICE: 'microservice', - CMD_ROUTE_CREATE: 'route-create', - CMD_ROUTE_REMOVE: 'route-remove', CMD_PORT_MAPPING_CREATE: 'port-mapping-create', CMD_PORT_MAPPING_REMOVE: 'port-mapping-remove', CMD_PORT_MAPPING_LIST: 'port-mapping-list', @@ -67,11 +65,13 @@ module.exports = { HTTP_CODE_SEE_OTHER: 303, HTTP_CODE_BAD_REQUEST: 400, HTTP_CODE_UNAUTHORIZED: 401, + HTTP_CODE_FORBIDDEN: 403, HTTP_CODE_NOT_FOUND: 404, HTTP_CODE_DUPLICATE_PROPERTY: 409, HTTP_CODE_INTERNAL_ERROR: 500, DEFAULT_ROUTER_NAME: 'default-router', + DEFAULT_NATS_HUB_NAME: 'default-nats-hub', DEFAULT_PROXY_HOST: 'default-proxy-host', RESERVED_PORTS: [54321, 54322], diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index 6e1cfad3c..48be037df 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -18,7 +18,6 @@ module.exports = { INVALID_CATALOG_ITEM_ID: 'Invalid catalog item id \'{}\'', INVALID_FLOW_ID: 'Invalid application id \'{}\'', INVALID_FLOW_NAME: 'Invalid application name \'{}\'', - INVALID_ROUTING_NAME: 'Invalid route name \'{}\'', INVALID_REGISTRY_ID: 'Invalid registry id \'{}\'', UNABLE_TO_CREATE_ACTIVATION_CODE: 'Unable to create activation code', UNABLE_TO_GET_ACTIVATION_CODE: 'Unable to create activation code', @@ -101,9 +100,14 @@ module.exports = { SYSTEM_MICROSERVICE_DELETE: 'Microservice uuid {} is system and can\'t be deleted', INVALID_CONFIG_KEY: 'Unkown config key \'{}\'', INVALID_ROUTER: 'Invalid router \'{}\'', + INVALID_NATS: 'Invalid router \'{}\'', DUPLICATE_SYSTEM_FOG: 'There already is a system fog', INVALID_ROUTER_MODE: 'Invalid router mode \'{}\'', + INVALID_NATS_MODE: 'Invalid NATS mode \'{}\'', + INVALID_SYSTEM_CHANGE: 'System fog can\'t be changed', + INVALID_SYSTEM_FOG_KUBERNETES: 'System fog can\'t be created when ControlPlane is Kubernetes', INVALID_UPSTREAM_ROUTER: 'Upstream router must be interior \'{}\'', + INVALID_UPSTREAM_NATS: 'Upstream nats must be server \'{}\'', EDGE_ROUTER_HAS_DOWNSTREAM: 'Edge router {} has, or will have, downstream routers', HOST_IS_REQUIRED: '"host" is required', PORT_RESERVED: 'Port \'{}\' is reserved for internal use', diff --git a/src/helpers/errors.js b/src/helpers/errors.js index 3d4f8c1cd..95aab9a9a 100644 --- a/src/helpers/errors.js +++ b/src/helpers/errors.js @@ -110,6 +110,14 @@ class ConflictError extends Error { } } +class ForbiddenError extends Error { + constructor (message) { + super(message) + this.message = message + this.name = 'ForbiddenError' + } +} + module.exports = { AuthenticationError: AuthenticationError, TransactionError: TransactionError, @@ -122,5 +130,6 @@ module.exports = { InvalidArgumentError: InvalidArgumentError, InvalidArgumentTypeError: InvalidArgumentTypeError, CLIArgsNotProvidedError: CLIArgsNotProvidedError, - ConflictError: ConflictError + ConflictError: ConflictError, + ForbiddenError: ForbiddenError } diff --git a/src/helpers/system-naming.js b/src/helpers/system-naming.js new file mode 100644 index 000000000..f3a7132e9 --- /dev/null +++ b/src/helpers/system-naming.js @@ -0,0 +1,124 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2023 Datasance Teknoloji A.S. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const logger = require('../logger') +const Errors = require('./errors') +const ApplicationManager = require('../data/managers/application-manager') +const MicroserviceManager = require('../data/managers/microservice-manager') + +const SYSTEM_MICROSERVICE_TYPES = ['router', 'hal', 'ble', 'debug', 'nats'] + +const getSystemAppName = (fogName) => `system-${fogName}` + +const getLegacySystemAppName = (fogUuid) => `system-${fogUuid.toLowerCase()}` + +const getSystemMicroserviceName = (type) => type + +const getLegacySystemMicroserviceName = (type, fogUuid) => + `${type}-${fogUuid.toLowerCase()}` + +const slugifyName = (value, maxLength = 48) => { + const normalized = String(value || '') + .trim() + .toLowerCase() + .replace(/[^a-z0-9-]+/g, '-') + .replace(/-+/g, '-') + .replace(/^-|-$/g, '') + if (!normalized) { + return 'default' + } + return normalized.length > maxLength ? normalized.slice(0, maxLength).replace(/-+$/g, '') : normalized +} + +async function _migrateLegacySystemMicroservices (legacyAppId, targetAppId, fogUuid, transaction) { + for (const type of SYSTEM_MICROSERVICE_TYPES) { + const legacyName = getLegacySystemMicroserviceName(type, fogUuid) + const legacyMs = await MicroserviceManager.findOne({ + name: legacyName, + applicationId: legacyAppId + }, transaction) + if (!legacyMs) { + continue + } + + const canonicalName = getSystemMicroserviceName(type) + const canonicalMs = await MicroserviceManager.findOne({ + name: canonicalName, + applicationId: targetAppId + }, transaction) + + if (canonicalMs) { + logger.warn(`Legacy system microservice "${legacyName}" exists alongside "${canonicalName}". Keeping canonical and deleting legacy.`) + await MicroserviceManager.delete({ uuid: legacyMs.uuid }, transaction) + continue + } + + await MicroserviceManager.update( + { uuid: legacyMs.uuid }, + { name: canonicalName, applicationId: targetAppId }, + transaction + ) + } +} + +async function ensureSystemApplication (fog, transaction) { + if (!fog || !fog.uuid || !fog.name) { + throw new Errors.ValidationError('Missing fog name for system application naming') + } + + const newName = getSystemAppName(fog.name) + const legacyName = getLegacySystemAppName(fog.uuid) + + let application = await ApplicationManager.findOne({ name: newName }, transaction) + const legacyApplication = await ApplicationManager.findOne({ name: legacyName }, transaction) + + if (application && !application.isSystem) { + throw new Errors.ValidationError(`System application name conflict: ${newName}`) + } + + if (!application && legacyApplication) { + await ApplicationManager.update( + { id: legacyApplication.id }, + { name: newName }, + transaction + ) + application = await ApplicationManager.findOne({ id: legacyApplication.id }, transaction) + } + + if (!application) { + application = await ApplicationManager.create({ + name: newName, + isActivated: true, + isSystem: true + }, transaction) + } + + if (legacyApplication && application.id !== legacyApplication.id) { + await _migrateLegacySystemMicroservices(legacyApplication.id, application.id, fog.uuid, transaction) + await ApplicationManager.delete({ id: legacyApplication.id }, transaction) + } else { + await _migrateLegacySystemMicroservices(application.id, application.id, fog.uuid, transaction) + } + + return application +} + +module.exports = { + SYSTEM_MICROSERVICE_TYPES, + getSystemAppName, + getLegacySystemAppName, + getSystemMicroserviceName, + getLegacySystemMicroserviceName, + slugifyName, + ensureSystemApplication +} diff --git a/src/jobs/nats-reconcile-worker-job.js b/src/jobs/nats-reconcile-worker-job.js new file mode 100644 index 000000000..02a282757 --- /dev/null +++ b/src/jobs/nats-reconcile-worker-job.js @@ -0,0 +1,69 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2023 Datasance Teknoloji A.S. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const ClusterControllerService = require('../services/cluster-controller-service') +const NatsService = require('../services/nats-service') +const NatsReconcileTaskManager = require('../data/managers/nats-reconcile-task-manager') +const databaseProvider = require('../data/providers/database-factory') +const Config = require('../config') +const logger = require('../logger') + +const scheduleTime = (Config.get('settings.natsReconcileWorkerIntervalSeconds', 3)) * 1000 + +async function run () { + try { + await processNextTask() + } catch (error) { + logger.error('NATS reconcile worker error:', error) + } finally { + setTimeout(run, scheduleTime) + } +} + +async function processNextTask () { + const uuid = ClusterControllerService.getCurrentControllerUuid() + if (!uuid) { + return + } + const task = await NatsService.claimNextTask(uuid) + if (!task) { + return + } + const fogUuids = task.fogUuids + ? task.fogUuids.split(',').map((s) => s.trim()).filter(Boolean) + : undefined + const options = { + reason: task.reason, + applicationId: task.applicationId, + accountRuleId: task.accountRuleId, + userRuleId: task.userRuleId, + fogUuids: fogUuids && fogUuids.length > 0 ? fogUuids : undefined + } + try { + logger.info(`NATS reconcile task ${task.id} started`) + await NatsService.reconcileResolverArtifacts(options) + logger.info(`NATS reconcile task ${task.id} completed`) + await databaseProvider.sequelize.transaction(async (transaction) => { + await NatsReconcileTaskManager.getEntity().destroy({ + where: { id: task.id }, + transaction + }) + }) + } catch (error) { + logger.error(`NATS reconcile task ${task.id} failed: ${error.message}. Task will be reclaimed after staleness.`) + } +} + +module.exports = { + run +} diff --git a/src/logger/index.js b/src/logger/index.js index db7461a89..91548799a 100644 --- a/src/logger/index.js +++ b/src/logger/index.js @@ -294,9 +294,61 @@ for (const level of Object.keys(levels)) { if (log[0] instanceof Error) { log = serializer.err(...log) } + if (level === 'apiRes' && log[0] && typeof log[0] === 'object') { + log[0] = sanitizeApiResLogPayload(log[0]) + } getConsoleLogger()[level](...log) if (fileLogger !== null) { getLogger()[level](...log) } } } + +function sanitizeApiResLogPayload (payload) { + // Keep original req/res objects intact so pino serializers can process them. + // Redact only the remaining fields with cycle-aware traversal. + const sanitized = {} + for (const [key, value] of Object.entries(payload)) { + if (key === 'req' || key === 'res') { + sanitized[key] = value + continue + } + sanitized[key] = redactSensitiveKeys(value) + } + return sanitized +} + +function redactSensitiveKeys (value, seen = new WeakSet()) { + if (value === null || value === undefined) { + return value + } + + if (typeof value !== 'object') { + return value + } + + if (Buffer.isBuffer(value) || value instanceof Date || value instanceof RegExp) { + return value + } + + if (seen.has(value)) { + return '[Circular]' + } + + seen.add(value) + + if (Array.isArray(value)) { + return value.map((item) => redactSensitiveKeys(item, seen)) + } + + const redacted = {} + for (const [key, item] of Object.entries(value)) { + const loweredKey = key.toLowerCase() + if (loweredKey === 'jwt' || loweredKey === 'creds' || loweredKey.includes('seed') || loweredKey.includes('secret')) { + redacted[key] = '[REDACTED]' + continue + } + redacted[key] = redactSensitiveKeys(item, seen) + } + return redacted +} diff --git a/src/routes/capabilities.js b/src/routes/capabilities.js index 5c20ea3b6..9f576ae19 100644 --- a/src/routes/capabilities.js +++ b/src/routes/capabilities.js @@ -11,6 +11,7 @@ * */ const logger = require('../logger') +const config = require('../config') const rbacMiddleware = require('../lib/rbac/middleware') module.exports = [ @@ -37,5 +38,21 @@ module.exports = [ res.sendStatus(204) }) } + }, + { + method: 'head', + path: '/api/v3/capabilities/nats', + middleware: async (req, res) => { + logger.apiReq(req) + + // Add rbacMiddleware.protect middleware to protect the route + await rbacMiddleware.protect()(req, res, async () => { + if (config.get('nats.enabled')) { + res.sendStatus(204) + return + } + res.sendStatus(404) + }) + } } ] diff --git a/src/routes/microservices.js b/src/routes/microservices.js index e3f68e01f..27a5a8b6e 100644 --- a/src/routes/microservices.js +++ b/src/routes/microservices.js @@ -201,68 +201,6 @@ module.exports = [ }) } }, - { - method: 'get', - path: '/api/v3/microservices/pub/:tag', - middleware: async (req, res) => { - logger.apiReq(req) - - const successCode = constants.HTTP_CODE_SUCCESS - const errorCodes = [ - { - code: constants.HTTP_CODE_UNAUTHORIZED, - errors: [Errors.AuthenticationError] - }, - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - } - ] - - await rbacMiddleware.protect()(req, res, async () => { - const listMicroserviceByPubTagEndPoint = ResponseDecorator.handleErrors(MicroservicesController.listMicroserviceByPubTagEndPoint, - successCode, errorCodes) - const responseObject = await listMicroserviceByPubTagEndPoint(req) - const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token ? req.kauth.grant.access_token.content.preferred_username : 'system' - res - .status(responseObject.code) - .send(responseObject.body) - - logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) - }) - } - }, - { - method: 'get', - path: '/api/v3/microservices/sub/:tag', - middleware: async (req, res) => { - logger.apiReq(req) - - const successCode = constants.HTTP_CODE_SUCCESS - const errorCodes = [ - { - code: constants.HTTP_CODE_UNAUTHORIZED, - errors: [Errors.AuthenticationError] - }, - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - } - ] - - await rbacMiddleware.protect()(req, res, async () => { - const listMicroserviceBySubTagEndPoint = ResponseDecorator.handleErrors(MicroservicesController.listMicroserviceBySubTagEndPoint, - successCode, errorCodes) - const responseObject = await listMicroserviceBySubTagEndPoint(req) - const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token ? req.kauth.grant.access_token.content.preferred_username : 'system' - res - .status(responseObject.code) - .send(responseObject.body) - - logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) - }) - } - }, { method: 'patch', path: '/api/v3/microservices/:uuid', @@ -720,76 +658,6 @@ module.exports = [ }) } }, - { - method: 'post', - path: '/api/v3/microservices/:uuid/routes/:receiverUuid', - middleware: async (req, res) => { - logger.apiReq(req) - - const successCode = constants.HTTP_CODE_CREATED - const errorCodes = [ - { - code: constants.HTTP_CODE_BAD_REQUEST, - errors: [Errors.ValidationError] - }, - { - code: constants.HTTP_CODE_UNAUTHORIZED, - errors: [Errors.AuthenticationError] - }, - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - } - ] - - await rbacMiddleware.protect()(req, res, async () => { - const createMicroserviceRouteEndPoint = ResponseDecorator.handleErrors( - MicroservicesController.createMicroserviceRouteEndPoint, successCode, errorCodes) - const responseObject = await createMicroserviceRouteEndPoint(req) - const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token ? req.kauth.grant.access_token.content.preferred_username : 'system' - res - .status(responseObject.code) - .send(responseObject.body) - - logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) - }) - } - }, - { - method: 'delete', - path: '/api/v3/microservices/:uuid/routes/:receiverUuid', - middleware: async (req, res) => { - logger.apiReq(req) - - const successCode = constants.HTTP_CODE_NO_CONTENT - const errorCodes = [ - { - code: constants.HTTP_CODE_BAD_REQUEST, - errors: [Errors.ValidationError] - }, - { - code: constants.HTTP_CODE_UNAUTHORIZED, - errors: [Errors.AuthenticationError] - }, - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - } - ] - - await rbacMiddleware.protect()(req, res, async () => { - const deleteMicroserviceRouteEndPoint = ResponseDecorator.handleErrors( - MicroservicesController.deleteMicroserviceRouteEndPoint, successCode, errorCodes) - const responseObject = await deleteMicroserviceRouteEndPoint(req) - const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token ? req.kauth.grant.access_token.content.preferred_username : 'system' - res - .status(responseObject.code) - .send(responseObject.body) - - logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) - }) - } - }, { method: 'post', path: '/api/v3/microservices/:uuid/port-mapping', diff --git a/src/routes/nats.js b/src/routes/nats.js new file mode 100644 index 000000000..20aaa59d1 --- /dev/null +++ b/src/routes/nats.js @@ -0,0 +1,705 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2023 Datasance Teknoloji A.S. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ +const constants = require('../helpers/constants') +const NatsController = require('../controllers/nats-controller') +const ResponseDecorator = require('../decorators/response-decorator') +const logger = require('../logger') +const Errors = require('../helpers/errors') +const rbacMiddleware = require('../lib/rbac/middleware') + +module.exports = [ + { + method: 'get', + path: '/api/v3/nats/operator', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.getOperatorEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'post', + path: '/api/v3/nats/operator/rotate', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.rotateOperatorEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'get', + path: '/api/v3/nats/bootstrap', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_FORBIDDEN, errors: [Errors.ForbiddenError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.getBootstrapEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'get', + path: '/api/v3/nats/hub', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.getHubEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'put', + path: '/api/v3/nats/hub', + supportSubstitution: true, + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.upsertHubEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'get', + path: '/api/v3/nats/accounts', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.listAccountsEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'get', + path: '/api/v3/nats/users', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.listAllUsersEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'get', + path: '/api/v3/nats/account-rules', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.listAccountRulesEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'post', + path: '/api/v3/nats/account-rules', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_CREATED + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.createAccountRuleEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'post', + path: '/api/v3/nats/account-rules/yaml', + fileInput: 'natsAccountRule', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_CREATED + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.createAccountRuleFromYamlEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'patch', + path: '/api/v3/nats/account-rules/:ruleName', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.updateAccountRuleEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'patch', + path: '/api/v3/nats/account-rules/yaml/:ruleName', + fileInput: 'natsAccountRule', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.updateAccountRuleFromYamlEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'delete', + path: '/api/v3/nats/account-rules/:ruleName', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_NO_CONTENT + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.deleteAccountRuleEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'get', + path: '/api/v3/nats/user-rules', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.listUserRulesEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'post', + path: '/api/v3/nats/user-rules', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_CREATED + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.createUserRuleEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'post', + path: '/api/v3/nats/user-rules/yaml', + fileInput: 'natsUserRule', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_CREATED + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.createUserRuleFromYamlEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'patch', + path: '/api/v3/nats/user-rules/:ruleName', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.updateUserRuleEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'patch', + path: '/api/v3/nats/user-rules/yaml/:ruleName', + fileInput: 'natsUserRule', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.updateUserRuleFromYamlEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'delete', + path: '/api/v3/nats/user-rules/:ruleName', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_NO_CONTENT + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.deleteUserRuleEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'get', + path: '/api/v3/nats/accounts/:appName', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.getAccountEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'post', + path: '/api/v3/nats/accounts/:appName', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_CREATED + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.ensureAccountEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'get', + path: '/api/v3/nats/accounts/:appName/users', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.listUsersEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'post', + path: '/api/v3/nats/accounts/:appName/users', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_CREATED + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.createUserEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'get', + path: '/api/v3/nats/accounts/:appName/users/:userName/creds', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.getUserCredsEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'delete', + path: '/api/v3/nats/accounts/:appName/users/:userName', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_NO_CONTENT + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.deleteUserEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'post', + path: '/api/v3/nats/accounts/:appName/mqtt-bearer', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_CREATED + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.createMqttBearerEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + }, + { + method: 'delete', + path: '/api/v3/nats/accounts/:appName/mqtt-bearer/:userName', + middleware: async (req, res) => { + logger.apiReq(req) + const successCode = constants.HTTP_CODE_NO_CONTENT + const errorCodes = [ + { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] }, + { code: constants.HTTP_CODE_BAD_REQUEST, errors: [Errors.ValidationError] }, + { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] } + ] + await rbacMiddleware.protect()(req, res, async () => { + const endpoint = ResponseDecorator.handleErrors( + NatsController.deleteMqttBearerEndPoint, + successCode, + errorCodes + ) + const responseObject = await endpoint(req) + const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token + ? req.kauth.grant.access_token.content.preferred_username + : 'system' + res.status(responseObject.code).send(responseObject.body) + logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) + }) + } + } +] diff --git a/src/routes/rbac.js b/src/routes/rbac.js index 1033d8a1a..77d97699f 100644 --- a/src/routes/rbac.js +++ b/src/routes/rbac.js @@ -567,7 +567,7 @@ module.exports = [ }, { method: 'get', - path: '/api/v3/serviceaccounts/:name', + path: '/api/v3/serviceaccounts/:appName/:name', middleware: async (req, res) => { logger.apiReq(req) @@ -597,7 +597,7 @@ module.exports = [ }, { method: 'patch', - path: '/api/v3/serviceaccounts/:name', + path: '/api/v3/serviceaccounts/:appName/:name', middleware: async (req, res) => { logger.apiReq(req) @@ -631,7 +631,7 @@ module.exports = [ }, { method: 'patch', - path: '/api/v3/serviceaccounts/yaml/:name', + path: '/api/v3/serviceaccounts/yaml/:appName/:name', fileInput: 'serviceaccount', middleware: async (req, res) => { logger.apiReq(req) @@ -666,7 +666,7 @@ module.exports = [ }, { method: 'delete', - path: '/api/v3/serviceaccounts/:name', + path: '/api/v3/serviceaccounts/:appName/:name', middleware: async (req, res) => { logger.apiReq(req) @@ -679,6 +679,10 @@ module.exports = [ { code: constants.HTTP_CODE_NOT_FOUND, errors: [Errors.NotFoundError] + }, + { + code: constants.HTTP_CODE_CONFLICT, + errors: [Errors.ConflictError] } ] diff --git a/src/routes/routing.js b/src/routes/routing.js deleted file mode 100644 index 311226ad8..000000000 --- a/src/routes/routing.js +++ /dev/null @@ -1,210 +0,0 @@ -/* - * ******************************************************************************* - * * Copyright (c) 2023 Datasance Teknoloji A.S. - * * - * * This program and the accompanying materials are made available under the - * * terms of the Eclipse Public License v. 2.0 which is available at - * * http://www.eclipse.org/legal/epl-2.0 - * * - * * SPDX-License-Identifier: EPL-2.0 - * ******************************************************************************* - * - */ -const constants = require('../helpers/constants') -const Routing = require('../controllers/routing-controller') -const ResponseDecorator = require('../decorators/response-decorator') -const logger = require('../logger') -const Errors = require('../helpers/errors') -const rbacMiddleware = require('../lib/rbac/middleware') - -module.exports = [ - { - method: 'get', - path: '/api/v3/routes', - middleware: async (req, res) => { - logger.apiReq(req) - - const successCode = constants.HTTP_CODE_SUCCESS - const errorCodes = [ - { - code: constants.HTTP_CODE_UNAUTHORIZED, - errors: [Errors.AuthenticationError] - }, - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - } - ] - - // Protecting for SRE , Developer and Viewer roles - await rbacMiddleware.protect()(req, res, async () => { - const getRouterEndpoint = ResponseDecorator.handleErrors( - Routing.getRoutingsEndPoint, - successCode, - errorCodes - ) - const responseObject = await getRouterEndpoint(req) - const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token ? req.kauth.grant.access_token.content.preferred_username : 'system' - res - .status(responseObject.code) - .send(responseObject.body) - - logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) - }) - } - }, - { - method: 'get', - path: '/api/v3/routes/:appName/:name', - middleware: async (req, res) => { - logger.apiReq(req) - - const successCode = constants.HTTP_CODE_SUCCESS - const errorCodes = [ - { - code: constants.HTTP_CODE_UNAUTHORIZED, - errors: [Errors.AuthenticationError] - }, - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - } - ] - - // Protecting for SRE, Developer, and Viewer roles - await rbacMiddleware.protect()(req, res, async () => { - const getRouterEndpoint = ResponseDecorator.handleErrors( - Routing.getRoutingEndPoint, - successCode, - errorCodes - ) - const responseObject = await getRouterEndpoint(req) - const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token ? req.kauth.grant.access_token.content.preferred_username : 'system' - res - .status(responseObject.code) - .send(responseObject.body) - - logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) - }) - } - }, - { - method: 'post', - path: '/api/v3/routes', - supportSubstitution: true, - middleware: async (req, res) => { - logger.apiReq(req) - - const successCode = constants.HTTP_CODE_SUCCESS - const errorCodes = [ - { - code: constants.HTTP_CODE_UNAUTHORIZED, - errors: [Errors.AuthenticationError] - }, - { - code: constants.HTTP_CODE_BAD_REQUEST, - errors: [Errors.ValidationError] - }, - { - code: constants.HTTP_CODE_BAD_REQUEST, - errors: [Errors.DuplicatePropertyError] - }, - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - } - ] - - // Protecting for SRE and Developer roles - await rbacMiddleware.protect()(req, res, async () => { - const createRoutingEndpoint = ResponseDecorator.handleErrors( - Routing.createRoutingEndpoint, - successCode, - errorCodes - ) - const responseObject = await createRoutingEndpoint(req) - const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token ? req.kauth.grant.access_token.content.preferred_username : 'system' - res - .status(responseObject.code) - .send(responseObject.body) - - logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) - }) - } - }, - { - method: 'patch', - path: '/api/v3/routes/:appName/:name', - supportSubstitution: true, - middleware: async (req, res) => { - logger.apiReq(req) - - const successCode = constants.HTTP_CODE_NO_CONTENT - const errorCodes = [ - { - code: constants.HTTP_CODE_BAD_REQUEST, - errors: [Errors.ValidationError] - }, - { - code: constants.HTTP_CODE_UNAUTHORIZED, - errors: [Errors.AuthenticationError] - }, - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - } - ] - - // Protecting for SRE and Developer roles - await rbacMiddleware.protect()(req, res, async () => { - const updateRoutingEndpoint = ResponseDecorator.handleErrors( - Routing.updateRoutingEndpoint, - successCode, - errorCodes - ) - const responseObject = await updateRoutingEndpoint(req) - const user = req.kauth && req.kauth.grant && req.kauth.grant.access_token ? req.kauth.grant.access_token.content.preferred_username : 'system' - res - .status(responseObject.code) - .send(responseObject.body) - - logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) - }) - } - }, - { - method: 'delete', - path: '/api/v3/routes/:appName/:name', - middleware: async (req, res) => { - logger.apiReq(req) - - const successCode = constants.HTTP_CODE_NO_CONTENT - const errorCodes = [ - { - code: constants.HTTP_CODE_UNAUTHORIZED, - errors: [Errors.AuthenticationError] - }, - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - } - ] - - // Protecting for SRE and Developer roles - await rbacMiddleware.protect()(req, res, async () => { - const deleteRoutingEndpoint = ResponseDecorator.handleErrors( - Routing.deleteRoutingEndpoint, - successCode, - errorCodes - ) - const responseObject = await deleteRoutingEndpoint(req) - const user = req.kauth.grant.access_token.content.preferred_username - res - .status(responseObject.code) - .send(responseObject.body) - - logger.apiRes({ req: req, user: user, res: res, responseObject: responseObject }) - }) - } - } -] diff --git a/src/schemas/application.js b/src/schemas/application.js index f6482c54f..f8175c1d4 100644 --- a/src/schemas/application.js +++ b/src/schemas/application.js @@ -9,17 +9,14 @@ const applicationCreate = { 'minLength': 1, 'pattern': nameRegex }, - 'routes': { - 'type': 'array', - 'items': { '$ref': '/routingCreate' } - }, 'microservices': { 'type': 'array', 'items': { '$ref': '/microserviceCreate' } }, 'description': { 'type': 'string' }, 'isActivated': { 'type': 'boolean' }, - 'isSystem': { 'type': 'boolean' } + 'isSystem': { 'type': 'boolean' }, + 'natsConfig': { '$ref': '/applicationNatsConfig' } }, 'required': ['name'], 'additionalProperties': true @@ -38,13 +35,10 @@ const applicationUpdate = { 'type': 'array', 'items': { '$ref': '/microserviceCreate' } }, - 'routes': { - 'type': 'array', - 'items': { '$ref': '/routingCreate' } - }, 'description': { 'type': 'string' }, 'isActivated': { 'type': 'boolean' }, - 'isSystem': { 'type': 'boolean' } + 'isSystem': { 'type': 'boolean' }, + 'natsConfig': { '$ref': '/applicationNatsConfig' } }, 'additionalProperties': true } @@ -60,12 +54,23 @@ const applicationPatch = { }, 'description': { 'type': 'string' }, 'isActivated': { 'type': 'boolean' }, - 'isSystem': { 'type': 'boolean' } + 'isSystem': { 'type': 'boolean' }, + 'natsConfig': { '$ref': '/applicationNatsConfig' } }, 'additionalProperties': true } +const applicationNatsConfig = { + 'id': '/applicationNatsConfig', + 'type': 'object', + 'properties': { + 'natsAccess': { 'type': 'boolean' }, + 'natsRule': { 'type': 'string', 'minLength': 1, 'maxLength': 255 } + }, + 'additionalProperties': false +} + module.exports = { mainSchemas: [applicationCreate, applicationUpdate, applicationPatch], - innerSchemas: [applicationCreate] + innerSchemas: [applicationCreate, applicationNatsConfig] } diff --git a/src/schemas/iofog.js b/src/schemas/iofog.js index c2246808a..aaa05d301 100644 --- a/src/schemas/iofog.js +++ b/src/schemas/iofog.js @@ -46,6 +46,18 @@ const iofogCreate = { 'messagingPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, 'interRouterPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, 'edgeRouterPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'natsMode': { 'enum': ['none', 'leaf', 'server'], 'default': 'leaf' }, + 'natsServerPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'natsLeafPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'natsClusterPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'natsMqttPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'natsHttpPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'jsStorageSize': { 'type': 'string', 'pattern': '^[0-9]+\\s*([mM][bB]?|[gG][bB]?|[tT][bB]?)?$', 'maxLength': 32 }, + 'jsMemoryStoreSize': { 'type': 'string', 'pattern': '^[0-9]+\\s*([mM][bB]?|[gG][bB]?|[tT][bB]?)?$', 'maxLength': 32 }, + 'upstreamNatsServers': { + 'type': 'array', + 'items': { 'type': 'string', 'minLength': 1 } + }, 'host': { 'type': 'string' }, 'tags': { 'type': 'array', @@ -111,6 +123,18 @@ const iofogUpdate = { 'messagingPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, 'interRouterPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, 'edgeRouterPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'natsMode': { 'enum': ['none', 'leaf', 'server'] }, + 'natsServerPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'natsLeafPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'natsClusterPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'natsMqttPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'natsHttpPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'jsStorageSize': { 'type': 'string', 'pattern': '^[0-9]+\\s*([mM][bB]?|[gG][bB]?|[tT][bB]?)?$', 'maxLength': 32 }, + 'jsMemoryStoreSize': { 'type': 'string', 'pattern': '^[0-9]+\\s*([mM][bB]?|[gG][bB]?|[tT][bB]?)?$', 'maxLength': 32 }, + 'upstreamNatsServers': { + 'type': 'array', + 'items': { 'type': 'string', 'minLength': 1 } + }, 'host': { 'type': 'string' }, 'upstreamRouters': { 'type': 'array', diff --git a/src/schemas/microservice.js b/src/schemas/microservice.js index 230cb8473..56872ab35 100644 --- a/src/schemas/microservice.js +++ b/src/schemas/microservice.js @@ -48,9 +48,6 @@ const microserviceCreate = { 'extraHosts': { 'type': 'array', 'items': { '$ref': '/extraHosts' } }, - 'routes': { - 'type': 'array', - 'items': { 'type': 'string' } }, 'env': { 'type': 'array', 'items': { '$ref': '/env' } }, @@ -71,14 +68,7 @@ const microserviceCreate = { 'runtime': { 'type': 'string' }, 'cpuSetCpus': { 'type': 'string' }, 'memoryLimit': { 'type': 'integer' }, - 'pubTags': { - 'type': 'array', - 'items': { 'type': 'string' } - }, - 'subTags': { - 'type': 'array', - 'items': { 'type': 'string' } - }, + 'natsConfig': { '$ref': '/microserviceNatsConfig' }, 'healthCheck': { 'type': 'object', 'properties': { '$ref': '/microserviceHealthCheck' } @@ -160,14 +150,7 @@ const microserviceUpdate = { 'runtime': { 'type': 'string' }, 'cpuSetCpus': { 'type': 'string' }, 'memoryLimit': { 'type': 'integer' }, - 'pubTags': { - 'type': 'array', - 'items': { 'type': 'string' } - }, - 'subTags': { - 'type': 'array', - 'items': { 'type': 'string' } - }, + 'natsConfig': { '$ref': '/microserviceNatsConfig' }, 'healthCheck': { 'type': 'object', 'properties': { '$ref': '/microserviceHealthCheck' } @@ -292,7 +275,17 @@ const microserviceHealthCheck = { 'required': ['test'] } +const microserviceNatsConfig = { + 'id': '/microserviceNatsConfig', + 'type': 'object', + 'properties': { + 'natsAccess': { 'type': 'boolean' }, + 'natsRule': { 'type': 'string', 'minLength': 1, 'maxLength': 255 } + }, + 'additionalProperties': false +} + module.exports = { mainSchemas: [microserviceCreate, microserviceUpdate, env, ports, extraHosts, portsCreate, microserviceDelete, volumeMappings, microserviceHealthCheck], - innerSchemas: [volumeMappings, ports, env, extraHosts, microserviceCreate, microserviceHealthCheck] + innerSchemas: [volumeMappings, ports, env, extraHosts, microserviceCreate, microserviceHealthCheck, microserviceNatsConfig] } diff --git a/src/schemas/nats.js b/src/schemas/nats.js new file mode 100644 index 000000000..0c90b13d3 --- /dev/null +++ b/src/schemas/nats.js @@ -0,0 +1,168 @@ +'use strict' + +const natsHubCreate = { + 'id': '/natsHubCreate', + 'type': 'object', + 'properties': { + 'host': { 'type': 'string' }, + 'serverPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'clusterPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'leafPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'mqttPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'httpPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, + 'jsStorageSize': { 'type': 'string', 'pattern': '^[0-9]+\\s*([mM][bB]?|[gG][bB]?|[tT][bB]?)?$', 'maxLength': 32 }, + 'jsMemoryStoreSize': { 'type': 'string', 'pattern': '^[0-9]+\\s*([mM][bB]?|[gG][bB]?|[tT][bB]?)?$', 'maxLength': 32 } + }, + 'required': ['host'], + 'additionalProperties': true +} + +const natsAccountEnsure = { + 'id': '/natsAccountEnsure', + 'type': 'object', + 'properties': { + 'natsRule': { 'type': 'string', 'minLength': 1, 'maxLength': 255 } + }, + 'required': [], + 'additionalProperties': true +} + +const natsUserCreate = { + 'id': '/natsUserCreate', + 'type': 'object', + 'properties': { + 'name': { 'type': 'string' }, + 'expiresIn': { 'type': 'string', 'pattern': '^[0-9]+[hdm]$', 'maxLength': 8 }, + 'natsRule': { 'type': 'string', 'minLength': 1, 'maxLength': 255 } + }, + 'required': ['name'], + 'additionalProperties': false +} + +const natsImportSchema = { + type: 'object', + properties: { + name: { type: 'string' }, + subject: { type: 'string' }, + type: { type: 'string', enum: ['stream', 'service'] }, + account: { type: 'string' }, + token: { type: 'string' }, + to: { type: 'string' }, + local_subject: { type: 'string' }, + share: { type: 'boolean' } + }, + additionalProperties: true +} + +const natsExportSchema = { + type: 'object', + properties: { + name: { type: 'string' }, + subject: { type: 'string' }, + type: { type: 'string', enum: ['stream', 'service'] }, + description: { type: 'string' }, + info_url: { type: 'string' }, + token_req: { type: 'boolean' }, + response_type: { type: 'string', enum: ['Singleton', 'Stream', 'Chunked'] }, + account_token_position: { type: 'integer' } + }, + additionalProperties: true +} + +// Byte-size limits: integer or string with k/m/g/t suffix (e.g. -1, 1024, "1k", "100m", "1g", "1t") +const byteSizeLimitSchema = { + oneOf: [ + { type: 'integer', minimum: -1 }, + { type: 'string', pattern: '^(-1|[0-9]+[kmgtKMGT]?)$' } + ] +} + +const natsAccountRulePayload = { + 'id': '/natsAccountRulePayload', + 'type': 'object', + 'properties': { + 'name': { 'type': 'string', 'minLength': 1, 'maxLength': 255 }, + 'description': { 'type': 'string' }, + 'infoUrl': { 'type': 'string' }, + 'maxConnections': { 'type': 'integer', 'minimum': -1 }, + 'maxLeafNodeConnections': { 'type': 'integer', 'minimum': -1 }, + 'maxData': byteSizeLimitSchema, + 'maxExports': { 'type': 'integer', 'minimum': -1 }, + 'maxImports': { 'type': 'integer', 'minimum': -1 }, + 'maxMsgPayload': byteSizeLimitSchema, + 'maxSubscriptions': { 'type': 'integer', 'minimum': -1 }, + 'exportsAllowWildcards': { 'type': 'boolean' }, + 'disallowBearer': { 'type': 'boolean' }, + 'responsePermissions': { + 'type': 'object', + 'properties': { + 'maxMsgs': { 'type': 'integer', 'minimum': 0 }, + 'expires': { 'type': 'integer', 'minimum': 0 } + }, + 'additionalProperties': false + }, + 'respMax': { 'type': 'integer', 'minimum': 0 }, + 'respTtl': { 'type': 'integer', 'minimum': 0 }, + 'imports': { type: 'array', items: natsImportSchema }, + 'exports': { type: 'array', items: natsExportSchema }, + 'memStorage': byteSizeLimitSchema, + 'diskStorage': byteSizeLimitSchema, + 'streams': { 'type': 'integer', 'minimum': -1 }, + 'consumer': { 'type': 'integer', 'minimum': -1 }, + 'maxAckPending': { 'type': 'integer', 'minimum': -1 }, + 'memMaxStreamBytes': byteSizeLimitSchema, + 'diskMaxStreamBytes': byteSizeLimitSchema, + 'maxBytesRequired': { 'type': 'boolean' }, + 'tieredLimits': { 'type': 'object', 'additionalProperties': true }, + 'pubAllow': { 'type': 'array', 'items': { 'type': 'string' } }, + 'pubDeny': { 'type': 'array', 'items': { 'type': 'string' } }, + 'subAllow': { 'type': 'array', 'items': { 'type': 'string' } }, + 'subDeny': { 'type': 'array', 'items': { 'type': 'string' } } + }, + 'required': [], + 'additionalProperties': false +} + +const natsUserRulePayload = { + 'id': '/natsUserRulePayload', + 'type': 'object', + 'properties': { + 'name': { 'type': 'string', 'minLength': 1, 'maxLength': 255 }, + 'description': { 'type': 'string' }, + 'maxSubscriptions': { 'type': 'integer', 'minimum': -1 }, + 'maxPayload': byteSizeLimitSchema, + 'maxData': byteSizeLimitSchema, + 'bearerToken': { 'type': 'boolean' }, + 'proxyRequired': { 'type': 'boolean' }, + 'allowedConnectionTypes': { + 'type': 'array', + 'items': { + 'type': 'string', + 'enum': ['STANDARD', 'WEBSOCKET', 'LEAFNODE', 'LEAFNODE_WS', 'MQTT', 'MQTT_WS', 'IN_PROCESS'] + } + }, + 'src': { 'type': 'array', 'items': { 'type': 'string' } }, + 'times': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { 'start': { 'type': 'string' }, 'end': { 'type': 'string' } }, + 'additionalProperties': false + } + }, + 'timesLocation': { 'type': 'string' }, + 'respMax': { 'type': 'integer', 'minimum': 0 }, + 'respTtl': { 'type': 'integer', 'minimum': 0 }, + 'pubAllow': { 'type': 'array', 'items': { 'type': 'string' } }, + 'pubDeny': { 'type': 'array', 'items': { 'type': 'string' } }, + 'subAllow': { 'type': 'array', 'items': { 'type': 'string' } }, + 'subDeny': { 'type': 'array', 'items': { 'type': 'string' } }, + 'tags': { 'type': 'array', 'items': { 'type': 'string' } } + }, + 'required': [], + 'additionalProperties': false +} + +module.exports = { + mainSchemas: [natsHubCreate, natsAccountEnsure, natsUserCreate, natsAccountRulePayload, natsUserRulePayload] +} diff --git a/src/schemas/rbac.js b/src/schemas/rbac.js index f361279f9..e9b77efc6 100644 --- a/src/schemas/rbac.js +++ b/src/schemas/rbac.js @@ -197,7 +197,7 @@ const roleBindingUpdate = { const serviceAccountCreate = { id: '/serviceAccountCreate', type: 'object', - required: ['name', 'roleRef'], + required: ['name', 'applicationName', 'roleRef'], properties: { name: { type: 'string', @@ -205,6 +205,12 @@ const serviceAccountCreate = { maxLength: 255, pattern: nameRegex }, + applicationName: { + type: 'string', + minLength: 1, + maxLength: 255, + pattern: nameRegex + }, roleRef: { $ref: '/roleRef' } diff --git a/src/schemas/routing.js b/src/schemas/routing.js deleted file mode 100644 index 36d15db0c..000000000 --- a/src/schemas/routing.js +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ******************************************************************************* - * * Copyright (c) 2023 Datasance Teknoloji A.S. - * * - * * This program and the accompanying materials are made available under the - * * terms of the Eclipse Public License v. 2.0 which is available at - * * http://www.eclipse.org/legal/epl-2.0 - * * - * * SPDX-License-Identifier: EPL-2.0 - * ******************************************************************************* - * - */ - -const { nameRegex } = require('./utils/utils') - -const routingCreate = { - 'id': '/routingCreate', - 'type': 'object', - 'properties': { - 'name': { - 'type': 'string', - 'pattern': nameRegex - } - }, - 'oneOf': [ - { - 'properties': { - 'from': { - 'type': 'string', - 'pattern': nameRegex - }, - 'to': { - 'type': 'string', - 'pattern': nameRegex - }, - 'application': { - 'type': 'string', - 'pattern': nameRegex - } - }, - 'required': ['name', 'from', 'to'] - }, - { - 'properties': { - 'sourceMicroserviceUuid': { - 'type': 'string' - }, - 'destMicroserviceUuid': { - 'type': 'string' - } - }, - 'required': ['name', 'sourceMicroserviceUuid', 'destMicroserviceUuid'] - } - ], - 'additionalProperties': true -} - -const routingUpdate = { - 'id': '/routingUpdate', - 'type': 'object', - 'properties': { - 'name': { - 'type': 'string', - 'pattern': nameRegex - } - }, - 'oneOf': [ - { - 'properties': { - 'from': { - 'type': 'string', - 'pattern': nameRegex - }, - 'to': { - 'type': 'string', - 'pattern': nameRegex - }, - 'application': { - 'type': 'string', - 'pattern': nameRegex - } - }, - 'required': ['from', 'to', 'application'] - }, - { - 'properties': { - 'sourceMicroserviceUuid': { - 'type': 'string' - }, - 'destMicroserviceUuid': { - 'type': 'string' - } - }, - 'required': ['sourceMicroserviceUuid', 'destMicroserviceUuid'] - } - ], - 'additionalProperties': true -} - -module.exports = { - mainSchemas: [routingUpdate, routingCreate], - innerSchemas: [routingCreate] -} diff --git a/src/server.js b/src/server.js index f76a5d129..47650a0ac 100755 --- a/src/server.js +++ b/src/server.js @@ -255,9 +255,9 @@ initialize().then(() => { port: apiPort, user: {}, controllerDevMode: devMode, - keycloakURL: kcURL, + keycloakUrl: kcURL, keycloakRealm: kcRealm, - keycloakClientid: kcClient + keycloakClientId: kcClient } if (viewerURL) { ecnViewerControllerConfig.url = viewerURL diff --git a/src/services/agent-service.js b/src/services/agent-service.js index 427687a58..485bbcc18 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -41,7 +41,7 @@ const USBInfoManager = require('../data/managers/usb-info-manager') const TunnelManager = require('../data/managers/tunnel-manager') const MicroserviceManager = require('../data/managers/microservice-manager') const MicroserviceService = require('../services/microservices-service') -const RouterManager = require('../data/managers/router-manager') +const ApplicationManager = require('../data/managers/application-manager') const EdgeResourceService = require('./edge-resource-service') const constants = require('../helpers/constants') const SecretManager = require('../data/managers/secret-manager') @@ -52,7 +52,7 @@ const RbacRoleManager = require('../data/managers/rbac-role-manager') const IncomingForm = formidable.IncomingForm const CHANGE_TRACKING_DEFAULT = {} -const CHANGE_TRACKING_KEYS = ['config', 'version', 'reboot', 'deleteNode', 'microserviceList', 'microserviceConfig', 'routing', 'registries', 'tunnel', 'diagnostics', 'isImageSnapshot', 'prune', 'routerChanged', 'linkedEdgeResources', 'volumeMounts', 'execSessions', 'microserviceLogs', 'fogLogs'] +const CHANGE_TRACKING_KEYS = ['config', 'version', 'reboot', 'deleteNode', 'microserviceList', 'microserviceConfig', 'registries', 'tunnel', 'diagnostics', 'isImageSnapshot', 'prune', 'routerChanged', 'linkedEdgeResources', 'volumeMounts', 'execSessions', 'microserviceLogs', 'fogLogs'] for (const key of CHANGE_TRACKING_KEYS) { CHANGE_TRACKING_DEFAULT[key] = false } @@ -145,10 +145,6 @@ const _invalidateFogNode = async function (fog, transaction) { } const getAgentConfig = async function (fog, transaction) { - const router = fog.routerId ? await RouterManager.findOne({ id: fog.routerId }, transaction) : await fog.getRouter() - // Get local agent certificate from secrets - const localAgentSecret = await SecretManager.getSecret(`${fog.uuid}-local-agent`, transaction) - const fogData = await FogManager.findOne({ uuid: fog.uuid }, transaction) @@ -175,12 +171,7 @@ const getAgentConfig = async function (fog, transaction) { logLevel: fogData.logLevel, availableDiskThreshold: fogData.availableDiskThreshold, dockerPruningFrequency: fogData.dockerPruningFrequency, - routerHost: router.host === fogData.host ? 'localhost' : router.host, - routerPort: router.messagingPort, - timeZone: fogData.timeZone, - caCert: localAgentSecret ? localAgentSecret.data['ca.crt'] : null, - tlsCert: localAgentSecret ? localAgentSecret.data['tls.crt'] : null, - tlsKey: localAgentSecret ? localAgentSecret.data['tls.key'] : null + timeZone: fogData.timeZone } return resp } @@ -394,10 +385,13 @@ const getAgentMicroservices = async function (fog, transaction) { continue } - const routes = await MicroserviceService.getReceiverMicroservices(microservice, transaction) - const isConsumer = await MicroserviceService.isMicroserviceConsumer(microservice, transaction) const isRouter = await MicroserviceService.isMicroserviceRouter(microservice, transaction) - + const isNats = await MicroserviceService.isMicroserviceNats(microservice, transaction) + const msvcApp = await ApplicationManager.findOne({ id: microservice.applicationId }, transaction) + if (!msvcApp) { + continue + } + const application = msvcApp.name const env = microservice.env && microservice.env.map((it) => { return { key: it.key, @@ -448,6 +442,8 @@ const getAgentMicroservices = async function (fog, transaction) { const responseMicroservice = { uuid: microservice.uuid, + name: microservice.name, + application, imageId: imageId, config: microservice.config, annotations: microservice.annotations, @@ -475,9 +471,8 @@ const getAgentMicroservices = async function (fog, transaction) { cdiDevices, capAdd, capDrop, - routes, - isConsumer, isRouter, + isNats, execEnabled: microservice.execEnabled, schedule: microservice.schedule } diff --git a/src/services/application-service.js b/src/services/application-service.js index 4e0aee1ae..62553b739 100644 --- a/src/services/application-service.js +++ b/src/services/application-service.js @@ -19,15 +19,36 @@ const ChangeTrackingService = require('./change-tracking-service') const ErrorMessages = require('../helpers/error-messages') const Errors = require('../helpers/errors') const MicroserviceService = require('./microservices-service') -const RoutingService = require('./routing-service') const ApplicationManager = require('../data/managers/application-manager') const TransactionDecorator = require('../decorators/transaction-decorator') const ApplicationTemplateService = require('./application-template-service') const Validator = require('../schemas') const remove = require('lodash/remove') +const NatsAccountRuleManager = require('../data/managers/nats-account-rule-manager') +const NatsAuthService = require('./nats-auth-service') +const logger = require('../logger') const onlyUnique = (value, index, self) => self.indexOf(value) === index +function _scheduleApplicationNatsOrchestration (applicationId, reason) { + setImmediate(async () => { + try { + logger.info(`Starting background app NATS orchestration for app ${applicationId}: ${reason}`) + if (reason === 'nats-access-disabled') { + await MicroserviceService.reconcileNatsForApplication(applicationId) + await NatsAuthService.deleteAccountForApplication(applicationId) + } else { + await NatsAuthService.ensureAccountForApplication(applicationId) + await NatsAuthService.reissueAccountForApplication(applicationId) + await MicroserviceService.reconcileNatsForApplication(applicationId) + } + logger.info(`Completed background app NATS orchestration for app ${applicationId}: ${reason}`) + } catch (error) { + logger.error(`Background app NATS orchestration failed for app ${applicationId}: ${error.message}`) + } + }) +} + const createApplicationEndPoint = async function (applicationData, isCLI, transaction) { // if template is provided, use template data if (applicationData.template && applicationData.template.name) { @@ -47,22 +68,18 @@ const createApplicationEndPoint = async function (applicationData, isCLI, transa application: applicationData.name })) } - if (applicationData.routes) { - applicationData.routes = applicationData.routes.map(r => ({ - ...r, - name: r.name || `r-${r.from}-${r.to}`, - application: applicationData.name - })) - } await Validator.validate(applicationData, Validator.schemas.applicationCreate) await _checkForDuplicateName(applicationData.name, null, transaction) + const applicationNatsConfig = await _resolveApplicationNatsConfig(applicationData, transaction) const applicationToCreate = { name: applicationData.name, description: applicationData.description, isActivated: !!applicationData.isActivated, - isSystem: !!applicationData.isSystem + isSystem: !!applicationData.isSystem, + natsAccess: applicationNatsConfig.natsAccess, + natsRuleId: applicationNatsConfig.natsRuleId } const applicationDataCreate = AppHelper.deleteUndefinedFields(applicationToCreate) @@ -76,10 +93,8 @@ const createApplicationEndPoint = async function (applicationData, isCLI, transa } } - if (applicationData.routes) { - for (const routeData of applicationData.routes) { - await RoutingService.createRouting(routeData, isCLI, transaction) - } + if (application.natsAccess) { + _scheduleApplicationNatsOrchestration(application.id, 'nats-access-created') } return { @@ -107,6 +122,8 @@ const deleteApplicationEndPoint = async function (conditions, isCLI, transaction await _updateChangeTrackingsAndDeleteMicroservicesByApplicationId(conditions, true, transaction) + await NatsAuthService.deleteAccountForApplication(application.id, transaction) + await ApplicationManager.delete(where, transaction) } @@ -116,8 +133,14 @@ const deleteSystemApplicationEndPoint = async function (conditions, isCLI, trans } const where = AppHelper.deleteUndefinedFields(whereObj) + const application = await ApplicationManager.findOne({ ...conditions }, transaction) + await _updateChangeTrackingsAndDeleteMicroservicesByApplicationId(conditions, true, transaction) + if (application) { + await NatsAuthService.deleteAccountForApplication(application.id, transaction) + } + await ApplicationManager.delete(where, transaction) } @@ -130,23 +153,39 @@ const patchApplicationEndPoint = async function (applicationData, conditions, is if (!oldApplication) { throw new Errors.NotFoundError(ErrorMessages.INVALID_FLOW_ID) } + if (applicationData.name && applicationData.name !== oldApplication.name) { + throw new Errors.ValidationError('Application Resource Name is immutable') + } if (applicationData.name) { await _checkForDuplicateName(applicationData.name, oldApplication.id, transaction) } + const applicationNatsConfig = await _resolveApplicationNatsConfig(applicationData, transaction, oldApplication) const application = { name: applicationData.name || conditions.name, description: applicationData.description, isActivated: applicationData.isActivated, - isSystem: applicationData.isSystem + isSystem: applicationData.isSystem, + natsAccess: applicationNatsConfig.natsAccess, + natsRuleId: applicationNatsConfig.natsRuleId } const updateApplicationData = AppHelper.deleteUndefinedFields(application) + const natsRuleChanged = Object.prototype.hasOwnProperty.call(updateApplicationData, 'natsRuleId') && + oldApplication.natsRuleId !== updateApplicationData.natsRuleId + const natsAccessDisabled = Object.prototype.hasOwnProperty.call(updateApplicationData, 'natsAccess') && + updateApplicationData.natsAccess === false + const natsAccessEnabled = Object.prototype.hasOwnProperty.call(updateApplicationData, 'natsAccess') && + updateApplicationData.natsAccess === true && !oldApplication.natsAccess const where = isCLI ? { id: oldApplication.id } : { id: oldApplication.id } await ApplicationManager.update(where, updateApplicationData, transaction) + if (natsRuleChanged || natsAccessDisabled || natsAccessEnabled) { + const reason = natsAccessDisabled ? 'nats-access-disabled' : natsAccessEnabled ? 'nats-access-enabled' : 'nats-rule-changed' + _scheduleApplicationNatsOrchestration(oldApplication.id, reason) + } if (oldApplication.isActivated !== applicationData.isActivated) { await _updateChangeTrackingsAndDeleteMicroservicesByApplicationId(conditions, false, transaction) @@ -172,13 +211,6 @@ const updateApplicationEndPoint = async function (applicationData, name, isCLI, application: applicationData.name || name })) } - if (applicationData.routes) { - applicationData.routes = applicationData.routes.map(r => ({ - ...r, - name: r.name || `r-${r.from}-${r.to}`, - application: applicationData.name || name - })) - } await Validator.validate(applicationData, Validator.schemas.applicationUpdate) @@ -187,55 +219,70 @@ const updateApplicationEndPoint = async function (applicationData, name, isCLI, if (!oldApplication) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, name)) } + if (applicationData.name && applicationData.name !== oldApplication.name) { + throw new Errors.ValidationError('Application Resource Name is immutable') + } if (applicationData.name) { await _checkForDuplicateName(applicationData.name, oldApplication.id, transaction) } + const applicationNatsConfig = await _resolveApplicationNatsConfig(applicationData, transaction, oldApplication) const application = { name: applicationData.name || name, description: applicationData.description, isActivated: applicationData.isActivated, - isSystem: applicationData.isSystem + isSystem: applicationData.isSystem, + natsAccess: applicationNatsConfig.natsAccess, + natsRuleId: applicationNatsConfig.natsRuleId } const updateApplicationData = AppHelper.deleteUndefinedFields(application) + const natsRuleChanged = Object.prototype.hasOwnProperty.call(updateApplicationData, 'natsRuleId') && + oldApplication.natsRuleId !== updateApplicationData.natsRuleId + const natsAccessDisabled = Object.prototype.hasOwnProperty.call(updateApplicationData, 'natsAccess') && + updateApplicationData.natsAccess === false + const natsAccessEnabled = Object.prototype.hasOwnProperty.call(updateApplicationData, 'natsAccess') && + updateApplicationData.natsAccess === true && !oldApplication.natsAccess const where = isCLI ? { id: oldApplication.id } : { id: oldApplication.id } await ApplicationManager.update(where, updateApplicationData, transaction) + if (natsRuleChanged || natsAccessDisabled || natsAccessEnabled) { + const reason = natsAccessDisabled ? 'nats-access-disabled' : natsAccessEnabled ? 'nats-access-enabled' : 'nats-rule-changed' + _scheduleApplicationNatsOrchestration(oldApplication.id, reason) + } if (applicationData.microservices) { await _updateMicroservices(application.name, applicationData.microservices, isCLI, transaction) } - if (applicationData.routes) { - await _updateRoutes(application.name, applicationData.routes, isCLI, transaction) - } - if (oldApplication.isActivated !== applicationData.isActivated) { await _updateChangeTrackingsAndDeleteMicroservicesByApplicationId({ name }, false, transaction) } } -const _updateRoutes = async function (application, routes, isCLI, transaction) { - // Update routes - const updatedRoutes = [...routes] - const oldRoutes = await ApplicationManager.findApplicationRoutes({ name: application }, transaction) - if (!oldRoutes) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, application)) +async function _resolveApplicationNatsConfig (applicationData, transaction, existingApplication = null) { + if (Object.prototype.hasOwnProperty.call(applicationData, 'natsAccess')) { + throw new Errors.ValidationError('natsAccess must be provided under natsConfig.natsAccess') } - for (const oldRoute of oldRoutes) { - const removed = remove(updatedRoutes, (n) => oldRoute.name === n.name) - if (!removed.length) { - await RoutingService.deleteRouting(oldRoute.name, isCLI, transaction) - } else { - const updatedRoute = removed[0] - await RoutingService.updateRouting(application, updatedRoute.name, updatedRoute, isCLI, transaction) + if (!applicationData.natsConfig) { + return { + natsAccess: existingApplication ? existingApplication.natsAccess : undefined, + natsRuleId: existingApplication ? existingApplication.natsRuleId : undefined + } + } + const natsAccess = applicationData.natsConfig.natsAccess + let natsRuleId = existingApplication ? existingApplication.natsRuleId : undefined + if (applicationData.natsConfig.natsRule) { + const rule = await NatsAccountRuleManager.findOne({ name: applicationData.natsConfig.natsRule }, transaction) + if (!rule) { + throw new Errors.ValidationError(`NATS account rule ${applicationData.natsConfig.natsRule} does not exist`) } + natsRuleId = rule.id } - // Create missing routes - for (const route of updatedRoutes) { - await RoutingService.createRouting(route, isCLI, transaction) + if (natsAccess === false) { + natsRuleId = null } + return { natsAccess, natsRuleId } } const _updateMicroservices = async function (application, microservices, isCLI, transaction) { @@ -274,7 +321,6 @@ const _updateMicroservices = async function (application, microservices, isCLI, .filter(onlyUnique) .filter((val) => val !== null) .forEach(async (iofogUuid) => { - await ChangeTrackingService.update(iofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) await MicroserviceService.updateChangeTracking(true, iofogUuid, transaction) }) @@ -282,7 +328,6 @@ const _updateMicroservices = async function (application, microservices, isCLI, .filter(onlyUnique) .filter((val) => val !== null) .forEach(async (iofogUuid) => { - await ChangeTrackingService.update(iofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) await MicroserviceService.updateChangeTracking(true, iofogUuid, transaction) }) } @@ -323,6 +368,18 @@ const getAllApplicationsEndPoint = async function (isCLI, transaction) { } async function _buildApplicationObject (application, transaction) { + // Resolve natsRuleId to rule name for API response + let ruleName = null + if (application.natsRuleId) { + const rule = await NatsAccountRuleManager.findOne({ id: application.natsRuleId }, transaction) + ruleName = rule ? rule.name : null + } + application.natsConfig = { + natsAccess: !!application.natsAccess, + natsRule: ruleName + } + delete application.natsRuleId + if (!application.microservices) { return application } @@ -400,12 +457,14 @@ async function _updateChangeTrackingsAndDeleteMicroservicesByApplicationId (cond } } +const bypassOptions = { bypassQueue: true } + module.exports = { - createApplicationEndPoint: TransactionDecorator.generateTransaction(createApplicationEndPoint), - deleteApplicationEndPoint: TransactionDecorator.generateTransaction(deleteApplicationEndPoint), - deleteSystemApplicationEndPoint: TransactionDecorator.generateTransaction(deleteSystemApplicationEndPoint), - updateApplicationEndPoint: TransactionDecorator.generateTransaction(updateApplicationEndPoint), - patchApplicationEndPoint: TransactionDecorator.generateTransaction(patchApplicationEndPoint), + createApplicationEndPoint: TransactionDecorator.generateTransaction(createApplicationEndPoint, bypassOptions), + deleteApplicationEndPoint: TransactionDecorator.generateTransaction(deleteApplicationEndPoint, bypassOptions), + deleteSystemApplicationEndPoint: TransactionDecorator.generateTransaction(deleteSystemApplicationEndPoint, bypassOptions), + updateApplicationEndPoint: TransactionDecorator.generateTransaction(updateApplicationEndPoint, bypassOptions), + patchApplicationEndPoint: TransactionDecorator.generateTransaction(patchApplicationEndPoint, bypassOptions), getUserApplicationsEndPoint: TransactionDecorator.generateTransaction(getUserApplicationsEndPoint), getSystemApplicationsEndPoint: TransactionDecorator.generateTransaction(getSystemApplicationsEndPoint), getAllApplicationsEndPoint: TransactionDecorator.generateTransaction(getAllApplicationsEndPoint), diff --git a/src/services/catalog-service.js b/src/services/catalog-service.js index dcd36ac95..a3de0cc37 100644 --- a/src/services/catalog-service.js +++ b/src/services/catalog-service.js @@ -145,7 +145,7 @@ const deleteCatalogItemEndPoint = async function (id, isCLI, transaction) { async function getNatsCatalogItem (transaction) { return CatalogItemManager.findOne({ name: 'NATs', - category: 'UTILITIES', + category: 'SYSTEM', publisher: 'Datasance', registry_id: 1 }, transaction) diff --git a/src/services/change-tracking-service.js b/src/services/change-tracking-service.js index c8b6b8907..221b8f66f 100644 --- a/src/services/change-tracking-service.js +++ b/src/services/change-tracking-service.js @@ -23,7 +23,6 @@ const events = Object.freeze({ deleteNode: false, microserviceList: false, microserviceConfig: false, - routing: false, registries: false, tunnel: false, diagnostics: false, @@ -41,8 +40,7 @@ const events = Object.freeze({ }, microserviceFull: { microserviceConfig: true, - microserviceList: true, - routing: true + microserviceList: true }, microserviceCommon: { microserviceConfig: true, @@ -54,9 +52,6 @@ const events = Object.freeze({ microserviceConfig: { microserviceConfig: true }, - microserviceRouting: { - routing: true - }, edgeResources: { linkedEdgeResources: true }, diff --git a/src/services/event-service.js b/src/services/event-service.js index 1aad64b1b..78f5ee76c 100644 --- a/src/services/event-service.js +++ b/src/services/event-service.js @@ -37,8 +37,8 @@ function extractResourceType (path) { { pattern: /^\/api\/v3\/services/, type: 'service' }, { pattern: /^\/api\/v3\/certificates/, type: 'certificate' }, { pattern: /^\/api\/v3\/tunnels/, type: 'tunnel' }, - { pattern: /^\/api\/v3\/routes/, type: 'routing' }, { pattern: /^\/api\/v3\/router/, type: 'router' }, + { pattern: /^\/api\/v3\/nats/, type: 'nats' }, { pattern: /^\/api\/v3\/registries/, type: 'registry' }, { pattern: /^\/api\/v3\/volumeMounts/, type: 'volumeMount' }, { pattern: /^\/api\/v3\/configMaps/, type: 'configMap' }, diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index 285e4c37c..8b4fa1511 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -20,6 +20,7 @@ const FogProvisionKeyManager = require('../data/managers/iofog-provision-key-man const FogKeyService = require('./iofog-key-service') const FogVersionCommandManager = require('../data/managers/iofog-version-command-manager') const ChangeTrackingService = require('./change-tracking-service') +const NatsService = require('./nats-service') const Errors = require('../helpers/errors') const ErrorMessages = require('../helpers/error-messages') const Validator = require('../schemas') @@ -36,8 +37,16 @@ const MicroserviceExtraHostManager = require('../data/managers/microservice-extr const MicroserviceStatusManager = require('../data/managers/microservice-status-manager') const MicroserviceExecStatusManager = require('../data/managers/microservice-exec-status-manager') const RouterConnectionManager = require('../data/managers/router-connection-manager') +const NatsInstanceManager = require('../data/managers/nats-instance-manager') +const NatsConnectionManager = require('../data/managers/nats-connection-manager') const CatalogItemImageManager = require('../data/managers/catalog-item-image-manager') const RouterService = require('./router-service') +const { + ensureSystemApplication, + getLegacySystemAppName, + getSystemAppName, + getSystemMicroserviceName +} = require('../helpers/system-naming') const Constants = require('../helpers/constants') const Op = require('sequelize').Op const lget = require('lodash/get') @@ -50,7 +59,7 @@ const vaultManager = require('../vault/vault-manager') const SecretHelper = require('../helpers/secret-helper') const FogPublicKeyManager = require('../data/managers/iofog-public-key-manager') -const SITE_CA_CERT = 'pot-site-ca' +const SITE_CA_CERT = 'router-site-ca' const DEFAULT_ROUTER_LOCAL_CA = 'default-router-local-ca' const SERVICE_ANNOTATION_TAG = 'service.datasance.com/tag' @@ -210,8 +219,8 @@ async function _handleRouterCertificates (fogData, uuid, isRouterModeChanged, tr } await ensureCert( - `${uuid}-local-agent`, - `${uuid}-local-agent`, + `router-local-agent-${fogData.name}`, + `${uuid}`, localHosts, { type: 'direct', secretName: defaultRouterLocalCA }, isRouterModeChanged @@ -225,8 +234,8 @@ async function _handleRouterCertificates (fogData, uuid, isRouterModeChanged, tr logger.debug('Ensuring site-server certificate exists') const siteHosts = await getSiteCertificateHosts(fogData) await ensureCert( - `${uuid}-site-server`, - `${uuid}-site-server`, + `router-site-server-${fogData.name}`, + `${uuid}`, siteHosts, { type: 'direct', secretName: SITE_CA_CERT }, false @@ -234,26 +243,26 @@ async function _handleRouterCertificates (fogData, uuid, isRouterModeChanged, tr // Always ensure local-ca exists logger.debug('Ensuring local-ca exists') - await ensureCA(`${uuid}-local-ca`, `${uuid}-local-ca`) + await ensureCA(`router-local-ca-${fogData.name}`, `${uuid}`) // Always ensure local-server cert exists logger.debug('Ensuring local-server certificate exists') const localHosts = await getLocalCertificateHosts(fogData) await ensureCert( - `${uuid}-local-server`, - `${uuid}-local-server`, + `router-local-server-${fogData.name}`, + `${uuid}`, localHosts, - { type: 'direct', secretName: `${uuid}-local-ca` }, + { type: 'direct', secretName: `router-local-ca-${fogData.name}` }, isRouterModeChanged ) // Always ensure local-agent cert exists logger.debug('Ensuring local-agent certificate exists') await ensureCert( - `${uuid}-local-agent`, - `${uuid}-local-agent`, + `router-local-agent-${fogData.name}`, + `${uuid}`, localHosts, - { type: 'direct', secretName: `${uuid}-local-ca` }, + { type: 'direct', secretName: `router-local-ca-${fogData.name}` }, isRouterModeChanged ) @@ -266,6 +275,10 @@ async function _handleRouterCertificates (fogData, uuid, isRouterModeChanged, tr async function createFogEndPoint (fogData, isCLI, transaction) { await Validator.validate(fogData, Validator.schemas.iofogCreate) + const isKubernetes = await checkKubernetesEnvironment() + if (isKubernetes && fogData.isSystem) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_SYSTEM_FOG_KUBERNETES)) + } let createFogData = { uuid: AppHelper.generateUUID(), name: fogData.name, @@ -324,6 +337,10 @@ async function createFogEndPoint (fogData, isCLI, transaction) { throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_ROUTER_MODE, fogData.routerMode)) } + if (fogData.isSystem && fogData.natsMode !== 'server') { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_NATS_MODE, fogData.natsMode)) + } + // // TODO: handle multiple system fogs a.k.a multi-remote-controller and multi interior routers // if (fogData.isSystem && !!(await FogManager.findOne({ isSystem: true }, transaction))) { // throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.DUPLICATE_SYSTEM_FOG)) @@ -354,12 +371,29 @@ async function createFogEndPoint (fogData, isCLI, transaction) { // Return fog UUID immediately const res = { uuid: fog.uuid } + const natsConfig = { + mode: fogData.natsMode || 'leaf', + serverPort: fogData.natsServerPort, + leafPort: fogData.natsLeafPort, + clusterPort: fogData.natsClusterPort, + mqttPort: fogData.natsMqttPort, + httpPort: fogData.natsHttpPort, + jsStorageSize: fogData.jsStorageSize || NatsService.DEFAULT_JS_STORAGE_SIZE, + jsMemoryStoreSize: fogData.jsMemoryStoreSize || NatsService.DEFAULT_JS_MEMORY_STORE_SIZE + } + + if (fogData.upstreamNatsServers) { + natsConfig.upstreamNatsServers = fogData.upstreamNatsServers + } + // Start background orchestration setImmediate(() => { (async () => { + const transaction = { fakeTransaction: true } try { // --- Begin orchestration logic (previously inside runWithRetries) --- - await _handleRouterCertificates(fogData, createFogData.uuid, false, transaction) + await _handleRouterCertificates({ ...fogData, name: fog.name }, fog.uuid, false, transaction) + await NatsService.ensureNatsForFog(fog, natsConfig, transaction) if (fogData.routerMode !== 'none') { if (!fogData.host && !isCLI) { @@ -372,8 +406,12 @@ async function createFogEndPoint (fogData, isCLI, transaction) { if (serviceTags.length > 0) { const services = await _findMatchingServices(serviceTags, transaction) if (services.length > 0) { - const routerName = `router-${fog.uuid.toLowerCase()}` - const routerMicroservice = await MicroserviceManager.findOne({ name: routerName }, transaction) + const application = await ensureSystemApplication(fog, transaction) + const routerName = getSystemMicroserviceName('router') + const routerMicroservice = await MicroserviceManager.findOne({ + name: routerName, + applicationId: application.id + }, transaction) if (!routerMicroservice) { throw new Errors.NotFoundError(`Router microservice not found: ${routerName}`) } @@ -492,6 +530,21 @@ async function updateFogEndPoint (fogData, isCLI, transaction) { if (!oldFog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogData.uuid)) } + if (updateFogData.name && updateFogData.name !== oldFog.name) { + throw new Errors.ValidationError('Agent Resource Name is immutable') + } + + if (updateFogData.isSystem && updateFogData.natsMode !== 'server') { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_NATS_MODE, updateFogData.natsMode)) + } + + if (updateFogData.isSystem && updateFogData.routerMode !== 'interior') { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_ROUTER_MODE, updateFogData.routerMode)) + } + + if (updateFogData.isSystem !== undefined && updateFogData.isSystem !== oldFog.isSystem) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_SYSTEM_CHANGE)) + } // Prevent overwriting detected fogType (1 or 2) with "auto" (0) // If fogType is being set to "auto" (0) but the agent has already detected its type (1 or 2), @@ -545,13 +598,33 @@ async function updateFogEndPoint (fogData, isCLI, transaction) { // Return immediately const res = { uuid: fogData.uuid } + const natsConfig = { + mode: fogData.natsMode, + serverPort: fogData.natsServerPort, + leafPort: fogData.natsLeafPort, + clusterPort: fogData.natsClusterPort, + mqttPort: fogData.natsMqttPort, + httpPort: fogData.natsHttpPort, + upstreamNatsServers: fogData.upstreamNatsServers, + jsStorageSize: fogData.jsStorageSize, + jsMemoryStoreSize: fogData.jsMemoryStoreSize + } + // Start background orchestration setImmediate(() => { (async () => { + const transaction = { fakeTransaction: true } try { // --- Begin orchestration logic --- const fog = await FogManager.findOne({ uuid: fogData.uuid }, transaction) - await _handleRouterCertificates(fogData, fog.uuid, isRouterModeChanged, transaction) + await _handleRouterCertificates({ ...fogData, name: fog.name }, fog.uuid, isRouterModeChanged, transaction) + if (natsConfig.mode === 'none') { + await NatsService.cleanupNatsForFog(fog, transaction) + await _deleteNatsMicroserviceByFog(fogData, transaction) + await ChangeTrackingService.update(fogData.uuid, ChangeTrackingService.events.microserviceList, transaction) + } else { + await NatsService.ensureNatsForFog(fog, natsConfig, transaction) + } if (routerMode === 'none') { networkRouter = await RouterService.getNetworkRouter(fogData.networkRouter) @@ -571,8 +644,12 @@ async function updateFogEndPoint (fogData, isCLI, transaction) { if (serviceTags.length > 0) { const services = await _findMatchingServices(serviceTags, transaction) if (services.length > 0) { - const routerName = `router-${fogData.uuid.toLowerCase()}` - const routerMicroservice = await MicroserviceManager.findOne({ name: routerName }, transaction) + const application = await ensureSystemApplication(oldFog, transaction) + const routerName = getSystemMicroserviceName('router') + const routerMicroservice = await MicroserviceManager.findOne({ + name: routerName, + applicationId: application.id + }, transaction) if (!routerMicroservice) { throw new Errors.NotFoundError(`Router microservice not found: ${routerName}`) } @@ -596,8 +673,12 @@ async function updateFogEndPoint (fogData, isCLI, transaction) { }, upstreamRouters, fogData.containerEngine) // --- Service Distribution Logic --- const serviceTags = await _extractServiceTags(fogData.tags) - const routerName = `router-${fogData.uuid.toLowerCase()}` - const routerMicroservice = await MicroserviceManager.findOne({ name: routerName }, transaction) + const application = await ensureSystemApplication(oldFog, transaction) + const routerName = getSystemMicroserviceName('router') + const routerMicroservice = await MicroserviceManager.findOne({ + name: routerName, + applicationId: application.id + }, transaction) if (!routerMicroservice) { throw new Errors.NotFoundError(`Router microservice not found: ${routerName}`) } @@ -662,7 +743,9 @@ async function updateFogEndPoint (fogData, isCLI, transaction) { // Set fog node as healthy await FogManager.update({ uuid: fogData.uuid }, { warningMessage: 'HEALTHY' }, transaction) } catch (err) { - logger.error('Background orchestration failed in updateFogEndPoint: ' + err.message) + logger.error('Background orchestration failed in updateFogEndPoint: ' + err.message, { + stack: err.stack + }) await FogManager.update( { uuid: fogData.uuid }, { @@ -772,6 +855,10 @@ function _getRouterUuid (router, defaultRouter) { return (defaultRouter && (router.id === defaultRouter.id)) ? Constants.DEFAULT_ROUTER_NAME : router.iofogUuid } +function _getNatsUuid (nats, defaultHub) { + return (defaultHub && (nats.id === defaultHub.id)) ? Constants.DEFAULT_NATS_HUB_NAME : nats.iofogUuid +} + async function _getFogRouterConfig (fog, transaction) { // Get fog router config const defaultRouter = await RouterManager.findOne({ isDefault: true }, transaction) @@ -801,6 +888,33 @@ async function _getFogRouterConfig (fog, transaction) { return routerConfig } +async function _getFogNatsConfig (fog, transaction) { + const defaultHub = await NatsInstanceManager.findOne({ isHub: true }, transaction) + const nats = await fog.getNats() + const natsConfig = {} + + if (nats) { + natsConfig.natsMode = nats.isLeaf ? 'leaf' : 'server' + natsConfig.natsServerPort = nats.serverPort + natsConfig.natsLeafPort = nats.leafPort + natsConfig.natsClusterPort = nats.clusterPort + natsConfig.natsMqttPort = nats.mqttPort + natsConfig.natsHttpPort = nats.httpPort + natsConfig.jsStorageSize = nats.jsStorageSize + natsConfig.jsMemoryStoreSize = nats.jsMemoryStoreSize + + const upstreamNatsConnections = await NatsConnectionManager.findAllWithNats({ sourceNats: nats.id }, transaction) + natsConfig.upstreamNatsServers = upstreamNatsConnections + ? upstreamNatsConnections.map((connection) => _getNatsUuid(connection.dest, defaultHub)) + : [] + } else { + natsConfig.natsMode = 'none' + natsConfig.upstreamNatsServers = [] + } + + return natsConfig +} + async function _getFogEdgeResources (fog, transaction) { const resourceAttributes = [ 'name', @@ -835,13 +949,14 @@ async function _getFogVolumeMounts (fog, transaction) { async function _getFogExtraInformation (fog, transaction) { const routerConfig = await _getFogRouterConfig(fog, transaction) + const natsConfig = await _getFogNatsConfig(fog, transaction) const edgeResources = await _getFogEdgeResources(fog, transaction) const volumeMounts = await _getFogVolumeMounts(fog, transaction) // Transform to plain JS object if (fog.toJSON && typeof fog.toJSON === 'function') { fog = fog.toJSON() } - return { ...fog, tags: _mapTags(fog), ...routerConfig, edgeResources, volumeMounts } + return { ...fog, tags: _mapTags(fog), ...routerConfig, ...natsConfig, edgeResources, volumeMounts } } // Map tags to string array @@ -1086,14 +1201,19 @@ async function _processDeleteCommand (fog, transaction) { for (const microservice of microservices) { await MicroserviceService.deleteMicroserviceWithRoutesAndPortMappings(microservice, transaction) } - await ApplicationManager.delete({ name: `system-${fog.uuid.toLowerCase()}` }, transaction) + const systemAppName = getSystemAppName(fog.name) + const legacySystemAppName = getLegacySystemAppName(fog.uuid) + await ApplicationManager.delete({ name: systemAppName }, transaction) + if (legacySystemAppName !== systemAppName) { + await ApplicationManager.delete({ name: legacySystemAppName }, transaction) + } await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.deleteNode, transaction) // Delete router-related secrets if they exist const secretNames = [ - `${fog.uuid}-site-server`, - `${fog.uuid}-local-ca`, - `${fog.uuid}-local-server`, - `${fog.uuid}-local-agent` + `router-site-server-${fog.name}`, + `router-local-ca-${fog.name}`, + `router-local-server-${fog.name}`, + `router-local-agent-${fog.name}` ] for (const secretName of secretNames) { @@ -1106,6 +1226,7 @@ async function _processDeleteCommand (fog, transaction) { await SecretManager.delete({ name: secretName }, transaction) } } + await NatsService.cleanupNatsForFog(fog, transaction) const fogPublicKey = await FogPublicKeyManager.findByFogUuid(fog.uuid, transaction) if (fogPublicKey) { await FogKeyService.deletePublicKey(fog.uuid, transaction) @@ -1115,10 +1236,12 @@ async function _processDeleteCommand (fog, transaction) { async function _createHalMicroserviceForFog (fogData, oldFog, transaction) { const halItem = await CatalogService.getHalCatalogItem(transaction) + const systemMicroserviceName = getSystemMicroserviceName('hal') + const fogForName = (fogData && fogData.name) ? fogData : oldFog const halMicroserviceData = { uuid: AppHelper.generateUUID(), - name: `hal-${fogData.uuid.toLowerCase()}`, + name: systemMicroserviceName, config: '{}', catalogItemId: halItem.id, iofogUuid: fogData.uuid, @@ -1129,22 +1252,17 @@ async function _createHalMicroserviceForFog (fogData, oldFog, transaction) { configLastUpdated: Date.now() } - let application - try { - application = await ApplicationManager.findOne({ name: `system-${fogData.uuid.toLowerCase()}` }, transaction) - } catch (error) { - const systemApplicationData = { - name: `system-${fogData.uuid.toLowerCase()}`, - isActivated: true, - isSystem: true - } - await ApplicationManager.create(systemApplicationData, transaction) - application = await ApplicationManager.findOne({ name: `system-${fogData.uuid.toLowerCase()}` }, transaction) - } + const application = await ensureSystemApplication(fogForName, transaction) halMicroserviceData.applicationId = application.id - await MicroserviceManager.create(halMicroserviceData, transaction) - await MicroserviceStatusManager.create({ microserviceUuid: halMicroserviceData.uuid }, transaction) - await MicroserviceExecStatusManager.create({ microserviceUuid: halMicroserviceData.uuid }, transaction) + const existingMicroservice = await MicroserviceManager.findOne({ + name: systemMicroserviceName, + applicationId: application.id + }, transaction) + if (!existingMicroservice) { + await MicroserviceManager.create(halMicroserviceData, transaction) + await MicroserviceStatusManager.create({ microserviceUuid: halMicroserviceData.uuid }, transaction) + await MicroserviceExecStatusManager.create({ microserviceUuid: halMicroserviceData.uuid }, transaction) + } } async function _deleteHalMicroserviceByFog (fogData, transaction) { @@ -1154,17 +1272,54 @@ async function _deleteHalMicroserviceByFog (fogData, transaction) { catalogItemId: halItem.id } - const application = await ApplicationManager.findOne({ name: `system-${fogData.uuid.toLowerCase()}` }, transaction) - deleteHalMicroserviceData.applicationId = application.id - await MicroserviceManager.delete(deleteHalMicroserviceData, transaction) + const fog = await FogManager.findOne({ uuid: fogData.uuid }, transaction) + if (!fog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogData.uuid)) + } + const systemAppName = getSystemAppName(fog.name) + const legacySystemAppName = getLegacySystemAppName(fog.uuid) + let application = await ApplicationManager.findOne({ name: systemAppName }, transaction) + if (!application) { + application = await ApplicationManager.findOne({ name: legacySystemAppName }, transaction) + } + if (application) { + deleteHalMicroserviceData.applicationId = application.id + await MicroserviceManager.delete(deleteHalMicroserviceData, transaction) + } +} + +async function _deleteNatsMicroserviceByFog (fogData, transaction) { + const natsItem = await CatalogService.getNatsCatalogItem(transaction) + if (!natsItem) return + const deleteNatsMicroserviceData = { + iofogUuid: fogData.uuid, + catalogItemId: natsItem.id + } + + const fog = await FogManager.findOne({ uuid: fogData.uuid }, transaction) + if (!fog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogData.uuid)) + } + const systemAppName = getSystemAppName(fog.name) + const legacySystemAppName = getLegacySystemAppName(fog.uuid) + let application = await ApplicationManager.findOne({ name: systemAppName }, transaction) + if (!application) { + application = await ApplicationManager.findOne({ name: legacySystemAppName }, transaction) + } + if (application) { + deleteNatsMicroserviceData.applicationId = application.id + await MicroserviceManager.delete(deleteNatsMicroserviceData, transaction) + } } async function _createBluetoothMicroserviceForFog (fogData, oldFog, transaction) { const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction) + const systemMicroserviceName = getSystemMicroserviceName('ble') + const fogForName = (fogData && fogData.name) ? fogData : oldFog const bluetoothMicroserviceData = { uuid: AppHelper.generateUUID(), - name: `ble-${fogData.uuid.toLowerCase()}`, + name: systemMicroserviceName, config: '{}', catalogItemId: bluetoothItem.id, iofogUuid: fogData.uuid, @@ -1175,22 +1330,17 @@ async function _createBluetoothMicroserviceForFog (fogData, oldFog, transaction) configLastUpdated: Date.now() } - let application - try { - application = await ApplicationManager.findOne({ name: `system-${fogData.uuid.toLowerCase()}` }, transaction) - } catch (error) { - const systemApplicationData = { - name: `system-${fogData.uuid.toLowerCase()}`, - isActivated: true, - isSystem: true - } - await ApplicationManager.create(systemApplicationData, transaction) - application = await ApplicationManager.findOne({ name: `system-${fogData.uuid.toLowerCase()}` }, transaction) - } + const application = await ensureSystemApplication(fogForName, transaction) bluetoothMicroserviceData.applicationId = application.id - await MicroserviceManager.create(bluetoothMicroserviceData, transaction) - await MicroserviceStatusManager.create({ microserviceUuid: bluetoothMicroserviceData.uuid }, transaction) - await MicroserviceExecStatusManager.create({ microserviceUuid: bluetoothMicroserviceData.uuid }, transaction) + const existingMicroservice = await MicroserviceManager.findOne({ + name: systemMicroserviceName, + applicationId: application.id + }, transaction) + if (!existingMicroservice) { + await MicroserviceManager.create(bluetoothMicroserviceData, transaction) + await MicroserviceStatusManager.create({ microserviceUuid: bluetoothMicroserviceData.uuid }, transaction) + await MicroserviceExecStatusManager.create({ microserviceUuid: bluetoothMicroserviceData.uuid }, transaction) + } } async function _deleteBluetoothMicroserviceByFog (fogData, transaction) { @@ -1199,10 +1349,20 @@ async function _deleteBluetoothMicroserviceByFog (fogData, transaction) { iofogUuid: fogData.uuid, catalogItemId: bluetoothItem.id } - const application = await ApplicationManager.findOne({ name: `system-${fogData.uuid.toLowerCase()}` }, transaction) - deleteBluetoothMicroserviceData.applicationId = application.id - - await MicroserviceManager.delete(deleteBluetoothMicroserviceData, transaction) + const fog = await FogManager.findOne({ uuid: fogData.uuid }, transaction) + if (!fog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogData.uuid)) + } + const systemAppName = getSystemAppName(fog.name) + const legacySystemAppName = getLegacySystemAppName(fog.uuid) + let application = await ApplicationManager.findOne({ name: systemAppName }, transaction) + if (!application) { + application = await ApplicationManager.findOne({ name: legacySystemAppName }, transaction) + } + if (application) { + deleteBluetoothMicroserviceData.applicationId = application.id + await MicroserviceManager.delete(deleteBluetoothMicroserviceData, transaction) + } } async function setFogPruneCommandEndPoint (fogData, isCLI, transaction) { @@ -1224,10 +1384,11 @@ async function enableNodeExecEndPoint (execData, isCLI, transaction) { if (!fog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, execData.uuid)) } + const systemMicroserviceName = getSystemMicroserviceName('debug') const debugMicroserviceData = { uuid: AppHelper.generateUUID(), - name: `debug-${execData.uuid.toLowerCase()}`, + name: systemMicroserviceName, config: '{}', iofogUuid: execData.uuid, ipcMode: 'host', @@ -1251,23 +1412,15 @@ async function enableNodeExecEndPoint (execData, isCLI, transaction) { debugMicroserviceData.catalogItemId = debugCatalog.id } - let application - try { - application = await ApplicationManager.findOne({ name: `system-${execData.uuid.toLowerCase()}` }, transaction) - } catch (error) { - const systemApplicationData = { - name: `system-${execData.uuid.toLowerCase()}`, - isActivated: true, - isSystem: true - } - await ApplicationManager.create(systemApplicationData, transaction) - application = await ApplicationManager.findOne({ name: `system-${execData.uuid.toLowerCase()}` }, transaction) - } + const application = await ensureSystemApplication(fog, transaction) debugMicroserviceData.applicationId = application.id let microservice // Check if microservice already exists - const existingMicroservice = await MicroserviceManager.findOneWithCategory({ name: `debug-${execData.uuid.toLowerCase()}` }, transaction) + const existingMicroservice = await MicroserviceManager.findOneWithCategory({ + name: systemMicroserviceName, + applicationId: application.id + }, transaction) if (existingMicroservice) { // Update existing microservice @@ -1340,7 +1493,11 @@ async function disableNodeExecEndPoint (fogData, isCLI, transaction) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogData.uuid)) } - const microservice = await MicroserviceManager.findOne({ name: `debug-${fogData.uuid.toLowerCase()}` }, transaction) + const application = await ensureSystemApplication(fog, transaction) + const microservice = await MicroserviceManager.findOne({ + name: getSystemMicroserviceName('debug'), + applicationId: application.id + }, transaction) if (!microservice) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, fogData.uuid)) } @@ -1418,8 +1575,16 @@ function _buildTcpListenerForFog (service, fogNodeUuid) { * @returns {Promise} Router microservice configuration */ async function _getRouterMicroserviceConfig (fogNodeUuid, transaction) { - const routerName = `router-${fogNodeUuid.toLowerCase()}` - const routerMicroservice = await MicroserviceManager.findOne({ name: routerName }, transaction) + const fog = await FogManager.findOne({ uuid: fogNodeUuid }, transaction) + if (!fog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogNodeUuid)) + } + const application = await ensureSystemApplication(fog, transaction) + const routerName = getSystemMicroserviceName('router') + const routerMicroservice = await MicroserviceManager.findOne({ + name: routerName, + applicationId: application.id + }, transaction) if (!routerMicroservice) { throw new Errors.NotFoundError(`Router microservice not found: ${routerName}`) } @@ -1500,10 +1665,12 @@ async function _updateImages (images, microserviceUuid, transaction) { return _createMicroserviceImages({ uuid: microserviceUuid }, images, transaction) } +const bypassOptions = { bypassQueue: true } + module.exports = { - createFogEndPoint: TransactionDecorator.generateTransaction(createFogEndPoint), - updateFogEndPoint: TransactionDecorator.generateTransaction(updateFogEndPoint), - deleteFogEndPoint: TransactionDecorator.generateTransaction(deleteFogEndPoint), + createFogEndPoint: TransactionDecorator.generateTransaction(createFogEndPoint, bypassOptions), + updateFogEndPoint: TransactionDecorator.generateTransaction(updateFogEndPoint, bypassOptions), + deleteFogEndPoint: TransactionDecorator.generateTransaction(deleteFogEndPoint, bypassOptions), getFogEndPoint: TransactionDecorator.generateTransaction(getFogEndPoint), getFogListEndPoint: TransactionDecorator.generateTransaction(getFogListEndPoint), generateProvisioningKeyEndPoint: TransactionDecorator.generateTransaction(generateProvisioningKeyEndPoint), diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index a8d6b2850..e29de2ef2 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -31,11 +31,10 @@ const ChangeTrackingService = require('./change-tracking-service') const AppHelper = require('../helpers/app-helper') const Errors = require('../helpers/errors') const ErrorMessages = require('../helpers/error-messages') +const { slugifyName } = require('../helpers/system-naming') const Validator = require('../schemas/index') const ApplicationManager = require('../data/managers/application-manager') const CatalogService = require('../services/catalog-service') -const RoutingManager = require('../data/managers/routing-manager') -const RoutingService = require('../services/routing-service') const ServiceManager = require('../data/managers/service-manager') const ServiceServices = require('./services-service') const ConfigMapManager = require('../data/managers/config-map-manager') @@ -43,6 +42,9 @@ const SecretManager = require('../data/managers/secret-manager') const VolumeMountService = require('./volume-mount-service') const RbacServiceAccountManager = require('../data/managers/rbac-service-account-manager') const RbacRoleManager = require('../data/managers/rbac-role-manager') +const RbacCacheVersionManager = require('../data/managers/rbac-cache-version-manager') +const NatsAuthService = require('./nats-auth-service') +const NatsUserRuleManager = require('../data/managers/nats-user-rule-manager') const Op = require('sequelize').Op const FogManager = require('../data/managers/iofog-manager') @@ -50,92 +52,166 @@ const MicroserviceExtraHostManager = require('../data/managers/microservice-extr const { VOLUME_MAPPING_DEFAULT } = require('../helpers/constants') const constants = require('../helpers/constants') const isEqual = require('lodash/isEqual') -const TagsManager = require('../data/managers/tags-manager') const logger = require('../logger') -async function _setPubTags (microserviceModel, tagsArray, transaction) { - if (tagsArray) { - let tags = [] - for (const tag of tagsArray) { - let tagModel = await TagsManager.findOne({ value: tag }, transaction) - if (!tagModel) { - tagModel = await TagsManager.create({ value: tag }, transaction) - } - tags.push(tagModel) - } - await microserviceModel.setPubTags(tags) - } -} - -async function _setSubTags (microserviceModel, tagsArray, transaction) { - if (tagsArray) { - let tags = [] - for (const tag of tagsArray) { - let tagModel = await TagsManager.findOne({ value: tag }, transaction) - if (!tagModel) { - tagModel = await TagsManager.create({ value: tag }, transaction) - } - tags.push(tagModel) - } - await microserviceModel.setSubTags(tags) - } -} - /** * Create or update service account for a microservice + * @param {string} microserviceUuid - UUID of the microservice * @param {string} microserviceName - Name of the microservice (used as service account name) * @param {string|null|undefined} roleRefName - Name of the role to reference (defaults to 'microservice' if not provided) * @param {Object} transaction - Database transaction * @returns {Object} Service account object */ -async function _createOrUpdateServiceAccountForMicroservice (microserviceName, roleRefName, transaction) { - // Default to 'microservice' role if not provided, null, undefined, or empty string +async function _createOrUpdateServiceAccountForMicroservice (microserviceUuid, microserviceName, roleRefName, transaction) { const roleName = (roleRefName && typeof roleRefName === 'string' && roleRefName.trim() !== '') ? roleRefName : 'microservice' - // Validate role exists (check system roles first, then database) const role = await RbacRoleManager.getRoleWithRules(roleName, transaction) if (!role) { throw new Errors.ValidationError(`Referenced role '${roleName}' does not exist`) } - // Prepare roleRef object const roleRef = { kind: 'Role', name: roleName } - // Check if service account already exists - const existingServiceAccount = await RbacServiceAccountManager.findOne({ name: microserviceName }, transaction) + const existingServiceAccount = await RbacServiceAccountManager.findOneByMicroserviceUuid(microserviceUuid, transaction) if (existingServiceAccount) { - // Update existing service account - const updated = await RbacServiceAccountManager.updateServiceAccount(microserviceName, { roleRef }, transaction) - return updated - } else { - // Create new service account - const created = await RbacServiceAccountManager.createServiceAccount({ - name: microserviceName, - roleRef + await RbacServiceAccountManager.update({ id: existingServiceAccount.id }, { roleRef, name: microserviceName }, transaction) + await RbacCacheVersionManager.incrementVersion(transaction) + return RbacServiceAccountManager.findOne({ id: existingServiceAccount.id }, transaction) + } + + const microservice = await MicroserviceManager.findOne({ uuid: microserviceUuid }, transaction) + if (!microservice || microservice.applicationId == null) { + throw new Errors.ValidationError('Microservice or application not found for service account creation') + } + return RbacServiceAccountManager.createServiceAccount({ + microserviceUuid, + applicationId: microservice.applicationId, + name: microserviceName, + roleRef + }, transaction) +} + +async function _ensureNatsCredsForMicroservice (microservice, transaction) { + if (!microservice.iofogUuid) { + return + } + + const { account, user } = await NatsAuthService.ensureUserForMicroservice(microservice, transaction) + const credsSecretName = user.credsSecretName + + try { + await VolumeMountService.getVolumeMountEndpoint(credsSecretName, transaction) + } catch (err) { + if (err.name !== 'NotFoundError') { + throw err + } + await VolumeMountService.createVolumeMountEndpoint({ name: credsSecretName, secretName: credsSecretName }, transaction) + } + + const linkedFogUuids = await VolumeMountService.findVolumeMountedFogNodes(credsSecretName, transaction) + if (!linkedFogUuids.includes(microservice.iofogUuid)) { + await VolumeMountService.linkVolumeMountEndpoint(credsSecretName, [microservice.iofogUuid], transaction) + } + const application = microservice.application || await ApplicationManager.findOne({ id: microservice.applicationId }, transaction) + const accountName = application ? application.name : account.name + const credsPath = `${slugifyName(accountName, 64)}/${slugifyName(microservice.name, 64)}.creds` + const containerDest = `/etc/nats/creds` + const existingMapping = await VolumeMappingManager.findOne({ + microserviceUuid: microservice.uuid, + hostDestination: credsSecretName, + containerDestination: containerDest, + type: 'volumeMount' + }, transaction) + if (!existingMapping) { + await VolumeMappingManager.create({ + microserviceUuid: microservice.uuid, + hostDestination: credsSecretName, + containerDestination: containerDest, + accessMode: 'ro', + type: 'volumeMount' }, transaction) - return created } + + const existingCredsPathEnv = await MicroserviceEnvManager.findOne( + { microserviceUuid: microservice.uuid, key: 'NATS_CREDS_PATH' }, + transaction + ) + if (existingCredsPathEnv) { + await MicroserviceEnvManager.update( + { id: existingCredsPathEnv.id }, + { value: `${containerDest}/${credsPath}` }, + transaction + ) + } else { + await MicroserviceEnvManager.create( + { microserviceUuid: microservice.uuid, key: 'NATS_CREDS_PATH', value: `${containerDest}/${credsPath}` }, + transaction + ) + } + + await MicroserviceManager.update( + { uuid: microservice.uuid }, + { + natsAccess: true, + natsAccountId: account.id, + natsUserId: user.id, + natsCredsSecretName: credsSecretName + }, + transaction + ) +} + +async function _detachNatsCredsForMicroservice (microservice, transaction) { + if (!microservice.natsCredsSecretName) { + return + } + + await MicroserviceEnvManager.delete( + { microserviceUuid: microservice.uuid, key: 'NATS_CREDS_PATH' }, + transaction + ) + + await VolumeMappingManager.delete({ + microserviceUuid: microservice.uuid, + hostDestination: microservice.natsCredsSecretName, + type: 'volumeMount' + }, transaction) + + try { + await VolumeMountService.unlinkVolumeMountEndpoint(microservice.natsCredsSecretName, [microservice.iofogUuid], transaction) + } catch (err) { + // Ignore missing volume mount or link errors + } + + await MicroserviceManager.update( + { uuid: microservice.uuid }, + { + natsAccess: false, + natsAccountId: null, + natsUserId: null, + natsCredsSecretName: null + }, + transaction + ) } /** * Delete service account for a microservice - * @param {string} microserviceName - Name of the microservice (used as service account name) + * @param {string} microserviceUuid - UUID of the microservice * @param {Object} transaction - Database transaction */ -async function _deleteServiceAccountForMicroservice (microserviceName, transaction) { +async function _deleteServiceAccountForMicroservice (microserviceUuid, transaction) { try { - await RbacServiceAccountManager.deleteServiceAccount(microserviceName, transaction) + await RbacServiceAccountManager.deleteByMicroserviceUuid(microserviceUuid, transaction) } catch (error) { - // Gracefully handle not found errors (service account might not exist) if (error.name !== 'NotFoundError') { throw error } - // Log but don't fail if service account doesn't exist - logger.warn(`Service account '${microserviceName}' not found during microservice deletion, continuing...`) + logger.warn(`Service account for microservice ${microserviceUuid} not found during deletion, continuing...`) } } @@ -352,11 +428,38 @@ async function _findFog (microserviceData, isCLI, transaction) { return FogManager.findOne(fogConditions, transaction) } +async function _normalizeMicroserviceNatsConfig (microserviceData, transaction, existingMicroservice = null) { + if (Object.prototype.hasOwnProperty.call(microserviceData, 'natsAccess')) { + throw new Errors.ValidationError('natsAccess must be provided under natsConfig.natsAccess') + } + const natsConfig = microserviceData.natsConfig || {} + if (natsConfig.natsAccess !== undefined) { + microserviceData.natsAccess = natsConfig.natsAccess + } else if (existingMicroservice) { + microserviceData.natsAccess = existingMicroservice.natsAccess + } + + if (natsConfig.natsRule) { + const rule = await NatsUserRuleManager.findOne({ name: natsConfig.natsRule }, transaction) + if (!rule) { + throw new Errors.ValidationError(`NATS user rule ${natsConfig.natsRule} does not exist`) + } + microserviceData.natsRuleId = rule.id + } else if (existingMicroservice && !Object.prototype.hasOwnProperty.call(natsConfig, 'natsRule')) { + microserviceData.natsRuleId = existingMicroservice.natsRuleId + } + + if (microserviceData.natsAccess === false) { + microserviceData.natsRuleId = null + } +} + async function createMicroserviceEndPoint (microserviceData, isCLI, transaction) { // API Retro compatibility if (!microserviceData.application) { microserviceData.application = microserviceData.flowId } + await _normalizeMicroserviceNatsConfig(microserviceData, transaction) await Validator.validate(microserviceData, Validator.schemas.microserviceCreate) // find fog @@ -464,37 +567,6 @@ async function createMicroserviceEndPoint (microserviceData, isCLI, transaction) await _createVolumeMappings(microservice, microserviceData.volumeMappings, transaction) } - if (microserviceData.pubTags) { - await _setPubTags(microservice, microserviceData.pubTags, transaction) - } - - if (microserviceData.subTags) { - await _setSubTags(microservice, microserviceData.subTags, transaction) - const fogsNeedUpdate = new Set() - for (const tag of microserviceData.subTags) { - try { - const where = { - delete: false, - '$pubTags.value$': tag - } - // Get fog nodes with microservices for the given pubTag - const response = await MicroserviceManager.findAllExcludeFields(where, transaction, { attributes: ['iofogUuid'] }) - if (response.length > 0) { - response.forEach(ms => ms.iofogUuid && fogsNeedUpdate.add(ms.iofogUuid)) - } - } catch (error) { - logger.error(`Checking fog nodes list for pubTag "${tag.value}":`, error.message) - } - } - for (const fog of fogsNeedUpdate) { - try { - await ChangeTrackingService.update(fog, ChangeTrackingService.events.microserviceFull, transaction) - } catch (error) { - logger.error(`Updating change tracking for fog "${fog.value}":`, error.message) - } - } - } - if (microserviceData.iofogUuid) { await _updateChangeTracking(false, microserviceData.iofogUuid, transaction) } @@ -510,18 +582,20 @@ async function createMicroserviceEndPoint (microserviceData, isCLI, transaction) roleRefName = microserviceData.serviceAccount.roleRef.name } try { - const serviceAccount = await _createOrUpdateServiceAccountForMicroservice(microservice.name, roleRefName, transaction) - // Update microservice with service account ID - await MicroserviceManager.update( - { uuid: microservice.uuid }, - { serviceAccountId: serviceAccount.id }, - transaction - ) + await _createOrUpdateServiceAccountForMicroservice(microservice.uuid, microservice.name, roleRefName, transaction) } catch (error) { logger.error(`Failed to create service account for microservice ${microservice.name}:`, error.message) throw error } + if (microserviceData.natsAccess) { + const app = await ApplicationManager.findOne({ id: microservice.applicationId }, transaction) + if (!app || !app.natsAccess) { + throw new Errors.ValidationError('Microservice natsAccess requires application natsAccess=true') + } + await _ensureNatsCredsForMicroservice(microservice, transaction) + } + const res = { uuid: microservice.uuid, name: microservice.name @@ -703,6 +777,7 @@ async function _updateRelatedExtraHosts (updatedMicroservice, transaction) { async function updateSystemMicroserviceEndPoint (microserviceUuid, microserviceData, isCLI, transaction, changeTrackingEnabled = true) { await Validator.validate(microserviceData, Validator.schemas.microserviceUpdate) + _validateMicroserviceSchedule(microserviceData.schedule, true) let needStatusReset = false const query = isCLI ? { @@ -762,6 +837,9 @@ async function updateSystemMicroserviceEndPoint (microserviceUuid, microserviceD if (!microservice) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) } + if (microserviceDataUpdate.name && microserviceDataUpdate.name !== microservice.name) { + throw new Errors.ValidationError('Microservice Resource Name is immutable') + } if (microserviceDataUpdate.registryId) { const registry = await RegistryManager.findOne({ id: microserviceDataUpdate.registryId }, transaction) if (!registry) { @@ -873,7 +951,7 @@ async function updateSystemMicroserviceEndPoint (microserviceUuid, microserviceD microserviceDataUpdate.runtime || microserviceDataUpdate.volumeMappings || microserviceDataUpdate.ports || - microserviceDataUpdate.schedule || + (microserviceDataUpdate.schedule !== undefined && microserviceDataUpdate.schedule !== microservice.schedule) || extraHosts ) const updatedMicroservice = await MicroserviceManager.updateAndFind(query, microserviceDataUpdate, transaction) @@ -955,21 +1033,13 @@ async function updateSystemMicroserviceEndPoint (microserviceUuid, microserviceD // If serviceAccount field is not provided, roleRefName stays null and will default to 'microservice' role try { - const serviceAccount = await _createOrUpdateServiceAccountForMicroservice(microserviceName, roleRefName, transaction) - // Update microservice with service account ID - await MicroserviceManager.update( - { uuid: updatedMicroservice.uuid }, - { serviceAccountId: serviceAccount.id }, - transaction - ) + await _createOrUpdateServiceAccountForMicroservice(updatedMicroservice.uuid, microserviceName, roleRefName, transaction) } catch (error) { logger.error(`Failed to update service account for microservice ${microserviceName}:`, error.message) throw error } if (changeTrackingEnabled) { - await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) - await ChangeTrackingService.update(updatedMicroservice.iofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) await _updateChangeTracking(true, microservice.iofogUuid, transaction) await _updateChangeTracking(true, updatedMicroservice.iofogUuid, transaction) } else { @@ -981,6 +1051,8 @@ async function updateSystemMicroserviceEndPoint (microserviceUuid, microserviceD } async function updateMicroserviceEndPoint (microserviceUuid, microserviceData, isCLI, transaction, changeTrackingEnabled = true) { + const current = await MicroserviceManager.findOne({ uuid: microserviceUuid }, transaction) + await _normalizeMicroserviceNatsConfig(microserviceData, transaction, current) await Validator.validate(microserviceData, Validator.schemas.microserviceUpdate) let needStatusReset = false const query = isCLI @@ -1027,7 +1099,9 @@ async function updateMicroserviceEndPoint (microserviceUuid, microserviceData, i env: microserviceData.env, cmd: microserviceData.cmd, ports: microserviceData.ports, - healthCheck: microserviceData.healthCheck + healthCheck: microserviceData.healthCheck, + natsAccess: microserviceData.natsAccess, + natsRuleId: microserviceData.natsRuleId } const microserviceDataUpdate = AppHelper.deleteUndefinedFields(microserviceToUpdate) @@ -1041,6 +1115,13 @@ async function updateMicroserviceEndPoint (microserviceUuid, microserviceData, i if (!microservice) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) } + const application = await ApplicationManager.findOne({ id: microservice.applicationId }, transaction) + if (microserviceDataUpdate.natsAccess === true && (!application || !application.natsAccess)) { + throw new Errors.ValidationError('Microservice natsAccess requires application natsAccess=true') + } + if (microserviceDataUpdate.name && microserviceDataUpdate.name !== microservice.name) { + throw new Errors.ValidationError('Microservice Resource Name is immutable') + } if (microserviceDataUpdate.registryId) { const registry = await RegistryManager.findOne({ id: microserviceDataUpdate.registryId }, transaction) if (!registry) { @@ -1080,6 +1161,8 @@ async function updateMicroserviceEndPoint (microserviceUuid, microserviceData, i throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.SYSTEM_MICROSERVICE_UPDATE, microserviceUuid)) } + _validateMicroserviceSchedule(microserviceDataUpdate.schedule, false) + // Validate images vs catalog item const iofogUuid = microserviceDataUpdate.iofogUuid || microservice.iofogUuid @@ -1156,7 +1239,7 @@ async function updateMicroserviceEndPoint (microserviceUuid, microserviceData, i microserviceDataUpdate.runtime || microserviceDataUpdate.volumeMappings || microserviceDataUpdate.ports || - microserviceDataUpdate.schedule || + (microserviceDataUpdate.schedule !== undefined && microserviceDataUpdate.schedule !== microservice.schedule) || extraHosts ) const updatedMicroservice = await MicroserviceManager.updateAndFind(query, microserviceDataUpdate, transaction) @@ -1211,37 +1294,6 @@ async function updateMicroserviceEndPoint (microserviceUuid, microserviceData, i } // Update tags - if (microserviceData.pubTags) { - await _setPubTags(microservice, microserviceData.pubTags, transaction) - } - - if (microserviceData.subTags) { - await _setSubTags(microservice, microserviceData.subTags, transaction) - const fogsNeedUpdate = new Set() - for (const tag of microserviceData.subTags) { - try { - const where = { - delete: false, - '$pubTags.value$': tag - } - // Get fog nodes with microservices for the given pubTag - const response = await MicroserviceManager.findAllExcludeFields(where, transaction, { attributes: ['iofogUuid'] }) - if (response.length > 0) { - response.forEach(ms => ms.iofogUuid && fogsNeedUpdate.add(ms.iofogUuid)) - } - } catch (error) { - logger.error(`Checking fog nodes list for pubTag "${tag.value}":`, error.message) - } - } - for (const fog of fogsNeedUpdate) { - try { - await ChangeTrackingService.update(fog, ChangeTrackingService.events.microserviceFull, transaction) - } catch (error) { - logger.error(`Updating change tracking for fog "${fog.value}":`, error.message) - } - } - } - if (needStatusReset) { const microserviceStatus = { status: MicroserviceStates.QUEUED, @@ -1275,21 +1327,28 @@ async function updateMicroserviceEndPoint (microserviceUuid, microserviceData, i // If serviceAccount field is not provided, roleRefName stays null and will default to 'microservice' role try { - const serviceAccount = await _createOrUpdateServiceAccountForMicroservice(microserviceName, roleRefName, transaction) - // Update microservice with service account ID - await MicroserviceManager.update( - { uuid: updatedMicroservice.uuid }, - { serviceAccountId: serviceAccount.id }, - transaction - ) + await _createOrUpdateServiceAccountForMicroservice(updatedMicroservice.uuid, microserviceName, roleRefName, transaction) } catch (error) { logger.error(`Failed to update service account for system microservice ${microserviceName}:`, error.message) throw error } + const shouldEnableNats = microserviceData.natsAccess === true + const shouldDisableNats = microserviceData.natsAccess === false && microservice.natsAccess + const natsRuleChanged = Object.prototype.hasOwnProperty.call(microserviceData, 'natsRuleId') && + microserviceData.natsRuleId !== microservice.natsRuleId + + if (shouldEnableNats) { + if (natsRuleChanged) { + await NatsAuthService.reissueUserForMicroservice(updatedMicroservice.uuid, transaction) + } + await _ensureNatsCredsForMicroservice(updatedMicroservice, transaction) + } else if (shouldDisableNats) { + await _detachNatsCredsForMicroservice(microservice, transaction) + await NatsAuthService.revokeMicroserviceUser(microservice.uuid, transaction) + } + if (changeTrackingEnabled) { - await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) - await ChangeTrackingService.update(updatedMicroservice.iofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) await _updateChangeTracking(true, microservice.iofogUuid, transaction) await _updateChangeTracking(true, updatedMicroservice.iofogUuid, transaction) } else { @@ -1529,7 +1588,7 @@ async function deleteMicroserviceEndPoint (microserviceUuid, microserviceData, i } // Delete service account for microservice - await _deleteServiceAccountForMicroservice(microservice.name, transaction) + await _deleteServiceAccountForMicroservice(microservice.uuid, transaction) await deleteMicroserviceWithRoutesAndPortMappings(microservice, transaction) await _updateChangeTracking(false, microservice.iofogUuid, transaction) @@ -1546,39 +1605,6 @@ async function deleteNotRunningMicroservices (fog, transaction) { .forEach(async (microservice) => { await deleteMicroserviceWithRoutesAndPortMappings(microservice, transaction) }) } -async function createRouteEndPoint (sourceMicroserviceUuid, destMicroserviceUuid, isCLI, transaction) { - // Print deprecated warning - const sourceMsvc = await MicroserviceManager.findMicroserviceOnGet({ uuid: sourceMicroserviceUuid }, transaction) - if (!sourceMsvc) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_SOURCE_MICROSERVICE_UUID, sourceMicroserviceUuid)) - } - const destMsvc = await MicroserviceManager.findMicroserviceOnGet({ uuid: destMicroserviceUuid }, transaction) - if (!destMsvc) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_SOURCE_MICROSERVICE_UUID, destMsvc)) - } - - const application = await ApplicationManager.findOne({ id: sourceMsvc.applicationId }, transaction) - if (!application) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, sourceMsvc.applicationId)) - } - - return RoutingService.createRouting({ application: application.name, from: sourceMsvc.name, to: destMsvc.name, name: `r-${sourceMsvc.name}-${destMsvc.name}` }, isCLI, transaction) -} - -async function deleteRouteEndPoint (sourceMicroserviceUuid, destMicroserviceUuid, isCLI, transaction) { - // Print deprecated warning - - const route = await RoutingManager.findOnePopulated({ - sourceMicroserviceUuid: sourceMicroserviceUuid, - destMicroserviceUuid: destMicroserviceUuid - }, transaction) - if (!route) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.ROUTE_NOT_FOUND)) - } - - return RoutingService.deleteRouting(route.application.name, route.name, isCLI, transaction) -} - async function createPortMappingEndPoint (microserviceUuid, portMappingData, isCLI, transaction) { await Validator.validate(portMappingData, Validator.schemas.portsCreate) await _validateMicroserviceOnGet(microserviceUuid, transaction) @@ -1756,77 +1782,20 @@ async function listPortMappingsEndPoint (microserviceUuid, isCLI, transaction) { return MicroservicePortService.listPortMappings(microserviceUuid, isCLI, transaction) } -async function getReceiverMicroservices (microservice, transaction) { - // 1. Get existing routes (app-level routing) - const routes = await RoutingManager.findAll({ sourceMicroserviceUuid: microservice.uuid }, transaction) - - let receiverMicroservices = routes.map(route => route.destMicroserviceUuid) - - // 2. Check if the microservice has pubTags and fetch microservices associated with those tags - if (microservice.pubTags) { - for (const tag of microservice.pubTags) { - try { - const where = { - delete: false, - '$subTags.value$': tag.value - } - // Get microservices for the given pubTag - const response = await MicroserviceManager.findAllExcludeFields(where, transaction, { attributes: ['uuid'] }) - if (response.length > 0) { - const tagMicroservices = response.map(ms => ms.uuid) - // Add the microservices' UUIDs to the receiver list (filtering duplicates and removing the current microservice's UUID) - receiverMicroservices = [ - ...new Set([ - ...receiverMicroservices, - ...tagMicroservices.filter(uuid => uuid !== microservice.uuid) // Remove the current microservice's UUID - ]) - ] - } - } catch (error) { - logger.error(`Checking microservices for pubTag "${tag.value}":`, error.message) - } - } - } - return receiverMicroservices -} - -async function isMicroserviceConsumer (microservice, transaction) { - // Step 1: App-level routing check - const routes = await RoutingManager.findAll({ destMicroserviceUuid: microservice.uuid }, transaction) - - if (routes.length > 0) { - return true - } - - // Step 2: Subtag-based routing check - if (microservice.subTags) { - for (const tag of microservice.subTags) { - try { - const where = { - delete: false, - '$pubTags.value$': tag.value - } - const result = await MicroserviceManager.findAllExcludeFields(where, transaction, { attributes: ['uuid'] }) - - if (result.length > 0) { - return true - } - } catch (error) { - logger.error(`Checking microservices for subTag "${tag.value}":`, error.message) - } - } +async function isMicroserviceRouter (microservice, transaction) { + if (microservice.name !== 'router') { + return false } - return false + const app = await ApplicationManager.findOne({ id: microservice.applicationId }, transaction) + return !!(app && app.isSystem === true) } -async function isMicroserviceRouter (microservice, transaction) { - if (microservice.name === `router-${microservice.iofogUuid.toLowerCase()}`) { - const app = await ApplicationManager.findOne({ id: microservice.applicationId }, transaction) - if (app.isSystem === true) { - return true - } +async function isMicroserviceNats (microservice, transaction) { + if (microservice.name !== 'nats') { + return false } - return false + const app = await ApplicationManager.findOne({ id: microservice.applicationId }, transaction) + return !!(app && app.isSystem === true) } async function createVolumeMappingEndPoint (microserviceUuid, volumeMappingData, isCLI, transaction) { @@ -1990,6 +1959,24 @@ function _validateMicroserviceAnnotations (annotations) { return result } +function _validateMicroserviceSchedule (schedule, isSystem) { + if (schedule === undefined || schedule === null) { + return + } + if (!Number.isInteger(schedule)) { + throw new Errors.ValidationError('Microservice schedule must be an integer') + } + if (isSystem) { + if (schedule < 0 || schedule > 5) { + throw new Errors.ValidationError('System microservice schedule must be between 0 and 5') + } + return + } + if (schedule < 6 || schedule > 100) { + throw new Errors.ValidationError('Microservice schedule must be between 6 and 100') + } +} + function _validateMicroserviceHealthCheck (healthCheck) { let result if (healthCheck) { @@ -2037,7 +2024,9 @@ async function _createMicroservice (microserviceData, isCLI, transaction) { runtime: microserviceData.runtime, registryId: microserviceData.registryId || 1, schedule: microserviceData.schedule || 50, - logSize: (microserviceData.logSize || constants.MICROSERVICE_DEFAULT_LOG_SIZE) * 1 + logSize: (microserviceData.logSize || constants.MICROSERVICE_DEFAULT_LOG_SIZE) * 1, + natsAccess: !!microserviceData.natsAccess, + natsRuleId: microserviceData.natsRuleId } newMicroservice = AppHelper.deleteUndefinedFields(newMicroservice) @@ -2052,6 +2041,9 @@ async function _createMicroservice (microserviceData, isCLI, transaction) { // validate application const application = await _validateApplication(microserviceData.application, isCLI, transaction) newMicroservice.applicationId = application.id + if (newMicroservice.natsAccess && !application.natsAccess) { + throw new Errors.ValidationError('Microservice natsAccess requires application natsAccess=true') + } await _checkForDuplicateName(newMicroservice.name, {}, newMicroservice.applicationId, transaction) @@ -2410,38 +2402,18 @@ async function _validateSystemMicroserviceOnGet (microserviceUuid, transaction) } } -async function _getLogicalRoutesByMicroservice (microserviceUuid, transaction) { - const res = [] - const query = { - [Op.or]: - [ - { - sourceMicroserviceUuid: microserviceUuid - }, - { - destMicroserviceUuid: microserviceUuid - } - ] - } - const routes = await RoutingManager.findAllPopulated(query, transaction) - for (const route of routes) { - if (route.sourceMicroserviceUuid && route.destMicroserviceUuid) { - res.push(route) - } - } - return res -} - async function deleteMicroserviceWithRoutesAndPortMappings (microservice, transaction) { - const routes = await _getLogicalRoutesByMicroservice(microservice.uuid, transaction) - for (const route of routes) { - await RoutingService.deleteRouting(route.application.name, route.name, false, transaction) - } - + // Clear Microservice -> NatsUser FK before revoking user (Postgres/MySQL enforce FK; SQLite does not) + await MicroserviceManager.update( + { uuid: microservice.uuid }, + { natsAccountId: null, natsUserId: null, natsCredsSecretName: null }, + transaction + ) + await NatsAuthService.revokeMicroserviceUser(microservice.uuid, transaction) await MicroservicePortService.deletePortMappings(microservice, transaction) // Delete service account for microservice (safety net in case it wasn't deleted earlier) - await _deleteServiceAccountForMicroservice(microservice.name, transaction) + await _deleteServiceAccountForMicroservice(microservice.uuid, transaction) await MicroserviceManager.delete({ uuid: microservice.uuid @@ -2457,7 +2429,6 @@ async function _buildGetMicroserviceResponse (microservice, transaction) { const extraHosts = await MicroserviceExtraHostManager.findAll({ microserviceUuid: microserviceUuid }, transaction) const images = await CatalogItemImageManager.findAll({ microserviceUuid: microserviceUuid }, transaction) const volumeMappings = await VolumeMappingManager.findAll({ microserviceUuid: microserviceUuid }, transaction) - const routes = await getReceiverMicroservices(microservice, transaction) const env = await MicroserviceEnvManager.findAllExcludeFields({ microserviceUuid: microserviceUuid }, transaction) const cmd = await MicroserviceArgManager.findAllExcludeFields({ microserviceUuid: microserviceUuid }, transaction) const arg = cmd.map((it) => it.cmd) @@ -2467,8 +2438,6 @@ async function _buildGetMicroserviceResponse (microservice, transaction) { const capAdds = capAdd.map((it) => it.capAdd) const capDrop = await MicroserviceCapDropManager.findAllExcludeFields({ microserviceUuid: microserviceUuid }, transaction) const capDrops = capDrop.map((it) => it.capDrop) - const pubTags = microservice.pubTags ? microservice.pubTags.map(t => t.value) : [] - const subTags = microservice.subTags ? microservice.subTags.map(t => t.value) : [] const status = await MicroserviceStatusManager.findAllExcludeFields({ microserviceUuid: microserviceUuid }, transaction) const execStatus = await MicroserviceExecStatusManager.findAllExcludeFields({ microserviceUuid: microserviceUuid }, transaction) const healthCheck = await MicroserviceHealthCheckManager.findAllExcludeFields({ microserviceUuid: microserviceUuid }, transaction) @@ -2481,7 +2450,6 @@ async function _buildGetMicroserviceResponse (microservice, transaction) { res.ports.push(mapping) } res.volumeMappings = volumeMappings.map((vm) => vm.dataValues) - res.routes = routes res.env = env res.cmd = arg res.cdiDevices = cdiDevs @@ -2542,8 +2510,6 @@ async function _buildGetMicroserviceResponse (microservice, transaction) { res.healthCheck = {} } } - res.pubTags = pubTags - res.subTags = subTags res.logSize *= 1 @@ -2552,41 +2518,19 @@ async function _buildGetMicroserviceResponse (microservice, transaction) { // API retrocompatibility res.flowId = res.applicationId - return res -} - -async function listMicroserviceByPubTagEndPoint (pubTag, transaction) { - const where = { - delete: false, - '$pubTags.value$': pubTag - } - - const microservices = await MicroserviceManager.findAllExcludeFields(where, transaction) - - const res = await Promise.all(microservices.map(async (microservice) => { - return _buildGetMicroserviceResponse(microservice.dataValues, transaction) - })) - - return { - microservices: res + // Resolve natsRuleId to rule name for API response + let natsRuleName = null + if (res.natsRuleId) { + const natsRule = await NatsUserRuleManager.findOne({ id: res.natsRuleId }, transaction) + natsRuleName = natsRule ? natsRule.name : null } -} - -async function listMicroserviceBySubTagEndPoint (subTag, transaction) { - const where = { - delete: false, - '$subTags.value$': subTag + res.natsConfig = { + natsAccess: !!res.natsAccess, + natsRule: natsRuleName } + delete res.natsRuleId - const microservices = await MicroserviceManager.findAllExcludeFields(where, transaction) - - const res = await Promise.all(microservices.map(async (microservice) => { - return _buildGetMicroserviceResponse(microservice.dataValues, transaction) - })) - - return { - microservices: res - } + return res } async function createExecEndPoint (microserviceUuid, isCLI, transaction) { @@ -2710,32 +2654,52 @@ async function stopMicroserviceEndPoint (microserviceUuid, isCLI, transaction) { } } +async function reconcileNatsForApplication (applicationId, transaction) { + const application = await ApplicationManager.findOne({ id: applicationId }, transaction) + if (!application) { + return + } + const microservices = await MicroserviceManager.findAll({ applicationId }, transaction) + for (const microservice of microservices) { + if (!application.natsAccess || !microservice.natsAccess) { + if (microservice.natsUserId || microservice.natsCredsSecretName || microservice.natsAccess) { + await NatsAuthService.revokeMicroserviceUser(microservice.uuid, transaction) + await _detachNatsCredsForMicroservice(microservice, transaction) + } + continue + } + const reconcileTriggerOptions = { triggerReconcile: false } + await NatsAuthService.reissueUserForMicroservice(microservice.uuid, transaction, reconcileTriggerOptions) + const refreshed = await MicroserviceManager.findOne({ uuid: microservice.uuid }, transaction) + await _ensureNatsCredsForMicroservice(refreshed || microservice, transaction) + } +} + +const bypassOptions = { bypassQueue: true } + module.exports = { - createMicroserviceEndPoint: TransactionDecorator.generateTransaction(createMicroserviceEndPoint), + createMicroserviceEndPoint: TransactionDecorator.generateTransaction(createMicroserviceEndPoint, bypassOptions), createPortMappingEndPoint: TransactionDecorator.generateTransaction(createPortMappingEndPoint), createSystemPortMappingEndPoint: TransactionDecorator.generateTransaction(createSystemPortMappingEndPoint), - createRouteEndPoint: TransactionDecorator.generateTransaction(createRouteEndPoint), createVolumeMappingEndPoint: TransactionDecorator.generateTransaction(createVolumeMappingEndPoint), createSystemVolumeMappingEndPoint: TransactionDecorator.generateTransaction(createSystemVolumeMappingEndPoint), - deleteMicroserviceEndPoint: TransactionDecorator.generateTransaction(deleteMicroserviceEndPoint), + deleteMicroserviceEndPoint: TransactionDecorator.generateTransaction(deleteMicroserviceEndPoint, bypassOptions), deleteMicroserviceWithRoutesAndPortMappings: deleteMicroserviceWithRoutesAndPortMappings, deleteNotRunningMicroservices: deleteNotRunningMicroservices, deletePortMappingEndPoint: TransactionDecorator.generateTransaction(deletePortMappingEndPoint), deleteSystemPortMappingEndPoint: TransactionDecorator.generateTransaction(deleteSystemPortMappingEndPoint), - deleteRouteEndPoint: TransactionDecorator.generateTransaction(deleteRouteEndPoint), deleteVolumeMappingEndPoint: TransactionDecorator.generateTransaction(deleteVolumeMappingEndPoint), deleteSystemVolumeMappingEndPoint: TransactionDecorator.generateTransaction(deleteSystemVolumeMappingEndPoint), getMicroserviceEndPoint: TransactionDecorator.generateTransaction(getMicroserviceEndPoint), getSystemMicroserviceEndPoint: TransactionDecorator.generateTransaction(getSystemMicroserviceEndPoint), - getReceiverMicroservices, - isMicroserviceConsumer, isMicroserviceRouter, + isMicroserviceNats, listMicroservicePortMappingsEndPoint: TransactionDecorator.generateTransaction(listPortMappingsEndPoint), listMicroservicesEndPoint: TransactionDecorator.generateTransaction(listMicroservicesEndPoint), listSystemMicroservicesEndPoint: TransactionDecorator.generateTransaction(listSystemMicroservicesEndPoint), listVolumeMappingsEndPoint: TransactionDecorator.generateTransaction(listVolumeMappingsEndPoint), - updateMicroserviceEndPoint: TransactionDecorator.generateTransaction(updateMicroserviceEndPoint), - updateSystemMicroserviceEndPoint: TransactionDecorator.generateTransaction(updateSystemMicroserviceEndPoint), + updateMicroserviceEndPoint: TransactionDecorator.generateTransaction(updateMicroserviceEndPoint, bypassOptions), + updateSystemMicroserviceEndPoint: TransactionDecorator.generateTransaction(updateSystemMicroserviceEndPoint, bypassOptions), updateMicroserviceConfigEndPoint: TransactionDecorator.generateTransaction(updateMicroserviceConfigEndPoint), getMicroserviceConfigEndPoint: TransactionDecorator.generateTransaction(getMicroserviceConfigEndPoint), getSystemMicroserviceConfigEndPoint: TransactionDecorator.generateTransaction(getSystemMicroserviceConfigEndPoint), @@ -2746,12 +2710,11 @@ module.exports = { rebuildSystemMicroserviceEndPoint: TransactionDecorator.generateTransaction(rebuildSystemMicroserviceEndPoint), buildGetMicroserviceResponse: _buildGetMicroserviceResponse, updateChangeTracking: _updateChangeTracking, - listMicroserviceByPubTagEndPoint: TransactionDecorator.generateTransaction(listMicroserviceByPubTagEndPoint), - listMicroserviceBySubTagEndPoint: TransactionDecorator.generateTransaction(listMicroserviceBySubTagEndPoint), createExecEndPoint: TransactionDecorator.generateTransaction(createExecEndPoint), deleteExecEndPoint: TransactionDecorator.generateTransaction(deleteExecEndPoint), createSystemExecEndPoint: TransactionDecorator.generateTransaction(createSystemExecEndPoint), deleteSystemExecEndPoint: TransactionDecorator.generateTransaction(deleteSystemExecEndPoint), startMicroserviceEndPoint: TransactionDecorator.generateTransaction(startMicroserviceEndPoint), - stopMicroserviceEndPoint: TransactionDecorator.generateTransaction(stopMicroserviceEndPoint) + stopMicroserviceEndPoint: TransactionDecorator.generateTransaction(stopMicroserviceEndPoint), + reconcileNatsForApplication: TransactionDecorator.generateTransaction(reconcileNatsForApplication, bypassOptions) } diff --git a/src/services/nats-api-service.js b/src/services/nats-api-service.js new file mode 100644 index 000000000..db37e1a37 --- /dev/null +++ b/src/services/nats-api-service.js @@ -0,0 +1,593 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2023 Datasance Teknoloji A.S. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const NatsAuthService = require('./nats-auth-service') +const NatsHubService = require('./nats-hub-service') +const NatsAccountManager = require('../data/managers/nats-account-manager') +const NatsUserManager = require('../data/managers/nats-user-manager') +const NatsAccountRuleManager = require('../data/managers/nats-account-rule-manager') +const NatsUserRuleManager = require('../data/managers/nats-user-rule-manager') +const ApplicationManager = require('../data/managers/application-manager') +const MicroserviceManager = require('../data/managers/microservice-manager') +const SecretService = require('./secret-service') +const Errors = require('../helpers/errors') +const ErrorMessages = require('../helpers/error-messages') +const AppHelper = require('../helpers/app-helper') +const Validator = require('../schemas') +const NatsSystemRules = require('../config/nats-system-rules') +const TransactionDecorator = require('../decorators/transaction-decorator') +const config = require('../config') +// const logger = require('../logger') + +/** + * Parse a byte-size limit value: integer or string with k/m/g/t suffix. + * Examples: -1, 1024, "1k", "100m", "1g", "1t" (case-insensitive). + * Returns integer or undefined if invalid/missing. + */ +function _parseLimitValue (val) { + if (val === undefined || val === null) return undefined + if (typeof val === 'number') return Number.isInteger(val) ? val : Math.floor(val) + if (typeof val !== 'string') return undefined + const s = String(val).trim() + if (s === '' || s === '-1') return -1 + const match = s.match(/^(\d+)([kmgt])?$/i) + if (!match) return undefined + const num = parseInt(match[1], 10) + const suffix = (match[2] || '').toLowerCase() + const multipliers = { k: 1024, m: 1024 * 1024, g: 1024 * 1024 * 1024, t: 1024 * 1024 * 1024 * 1024 } + return suffix ? num * multipliers[suffix] : num +} + +function _normalizeRulePayload (payload, isAccountRule = false) { + return { + name: payload.name, + description: payload.description, + infoUrl: isAccountRule ? payload.infoUrl : undefined, + maxConnections: isAccountRule ? payload.maxConnections : undefined, + maxLeafNodeConnections: isAccountRule ? payload.maxLeafNodeConnections : undefined, + maxData: payload.maxData !== undefined && payload.maxData !== null ? _parseLimitValue(payload.maxData) : payload.maxData, + maxExports: isAccountRule ? payload.maxExports : undefined, + maxImports: isAccountRule ? payload.maxImports : undefined, + maxMsgPayload: isAccountRule && (payload.maxMsgPayload !== undefined && payload.maxMsgPayload !== null) ? _parseLimitValue(payload.maxMsgPayload) : (isAccountRule ? payload.maxMsgPayload : undefined), + maxSubscriptions: payload.maxSubscriptions, + exportsAllowWildcards: isAccountRule ? payload.exportsAllowWildcards : undefined, + disallowBearer: isAccountRule ? payload.disallowBearer : undefined, + responsePermissions: payload.responsePermissions ? JSON.stringify(payload.responsePermissions) : undefined, + respMax: payload.respMax, + respTtl: payload.respTtl, + imports: isAccountRule && payload.imports != null ? (Array.isArray(payload.imports) ? JSON.stringify(payload.imports) : payload.imports) : undefined, + exports: isAccountRule && payload.exports != null ? (Array.isArray(payload.exports) ? JSON.stringify(payload.exports) : payload.exports) : undefined, + memStorage: isAccountRule && (payload.memStorage !== undefined && payload.memStorage !== null) ? _parseLimitValue(payload.memStorage) : (isAccountRule ? payload.memStorage : undefined), + diskStorage: isAccountRule && (payload.diskStorage !== undefined && payload.diskStorage !== null) ? _parseLimitValue(payload.diskStorage) : (isAccountRule ? payload.diskStorage : undefined), + streams: isAccountRule ? payload.streams : undefined, + consumer: isAccountRule ? payload.consumer : undefined, + maxAckPending: isAccountRule ? payload.maxAckPending : undefined, + memMaxStreamBytes: isAccountRule && (payload.memMaxStreamBytes !== undefined && payload.memMaxStreamBytes !== null) ? _parseLimitValue(payload.memMaxStreamBytes) : (isAccountRule ? payload.memMaxStreamBytes : undefined), + diskMaxStreamBytes: isAccountRule && (payload.diskMaxStreamBytes !== undefined && payload.diskMaxStreamBytes !== null) ? _parseLimitValue(payload.diskMaxStreamBytes) : (isAccountRule ? payload.diskMaxStreamBytes : undefined), + maxBytesRequired: isAccountRule ? payload.maxBytesRequired : undefined, + tieredLimits: isAccountRule && payload.tieredLimits != null ? (typeof payload.tieredLimits === 'object' ? JSON.stringify(payload.tieredLimits) : payload.tieredLimits) : undefined, + maxPayload: !isAccountRule && (payload.maxPayload !== undefined && payload.maxPayload !== null) ? _parseLimitValue(payload.maxPayload) : (!isAccountRule ? payload.maxPayload : undefined), + bearerToken: !isAccountRule ? payload.bearerToken : undefined, + proxyRequired: !isAccountRule ? payload.proxyRequired : undefined, + allowedConnectionTypes: payload.allowedConnectionTypes ? JSON.stringify(payload.allowedConnectionTypes) : undefined, + src: !isAccountRule && payload.src != null ? (Array.isArray(payload.src) ? JSON.stringify(payload.src) : payload.src) : undefined, + times: !isAccountRule && payload.times != null ? (Array.isArray(payload.times) ? JSON.stringify(payload.times) : payload.times) : undefined, + timesLocation: !isAccountRule ? payload.timesLocation : undefined, + pubAllow: payload.pubAllow ? JSON.stringify(payload.pubAllow) : undefined, + pubDeny: payload.pubDeny ? JSON.stringify(payload.pubDeny) : undefined, + subAllow: payload.subAllow ? JSON.stringify(payload.subAllow) : undefined, + subDeny: payload.subDeny ? JSON.stringify(payload.subDeny) : undefined, + tags: !isAccountRule && payload.tags != null ? (Array.isArray(payload.tags) ? JSON.stringify(payload.tags) : payload.tags) : undefined + } +} + +function _assertRuleIsMutable (name) { + if (NatsSystemRules.isReservedRuleName(name)) { + throw new Errors.ValidationError(`Rule ${name} is reserved and immutable`) + } +} + +function _hydrateRulePayload (rule, isAccountRule = false) { + return { + id: rule.id, + name: rule.name, + description: rule.description, + infoUrl: isAccountRule ? rule.infoUrl : undefined, + maxConnections: isAccountRule ? rule.maxConnections : undefined, + maxLeafNodeConnections: isAccountRule ? rule.maxLeafNodeConnections : undefined, + maxData: rule.maxData, + maxExports: isAccountRule ? rule.maxExports : undefined, + maxImports: isAccountRule ? rule.maxImports : undefined, + maxMsgPayload: isAccountRule ? rule.maxMsgPayload : undefined, + maxSubscriptions: rule.maxSubscriptions, + exportsAllowWildcards: isAccountRule ? rule.exportsAllowWildcards : undefined, + disallowBearer: isAccountRule ? rule.disallowBearer : undefined, + responsePermissions: rule.responsePermissions ? JSON.parse(rule.responsePermissions) : undefined, + respMax: rule.respMax, + respTtl: rule.respTtl, + imports: isAccountRule && rule.imports != null ? (typeof rule.imports === 'string' ? JSON.parse(rule.imports) : rule.imports) : undefined, + exports: isAccountRule && rule.exports != null ? (typeof rule.exports === 'string' ? JSON.parse(rule.exports) : rule.exports) : undefined, + memStorage: isAccountRule ? rule.memStorage : undefined, + diskStorage: isAccountRule ? rule.diskStorage : undefined, + streams: isAccountRule ? rule.streams : undefined, + consumer: isAccountRule ? rule.consumer : undefined, + maxAckPending: isAccountRule ? rule.maxAckPending : undefined, + memMaxStreamBytes: isAccountRule ? rule.memMaxStreamBytes : undefined, + diskMaxStreamBytes: isAccountRule ? rule.diskMaxStreamBytes : undefined, + maxBytesRequired: isAccountRule ? rule.maxBytesRequired : undefined, + tieredLimits: isAccountRule && rule.tieredLimits != null ? (typeof rule.tieredLimits === 'string' ? JSON.parse(rule.tieredLimits) : rule.tieredLimits) : undefined, + maxPayload: !isAccountRule ? rule.maxPayload : undefined, + bearerToken: !isAccountRule ? rule.bearerToken : undefined, + proxyRequired: !isAccountRule ? rule.proxyRequired : undefined, + allowedConnectionTypes: rule.allowedConnectionTypes ? JSON.parse(rule.allowedConnectionTypes) : undefined, + src: !isAccountRule && rule.src != null ? (typeof rule.src === 'string' ? JSON.parse(rule.src) : rule.src) : undefined, + times: !isAccountRule && rule.times != null ? (typeof rule.times === 'string' ? JSON.parse(rule.times) : rule.times) : undefined, + timesLocation: !isAccountRule ? rule.timesLocation : undefined, + pubAllow: rule.pubAllow ? JSON.parse(rule.pubAllow) : undefined, + pubDeny: rule.pubDeny ? JSON.parse(rule.pubDeny) : undefined, + subAllow: rule.subAllow ? JSON.parse(rule.subAllow) : undefined, + subDeny: rule.subDeny ? JSON.parse(rule.subDeny) : undefined, + tags: !isAccountRule && rule.tags != null ? (typeof rule.tags === 'string' ? JSON.parse(rule.tags) : rule.tags) : undefined + } +} + +async function listAccounts (transaction) { + const accounts = await NatsAccountManager.findAll({}, transaction) + return { + accounts: accounts.map(account => ({ + id: account.id, + name: account.name, + publicKey: account.publicKey, + jwt: account.jwt, + isSystem: account.isSystem, + isLeafSystem: account.isLeafSystem, + applicationId: account.applicationId + })) + } +} + +async function getOperator (transaction) { + const operator = await NatsAuthService.ensureOperator(transaction) + return { + name: operator.name, + publicKey: operator.publicKey, + jwt: operator.jwt + } +} + +function _isKubernetesControlPlane () { + const controlPlane = process.env.CONTROL_PLANE || config.get('app.ControlPlane') + return controlPlane && String(controlPlane).toLowerCase() === 'kubernetes' +} + +async function getBootstrap (transaction) { + if (!_isKubernetesControlPlane()) { + throw new Errors.ForbiddenError('NATS bootstrap is only available when the Controller runs on the Kubernetes control plane') + } + const operator = await NatsAuthService.ensureOperator(transaction, { triggerReconcile: false }) + const seedSecret = await SecretService.getSecretEndpoint(operator.seedSecretName, transaction) + if (!seedSecret || !seedSecret.data || !seedSecret.data.seed) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.SECRET_NOT_FOUND, operator.seedSecretName)) + } + const operatorSeed = typeof seedSecret.data.seed === 'string' + ? seedSecret.data.seed + : Buffer.from(seedSecret.data.seed).toString('utf8') + + const { account: systemAccount, user } = await NatsAuthService.ensureSysUserForServer({ isHub: true }, transaction) + const credsSecret = await SecretService.getSecretEndpoint(user.credsSecretName, transaction) + if (!credsSecret || !credsSecret.data) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.SECRET_NOT_FOUND, user.credsSecretName)) + } + const credsKey = Object.keys(credsSecret.data).find((key) => key.endsWith('.creds')) || 'creds' + const raw = credsSecret.data[credsKey] + if (!raw) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.SECRET_NOT_FOUND, user.credsSecretName)) + } + const sysUserCredsBase64 = typeof raw === 'string' + ? Buffer.from(raw, 'utf8').toString('base64') + : Buffer.from(raw).toString('base64') + + return { + operatorJwt: operator.jwt, + operatorPublicKey: operator.publicKey, + operatorSeed, + systemAccountJwt: systemAccount.jwt, + systemAccountPublicKey: systemAccount.publicKey, + sysUserCredsBase64 + } +} + +async function rotateOperator (transaction) { + const operator = await NatsAuthService.ensureOperator(transaction) + NatsAuthService.scheduleRotateOperator() + return { + name: operator.name, + publicKey: operator.publicKey, + jwt: operator.jwt + } +} + +async function getHub (transaction) { + return NatsHubService.getDefaultHub(transaction) +} + +async function upsertHub (payload, transaction) { + const hub = await NatsHubService.upsertDefaultHub(payload || {}, transaction) + return { + host: hub.host, + serverPort: hub.serverPort, + clusterPort: hub.clusterPort, + leafPort: hub.leafPort, + mqttPort: hub.mqttPort, + httpPort: hub.httpPort + } +} + +async function getAccount (appName, transaction) { + const application = await ApplicationManager.findOne({ name: appName }, transaction) + if (!application) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_NAME, appName)) + } + const account = await NatsAccountManager.findOne({ applicationId: application.id }, transaction) + if (!account) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, application.id)) + } + return { + id: account.id, + name: account.name, + publicKey: account.publicKey, + jwt: account.jwt, + isSystem: account.isSystem, + applicationId: account.applicationId + } +} + +async function ensureAccount (appName, payload, transaction) { + const application = await ApplicationManager.findOne({ name: appName }, transaction) + if (!application) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_NAME, appName)) + } + if (application.natsAccess) { + throw new Errors.ValidationError( + 'Application already has NATS account enabled. Update application natsConfig (natsAccess/natsRule) to change.' + ) + } + const ruleName = (payload && payload.natsRule) || NatsSystemRules.APPLICATION_ACCOUNT_RULE_NAME + const rule = await NatsAccountRuleManager.findOne({ name: ruleName }, transaction) + if (!rule) { + throw new Errors.ValidationError(`NATS account rule '${ruleName}' not found`) + } + const account = await NatsAuthService.ensureAccountForApplication(application.id, transaction) + await ApplicationManager.update({ id: application.id }, { + natsAccess: true, + natsRuleId: rule.id + }, transaction) + return { + id: account.id, + name: account.name, + publicKey: account.publicKey, + jwt: account.jwt, + isSystem: account.isSystem, + applicationId: account.applicationId + } +} + +async function listAllUsers (transaction) { + const users = await NatsUserManager.findAllWithAccountAndApplication(transaction) + return { + users: users.map(user => ({ + id: user.id, + name: user.name, + publicKey: user.publicKey, + jwt: user.jwt, + isBearer: user.isBearer, + accountId: user.accountId, + accountName: user.account ? user.account.name : null, + applicationId: user.account && user.account.application ? user.account.application.id : null, + applicationName: user.account && user.account.application ? user.account.application.name : null, + microserviceUuid: user.microserviceUuid + })) + } +} + +async function listUsers (appName, transaction) { + const application = await ApplicationManager.findOne({ name: appName }, transaction) + if (!application) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_NAME, appName)) + } + const account = await NatsAccountManager.findOne({ applicationId: application.id }, transaction) + if (!account) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, application.id)) + } + const users = await NatsUserManager.findAll({ accountId: account.id }, transaction) + return { + users: users.map(user => ({ + id: user.id, + name: user.name, + publicKey: user.publicKey, + jwt: user.jwt, + isBearer: user.isBearer, + microserviceUuid: user.microserviceUuid + })) + } +} + +async function createUser (appName, payload, transaction) { + await Validator.validate(payload || {}, Validator.schemas.natsUserCreate) + const userName = payload && payload.name + if (!userName) { + throw new Errors.ValidationError('User name is required') + } + const application = await ApplicationManager.findOne({ name: appName }, transaction) + if (!application) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_NAME, appName)) + } + const account = await NatsAuthService.ensureAccountForApplication(application.id, transaction) + const expiresIn = payload && payload.expiresIn + const natsRule = payload && payload.natsRule + const { user } = await NatsAuthService.createUserForAccount(account.id, userName, expiresIn, natsRule, null, transaction) + return { + id: user.id, + name: user.name, + publicKey: user.publicKey, + jwt: user.jwt, + isBearer: user.isBearer + } +} + +async function getUserCreds (appName, userName, transaction) { + const application = await ApplicationManager.findOne({ name: appName }, transaction) + const sysAccount = await NatsAccountManager.findOne({ name: appName }, transaction) + + if (!application && (!sysAccount || (!sysAccount.isSystem && !sysAccount.isLeafSystem))) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_NAME, appName)) + } + let accountId = null + if (application) { + const account = await NatsAccountManager.findOne({ applicationId: application.id }, transaction) + if (!account) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, application.id)) + } + accountId = account.id + } + if (sysAccount && (sysAccount.isSystem || sysAccount.isLeafSystem)) { + accountId = sysAccount.id + } + const user = await NatsUserManager.findOne({ accountId: accountId, name: userName }, transaction) + if (!user) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_NAME, userName)) + } + const secret = await SecretService.getSecretEndpoint(user.credsSecretName, transaction) + if (!secret || !secret.data) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.SECRET_NOT_FOUND, user.credsSecretName)) + } + const credsKey = Object.keys(secret.data).find((key) => key.endsWith('.creds')) || 'creds' + const raw = secret.data[credsKey] + if (!raw) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.SECRET_NOT_FOUND, user.credsSecretName)) + } + const credsBase64 = typeof raw === 'string' + ? Buffer.from(raw, 'utf8').toString('base64') + : Buffer.from(raw).toString('base64') + return { + credsBase64 + } +} + +async function createMqttBearer (appName, payload, transaction) { + await Validator.validate(payload || {}, Validator.schemas.natsUserCreate) + const userName = payload && payload.name + if (!userName) { + throw new Errors.ValidationError('User name is required') + } + const application = await ApplicationManager.findOne({ name: appName }, transaction) + if (!application) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_NAME, appName)) + } + const expiresIn = payload && payload.expiresIn + const natsRule = payload && payload.natsRule + const { user, bearerJwt } = await NatsAuthService.createMqttBearerUser(application.id, userName, expiresIn, natsRule, transaction) + return { + id: user.id, + name: user.name, + publicKey: user.publicKey, + jwt: bearerJwt + } +} + +async function deleteUser (appName, userName, transaction) { + const application = await ApplicationManager.findOne({ name: appName }, transaction) + if (!application) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_NAME, appName)) + } + const account = await NatsAccountManager.findOne({ applicationId: application.id }, transaction) + if (!account) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, application.id)) + } + await NatsAuthService.revokeUserByAccountAndName(account.id, userName, transaction) +} + +async function deleteMqttBearer (appName, userName, transaction) { + const application = await ApplicationManager.findOne({ name: appName }, transaction) + if (!application) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_NAME, appName)) + } + const account = await NatsAccountManager.findOne({ applicationId: application.id }, transaction) + if (!account) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, application.id)) + } + const user = await NatsUserManager.findOne({ accountId: account.id, name: userName }, transaction) + if (!user) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_NAME, userName)) + } + if (!user.isBearer) { + throw new Errors.ValidationError('User is not an MQTT bearer user. Use account user delete endpoint instead.') + } + await NatsAuthService.revokeUserByAccountAndName(account.id, userName, transaction) +} + +async function listAccountRules (transaction) { + await NatsAuthService.ensureDefaultRules(transaction) + const rules = await NatsAccountRuleManager.findAll({}, transaction) + const systemRuleNames = new Set(NatsSystemRules.getSystemAccountRuleDefinitions().map((rule) => rule.name)) + const customRules = rules.filter((rule) => !systemRuleNames.has(rule.name)) + const systemRules = await Promise.all( + NatsSystemRules.getSystemAccountRuleDefinitions().map(async (rule) => { + const persisted = await NatsAccountRuleManager.findOne({ name: rule.name }, transaction) + return _hydrateRulePayload(persisted || rule, true) + }) + ) + return { + rules: [ + ...systemRules.map((rule) => ({ ...rule, isSystem: true })), + ...customRules.map((rule) => ({ ..._hydrateRulePayload(rule, true), isSystem: false })) + ] + } +} + +async function createAccountRule (payload, transaction) { + await Validator.validate(payload || {}, Validator.schemas.natsAccountRulePayload) + if (!payload || !payload.name) { + throw new Errors.ValidationError('name is required') + } + _assertRuleIsMutable(payload.name) + const existing = await NatsAccountRuleManager.findOne({ name: payload.name }, transaction) + if (existing) { + throw new Errors.ValidationError(`NATS account rule ${payload.name} already exists`) + } + const created = await NatsAccountRuleManager.create(_normalizeRulePayload(payload, true), transaction) + return _hydrateRulePayload(created, true) +} + +async function updateAccountRule (ruleName, payload, transaction) { + await Validator.validate(payload || {}, Validator.schemas.natsAccountRulePayload) + _assertRuleIsMutable(ruleName) + const rule = await NatsAccountRuleManager.findOne({ name: ruleName }, transaction) + if (!rule) { + throw new Errors.NotFoundError(`NATS account rule ${ruleName} not found`) + } + const normalizedPayload = _normalizeRulePayload(payload, true) + delete normalizedPayload.name + await NatsAccountRuleManager.update({ id: rule.id }, normalizedPayload, transaction) + NatsAuthService.scheduleReissueForAccountRule(rule.id) + const updated = await NatsAccountRuleManager.findOne({ id: rule.id }, transaction) + return _hydrateRulePayload(updated, true) +} + +async function deleteAccountRule (ruleName, transaction) { + _assertRuleIsMutable(ruleName) + const rule = await NatsAccountRuleManager.findOne({ name: ruleName }, transaction) + if (!rule) { + throw new Errors.NotFoundError(`NATS account rule ${ruleName} not found`) + } + + const affectedApps = await ApplicationManager.findAll({ natsRuleId: rule.id }, transaction) + if (affectedApps.length > 0) { + throw new Errors.ValidationError( + 'Cannot delete NATS account rule that is attached to one or more applications. Detach or change the rule on each application first.' + ) + } + await NatsAccountRuleManager.delete({ id: rule.id }, transaction) +} + +async function listUserRules (transaction) { + await NatsAuthService.ensureDefaultRules(transaction) + const rules = await NatsUserRuleManager.findAll({}, transaction) + const systemRuleNames = new Set(NatsSystemRules.getSystemUserRuleDefinitions().map((rule) => rule.name)) + const customRules = rules.filter((rule) => !systemRuleNames.has(rule.name)) + const systemRules = await Promise.all( + NatsSystemRules.getSystemUserRuleDefinitions().map(async (rule) => { + const persisted = await NatsUserRuleManager.findOne({ name: rule.name }, transaction) + return _hydrateRulePayload(persisted || rule, false) + }) + ) + return { + rules: [ + ...systemRules.map((rule) => ({ ...rule, isSystem: true })), + ...customRules.map((rule) => ({ ..._hydrateRulePayload(rule, false), isSystem: false })) + ] + } +} + +async function createUserRule (payload, transaction) { + await Validator.validate(payload || {}, Validator.schemas.natsUserRulePayload) + if (!payload || !payload.name) { + throw new Errors.ValidationError('name is required') + } + _assertRuleIsMutable(payload.name) + const existing = await NatsUserRuleManager.findOne({ name: payload.name }, transaction) + if (existing) { + throw new Errors.ValidationError(`NATS user rule ${payload.name} already exists`) + } + const created = await NatsUserRuleManager.create(_normalizeRulePayload(payload, false), transaction) + return _hydrateRulePayload(created, false) +} + +async function updateUserRule (ruleName, payload, transaction) { + await Validator.validate(payload || {}, Validator.schemas.natsUserRulePayload) + _assertRuleIsMutable(ruleName) + const rule = await NatsUserRuleManager.findOne({ name: ruleName }, transaction) + if (!rule) { + throw new Errors.NotFoundError(`NATS user rule ${ruleName} not found`) + } + const normalizedPayload = _normalizeRulePayload(payload, false) + delete normalizedPayload.name + await NatsUserRuleManager.update({ id: rule.id }, normalizedPayload, transaction) + NatsAuthService.scheduleReissueForUserRule(rule.id) + const updated = await NatsUserRuleManager.findOne({ id: rule.id }, transaction) + return _hydrateRulePayload(updated, false) +} + +async function deleteUserRule (ruleName, transaction) { + _assertRuleIsMutable(ruleName) + const rule = await NatsUserRuleManager.findOne({ name: ruleName }, transaction) + if (!rule) { + throw new Errors.NotFoundError(`NATS user rule ${ruleName} not found`) + } + + const affectedMicroservices = await MicroserviceManager.findAll({ natsRuleId: rule.id }, transaction) + if (affectedMicroservices.length > 0) { + throw new Errors.ValidationError( + 'Cannot delete NATS user rule that is attached to one or more users/microservices. Detach or change the rule on each microservice first.' + ) + } + await NatsUserRuleManager.delete({ id: rule.id }, transaction) +} + +const bypassOptions = { bypassQueue: true } + +module.exports = { + getOperator: TransactionDecorator.generateTransaction(getOperator, bypassOptions), + rotateOperator: TransactionDecorator.generateTransaction(rotateOperator, bypassOptions), + getBootstrap: TransactionDecorator.generateTransaction(getBootstrap, bypassOptions), + getHub: TransactionDecorator.generateTransaction(getHub, bypassOptions), + upsertHub: TransactionDecorator.generateTransaction(upsertHub, bypassOptions), + listAccounts: TransactionDecorator.generateTransaction(listAccounts), + getAccount: TransactionDecorator.generateTransaction(getAccount), + ensureAccount: TransactionDecorator.generateTransaction(ensureAccount, bypassOptions), + listAllUsers: TransactionDecorator.generateTransaction(listAllUsers), + listUsers: TransactionDecorator.generateTransaction(listUsers), + createUser: TransactionDecorator.generateTransaction(createUser, bypassOptions), + getUserCreds: TransactionDecorator.generateTransaction(getUserCreds), + deleteUser: TransactionDecorator.generateTransaction(deleteUser, bypassOptions), + createMqttBearer: TransactionDecorator.generateTransaction(createMqttBearer, bypassOptions), + deleteMqttBearer: TransactionDecorator.generateTransaction(deleteMqttBearer, bypassOptions), + listAccountRules: TransactionDecorator.generateTransaction(listAccountRules), + createAccountRule: TransactionDecorator.generateTransaction(createAccountRule, bypassOptions), + updateAccountRule: TransactionDecorator.generateTransaction(updateAccountRule, bypassOptions), + deleteAccountRule: TransactionDecorator.generateTransaction(deleteAccountRule, bypassOptions), + listUserRules: TransactionDecorator.generateTransaction(listUserRules), + createUserRule: TransactionDecorator.generateTransaction(createUserRule, bypassOptions), + updateUserRule: TransactionDecorator.generateTransaction(updateUserRule, bypassOptions), + deleteUserRule: TransactionDecorator.generateTransaction(deleteUserRule, bypassOptions) +} diff --git a/src/services/nats-auth-service.js b/src/services/nats-auth-service.js new file mode 100644 index 000000000..01a071daa --- /dev/null +++ b/src/services/nats-auth-service.js @@ -0,0 +1,1223 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2023 Datasance Teknoloji A.S. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const { createOperator, createAccount, createUser, fromSeed, encodeOperator, encodeAccount, encodeUser, fmtCreds } = require('@nats-io/jwt') +const AppHelper = require('../helpers/app-helper') +const Errors = require('../helpers/errors') +const ErrorMessages = require('../helpers/error-messages') +const config = require('../config') +const SecretService = require('./secret-service') +const ApplicationManager = require('../data/managers/application-manager') +const NatsOperatorManager = require('../data/managers/nats-operator-manager') +const NatsAccountManager = require('../data/managers/nats-account-manager') +const NatsUserManager = require('../data/managers/nats-user-manager') +const NatsAccountRuleManager = require('../data/managers/nats-account-rule-manager') +const NatsUserRuleManager = require('../data/managers/nats-user-rule-manager') +const MicroserviceManager = require('../data/managers/microservice-manager') +const TransactionDecorator = require('../decorators/transaction-decorator') +const logger = require('../logger') +const NatsSystemRules = require('../config/nats-system-rules') +const { slugifyName } = require('../helpers/system-naming') + +const OPERATOR_SEED_SECRET = 'nats-operator-seed' +const SYSTEM_ACCOUNT_NAME = 'SYS' +const SYSTEM_ACCOUNT_SEED_SECRET = 'nats-system-account-seed' +const leafSystemAccountName = (fog) => `SYS-leaf-${slugifyName(fog.name)}` +function sysUserNameForServer (isHub, fog) { + return isHub ? 'admin-hub' : `admin-server-${slugifyName(fog.name)}` +} +const leafSystemAccountSeedSecretName = (fog) => `nats-leaf-system-seed-${slugifyName(fog.name)}` +const leafSystemAccountUserName = (fog) => `admin-leaf-${slugifyName(fog.name)}` +const accountSeedSecretName = (applicationName) => `nats-account-seed-${slugifyName(applicationName)}` +const mqttBearerSecretName = (applicationName, userName) => `nats-mqtt-creds-${slugifyName(applicationName)}-${slugifyName(userName)}` +const microserviceCredsSecretName = (applicationName, microserviceName) => `nats-creds-${slugifyName(applicationName)}-${slugifyName(microserviceName)}` + +function _parseJsonText (value, fallback) { + if (!value) { + return fallback + } + try { + return JSON.parse(value) + } catch (error) { + return fallback + } +} + +function _credsSecretData (accountName, userName, credsString) { + const key = `${slugifyName(accountName, 64)}/${slugifyName(userName, 64)}.creds` + return { [key]: credsString } +} + +function _buildAccountRuleClaims (rule) { + if (!rule) { + return {} + } + const limits = { + conn: rule.maxConnections, + leaf: rule.maxLeafNodeConnections, + data: rule.maxData, + exports: rule.maxExports, + imports: rule.maxImports, + payload: rule.maxMsgPayload, + subs: rule.maxSubscriptions, + wildcards: rule.exportsAllowWildcards, + disallow_bearer: rule.disallowBearer + } + if (rule.memStorage != null || rule.diskStorage != null || rule.streams != null || + rule.consumer != null || rule.maxAckPending != null || rule.memMaxStreamBytes != null || + rule.diskMaxStreamBytes != null || rule.maxBytesRequired != null) { + limits.mem_storage = rule.memStorage + limits.disk_storage = rule.diskStorage + limits.streams = rule.streams + limits.consumer = rule.consumer + limits.max_ack_pending = rule.maxAckPending + limits.mem_max_stream_bytes = rule.memMaxStreamBytes + limits.disk_max_stream_bytes = rule.diskMaxStreamBytes + limits.max_bytes_required = rule.maxBytesRequired + } + if (rule.tieredLimits) { + const tiered = _parseJsonText(rule.tieredLimits, undefined) + if (tiered && typeof tiered === 'object') { + limits.tiered_limits = tiered + } + } + const defaultPerms = { + pub: { + allow: _parseJsonText(rule.pubAllow, undefined), + deny: _parseJsonText(rule.pubDeny, undefined) + }, + sub: { + allow: _parseJsonText(rule.subAllow, undefined), + deny: _parseJsonText(rule.subDeny, undefined) + } + } + if (rule.respMax != null || rule.respTtl != null) { + defaultPerms.resp = { + max: rule.respMax, + ttl: rule.respTtl + } + } + const out = { + limits, + default_permissions: defaultPerms + } + if (rule.description != null) out.description = rule.description + if (rule.infoUrl != null) out.info_url = rule.infoUrl + const importsVal = rule.imports != null ? (Array.isArray(rule.imports) ? rule.imports : _parseJsonText(rule.imports, undefined)) : undefined + if (Array.isArray(importsVal) && importsVal.length > 0) out.imports = importsVal + const exportsVal = rule.exports != null ? (Array.isArray(rule.exports) ? rule.exports : _parseJsonText(rule.exports, undefined)) : undefined + if (Array.isArray(exportsVal) && exportsVal.length > 0) out.exports = exportsVal + return out +} + +function _buildUserRuleClaims (rule, baseClaims = {}) { + if (!rule) { + return baseClaims + } + const out = { + ...baseClaims, + bearer_token: rule.bearerToken || baseClaims.bearer_token, + allowed_connection_types: _parseJsonText(rule.allowedConnectionTypes, baseClaims.allowed_connection_types), + pub: { + allow: _parseJsonText(rule.pubAllow, undefined), + deny: _parseJsonText(rule.pubDeny, undefined) + }, + sub: { + allow: _parseJsonText(rule.subAllow, undefined), + deny: _parseJsonText(rule.subDeny, undefined) + }, + subs: rule.maxSubscriptions, + data: rule.maxData, + payload: rule.maxPayload + } + if (rule.proxyRequired != null) out.proxy_required = rule.proxyRequired + const src = _parseJsonText(rule.src, undefined) + if (Array.isArray(src)) out.src = src + const times = _parseJsonText(rule.times, undefined) + if (Array.isArray(times)) out.times = times + if (rule.timesLocation != null) out.times_location = rule.timesLocation + if (rule.respMax != null || rule.respTtl != null) { + out.resp = { max: rule.respMax, ttl: rule.respTtl } + } + const tags = _parseJsonText(rule.tags, undefined) + if (Array.isArray(tags)) out.tags = tags + return out +} + +function _decodeJwtPayload (jwt) { + try { + if (!jwt || typeof jwt !== 'string') { + return {} + } + const parts = jwt.split('.') + if (parts.length < 2) { + return {} + } + return JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf8')) + } catch (error) { + logger.warn(`Failed to decode JWT payload: ${error.message}`) + return {} + } +} + +function _extractAccountRevocations (accountJwt) { + const payload = _decodeJwtPayload(accountJwt) + return (payload && payload.nats && payload.nats.revocations) || {} +} + +async function _resolveNatsUserRule (ruleName, defaultRuleName, transaction) { + if (ruleName) { + const explicitRule = await NatsUserRuleManager.findOne({ name: ruleName }, transaction) + if (!explicitRule) { + throw new Errors.ValidationError(`NATS user rule ${ruleName} does not exist`) + } + return explicitRule + } + + return NatsUserRuleManager.findOne({ name: defaultRuleName }, transaction) +} + +async function _encodeAccountJwtWithRuleAndRevocations (accountName, accountKp, operatorKp, rule, existingAccountJwt) { + const existingRevocations = _extractAccountRevocations(existingAccountJwt) + return encodeAccount( + accountName, + accountKp, + { + ..._buildAccountRuleClaims(rule), + revocations: existingRevocations + }, + { signer: operatorKp } + ) +} + +function _normalizeSystemUserRuleForPersistence (rule) { + return { + ...rule, + allowedConnectionTypes: rule.allowedConnectionTypes ? JSON.stringify(rule.allowedConnectionTypes) : undefined + } +} + +/** + * NATS reconciliation is triggered in two ways: + * (A) From this module: _triggerResolverArtifactsReconcile calls NatsService.enqueueReconcileTask (fire-and-forget). + * Call sites: ensureOperator, rotateOperator, ensureSystemAccount, createUserForAccount, ensureAccountForApplication, + * createAccountForApplication, ensureUserForMicroservice, createMqttBearerUser, ensureLeafSystemAccount, + * reissueAccountForApplication, reissueUserForMicroservice, deleteAccountForApplication, revokeMicroserviceUser, + * reissueForAccountRule, reissueForUserRule, revokeUserByAccountAndName, deleteLeafSystemArtifactsForFog, etc. + * (B) From nats-service: enqueueReconcileTask(..., transaction) inside ensureNatsForFog (cluster-routes-changed) and + * cleanupNatsForFog (server-deleted). + * All API endpoints that trigger reconciliation use the transaction-queue bypass (bypassQueue: true) so requests + * do not wait behind long-running reconcile jobs. + */ +function _triggerResolverArtifactsReconcile (triggerOptions = {}) { + if (triggerOptions.triggerReconcile === false) { + return + } + const NatsService = require('./nats-service') + if (NatsService && typeof NatsService.enqueueReconcileTask === 'function') { + const options = { reason: 'auth-mutation', ...triggerOptions } + NatsService.enqueueReconcileTask(options).catch((err) => { + logger.error(`NATS reconcile enqueue failed: ${err.message}`) + }) + } +} + +function _runBackgroundTask (label, task) { + setImmediate(async () => { + try { + logger.info(`Starting background NATS task: ${label}`) + await task() + logger.info(`Completed background NATS task: ${label}`) + } catch (error) { + logger.error(`Background NATS task failed (${label}): ${error.message}`) + } + }) +} + +async function _loadSeedFromSecret (secretName, transaction) { + const secret = await SecretService.getSecretEndpoint(secretName, transaction) + if (!secret || !secret.data || !secret.data.seed) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.SECRET_NOT_FOUND, secretName)) + } + return secret.data.seed +} + +async function _upsertOpaqueSecret (name, data, transaction) { + try { + await SecretService.createSecretEndpoint({ + name, + type: 'Opaque', + data + }, transaction) + } catch (error) { + if (error.name === 'ConflictError') { + await SecretService.updateSecretEndpointIfChanged(name, { + name, + type: 'Opaque', + data + }, transaction) + } else { + throw error + } + } +} + +function _triggerOptionsFromArgs (args) { + const second = args[0] + return (second && typeof second === 'object' && !second.fakeTransaction) ? second : {} +} + +async function ensureOperator (transaction, ...rest) { + const options = _triggerOptionsFromArgs(rest) + const existing = await NatsOperatorManager.findOne({}, transaction) + if (existing) { + return existing + } + + const operatorName = `${config.get('app.name')}-operator` + const operatorKp = createOperator() + const operatorJwt = await encodeOperator(operatorName, operatorKp) + const operatorSeed = new TextDecoder().decode(operatorKp.getSeed()) + + await _upsertOpaqueSecret(OPERATOR_SEED_SECRET, { seed: operatorSeed }, transaction) + + const created = await NatsOperatorManager.create({ + name: operatorName, + publicKey: operatorKp.getPublicKey(), + jwt: operatorJwt, + seedSecretName: OPERATOR_SEED_SECRET + }, transaction) + _triggerResolverArtifactsReconcile(options) + return created +} + +async function rotateOperator (transaction) { + const existing = await NatsOperatorManager.findOne({}, transaction) + if (!existing) { + return ensureOperator(transaction) + } + + const operatorName = existing.name + const operatorKp = createOperator() + const operatorJwt = await encodeOperator(operatorName, operatorKp) + const operatorSeed = new TextDecoder().decode(operatorKp.getSeed()) + + await SecretService.updateSecretEndpointIfChanged(existing.seedSecretName, { + name: existing.seedSecretName, + type: 'Opaque', + data: { seed: operatorSeed } + }, transaction) + + await NatsOperatorManager.update({ id: existing.id }, { + publicKey: operatorKp.getPublicKey(), + jwt: operatorJwt + }, transaction) + + const accounts = await NatsAccountManager.findAll({}, transaction) + logger.info(`Rotating NATS operator and re-signing ${accounts.length} accounts`) + for (const account of accounts) { + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + const app = account.applicationId ? await ApplicationManager.findOne({ id: account.applicationId }, transaction) : null + const accountRule = account.isSystem + ? await NatsAccountRuleManager.findOne({ name: NatsSystemRules.SYSTEM_ACCOUNT_RULE_NAME }, transaction) + : (app && app.natsRuleId + ? await NatsAccountRuleManager.findOne({ id: app.natsRuleId }, transaction) + : await NatsAccountRuleManager.findOne({ name: NatsSystemRules.APPLICATION_ACCOUNT_RULE_NAME }, transaction)) + const newAccountJwt = await _encodeAccountJwtWithRuleAndRevocations( + account.name, + accountKp, + operatorKp, + accountRule, + account.jwt + ) + await NatsAccountManager.update({ id: account.id }, { jwt: newAccountJwt }, transaction) + } + + _triggerResolverArtifactsReconcile() + + return NatsOperatorManager.findOne({ id: existing.id }, transaction) +} + +async function ensureSystemAccount (transaction, ...rest) { + const options = _triggerOptionsFromArgs(rest) + await ensureDefaultRules(transaction) + const existing = await NatsAccountManager.findOne({ isSystem: true }, transaction) + if (existing) { + return existing + } + + const operator = await ensureOperator(transaction, options) + const operatorSeed = await _loadSeedFromSecret(operator.seedSecretName, transaction) + const operatorKp = fromSeed(new TextEncoder().encode(operatorSeed)) + + const accountKp = createAccount() + const systemRule = await NatsAccountRuleManager.findOne({ name: NatsSystemRules.SYSTEM_ACCOUNT_RULE_NAME }, transaction) + const accountJwt = await encodeAccount(SYSTEM_ACCOUNT_NAME, accountKp, { ..._buildAccountRuleClaims(systemRule), exports: NatsSystemRules.SYS_ACCOUNT_EXPORTS_INLINE }, { signer: operatorKp }) + const accountSeed = new TextDecoder().decode(accountKp.getSeed()) + + await _upsertOpaqueSecret(SYSTEM_ACCOUNT_SEED_SECRET, { seed: accountSeed }, transaction) + + const created = await NatsAccountManager.create({ + name: SYSTEM_ACCOUNT_NAME, + publicKey: accountKp.getPublicKey(), + jwt: accountJwt, + seedSecretName: SYSTEM_ACCOUNT_SEED_SECRET, + operatorId: operator.id, + isSystem: true, + isLeafSystem: false, + applicationId: null + }, transaction) + _triggerResolverArtifactsReconcile({ ...options, reason: 'system-account-created' }) + return created +} + +async function ensureLeafSystemAccount (fog, transaction) { + await ensureDefaultRules(transaction) + const operator = await ensureOperator(transaction) + const name = leafSystemAccountName(fog) + const existing = await NatsAccountManager.findOne({ name, operatorId: operator.id, isLeafSystem: true }, transaction) + if (existing) { + return existing + } + + const operatorSeed = await _loadSeedFromSecret(operator.seedSecretName, transaction) + const operatorKp = fromSeed(new TextEncoder().encode(operatorSeed)) + + const accountKp = createAccount() + const systemRule = await NatsAccountRuleManager.findOne({ name: NatsSystemRules.SYSTEM_ACCOUNT_RULE_NAME }, transaction) + const accountJwt = await encodeAccount(name, accountKp, { ..._buildAccountRuleClaims(systemRule), exports: NatsSystemRules.SYS_ACCOUNT_EXPORTS_INLINE }, { signer: operatorKp }) + const accountSeed = new TextDecoder().decode(accountKp.getSeed()) + + const seedSecretName = leafSystemAccountSeedSecretName(fog) + await _upsertOpaqueSecret(seedSecretName, { seed: accountSeed }, transaction) + + const created = await NatsAccountManager.create({ + name, + publicKey: accountKp.getPublicKey(), + jwt: accountJwt, + seedSecretName, + operatorId: operator.id, + isSystem: false, + isLeafSystem: true, + applicationId: null + }, transaction) + _triggerResolverArtifactsReconcile({ fogUuids: [fog.uuid] }) + return created +} + +async function ensureSysUserForServer (options = {}, transaction) { + const { isHub = true, fog } = options + const account = await ensureSystemAccount(transaction) + const sysUserName = sysUserNameForServer(isHub, fog) + const existingUser = await NatsUserManager.findOne({ accountId: account.id, name: sysUserName }, transaction) + const created = !existingUser + const { user } = existingUser + ? { user: existingUser } + : await createUserForAccount(account.id, sysUserName, null, null, null, transaction) + if (created && fog && fog.uuid) { + _triggerResolverArtifactsReconcile({ fogUuids: [fog.uuid] }) + } + return { account, user } +} + +async function ensureLeafSystemAccountUser (fog, transaction) { + const account = await ensureLeafSystemAccount(fog, transaction) + const userName = leafSystemAccountUserName(fog) + const existing = await NatsUserManager.findOne({ accountId: account.id, name: userName }, transaction) + if (existing) { + return { account, user: existing } + } + const result = await createUserForAccount(account.id, userName, null, null, null, transaction) + _triggerResolverArtifactsReconcile({ fogUuids: [fog.uuid] }) + return result +} + +/** + * Returns secret names for leaf system artifacts (creds + account seed) if a leaf system account exists for this fog. + * Used by nats-service to clean up mounts/secrets when deleting a leaf or transitioning leaf→server. + * @param {object} fog + * @param {object} transaction + * @returns {{ credsSecretName: string, seedSecretName: string } | null} + */ +async function getLeafSystemArtifactSecretNames (fog, transaction) { + const operator = await NatsOperatorManager.findOne({}, transaction) + if (!operator) return null + const name = leafSystemAccountName(fog) + const account = await NatsAccountManager.findOne({ name, operatorId: operator.id, isLeafSystem: true }, transaction) + if (!account) return null + const userName = leafSystemAccountUserName(fog) + const user = await NatsUserManager.findOne({ accountId: account.id, name: userName }, transaction) + if (!user || !user.credsSecretName) return { credsSecretName: null, seedSecretName: account.seedSecretName } + return { credsSecretName: user.credsSecretName, seedSecretName: account.seedSecretName } +} + +/** + * Deletes leaf system account, its user(s), and their secrets for a fog. Idempotent if already gone. + * Call when cleaning up a leaf instance or when transitioning a fog from leaf to server. + * @param {object} fog + * @param {object} transaction + */ +async function deleteLeafSystemArtifactsForFog (fog, transaction) { + const operator = await NatsOperatorManager.findOne({}, transaction) + if (!operator) return + const name = leafSystemAccountName(fog) + const account = await NatsAccountManager.findOne({ name, operatorId: operator.id, isLeafSystem: true }, transaction) + if (!account) return + const users = await NatsUserManager.findAll({ accountId: account.id }, transaction) + for (const user of users || []) { + if (user.credsSecretName) { + try { + await SecretService.deleteSecretEndpoint(user.credsSecretName, transaction) + } catch (error) { + // best-effort cleanup + } + } + await NatsUserManager.delete({ id: user.id }, transaction) + } + if (account.seedSecretName) { + try { + await SecretService.deleteSecretEndpoint(account.seedSecretName, transaction) + } catch (error) { + // best-effort cleanup + } + } + await NatsAccountManager.delete({ id: account.id }, transaction) + _triggerResolverArtifactsReconcile({ fogUuids: [fog.uuid] }) +} + +/** + * Deletes the system account user (and its creds secret) for a NATS server node. + * Used when cleaning up a fog that had a NATS server (hub or non-hub). Idempotent if already gone. + * @param {object} fog + * @param {boolean} isHub - whether the deleted instance was a hub + * @param {object} transaction + */ +async function deleteServerSysUserForFog (fog, isHub, transaction) { + const systemAccount = await NatsAccountManager.findOne({ isSystem: true }, transaction) + if (!systemAccount) return + const sysUserName = sysUserNameForServer(isHub, fog) + const user = await NatsUserManager.findOne({ accountId: systemAccount.id, name: sysUserName }, transaction) + if (!user) return + if (user.credsSecretName) { + try { + await SecretService.deleteSecretEndpoint(user.credsSecretName, transaction) + } catch (error) { + // best-effort cleanup + } + } + await NatsUserManager.delete({ id: user.id }, transaction) + _triggerResolverArtifactsReconcile({ fogUuids: [fog.uuid] }) +} + +async function ensureAccountForApplication (applicationId, transaction) { + await ensureDefaultRules(transaction) + const existing = await NatsAccountManager.findOne({ applicationId }, transaction) + if (existing) { + return existing + } + + const application = await ApplicationManager.findOne({ id: applicationId }, transaction) + if (!application) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, applicationId)) + } + + const operator = await ensureOperator(transaction) + const operatorSeed = await _loadSeedFromSecret(operator.seedSecretName, transaction) + const operatorKp = fromSeed(new TextEncoder().encode(operatorSeed)) + + const accountKp = createAccount() + const defaultAccountRule = await NatsAccountRuleManager.findOne({ name: NatsSystemRules.APPLICATION_ACCOUNT_RULE_NAME }, transaction) + const accountRule = application.natsRuleId + ? await NatsAccountRuleManager.findOne({ id: application.natsRuleId }, transaction) + : defaultAccountRule + const accountJwt = await encodeAccount(application.name, accountKp, _buildAccountRuleClaims(accountRule), { signer: operatorKp }) + const accountSeed = new TextDecoder().decode(accountKp.getSeed()) + + const seedSecretName = accountSeedSecretName(application.name) + await _upsertOpaqueSecret(seedSecretName, { seed: accountSeed }, transaction) + + const created = await NatsAccountManager.create({ + name: application.name, + publicKey: accountKp.getPublicKey(), + jwt: accountJwt, + seedSecretName: seedSecretName, + operatorId: operator.id, + applicationId: application.id, + isSystem: false, + isLeafSystem: false + }, transaction) + _triggerResolverArtifactsReconcile({ reason: 'account-created', applicationId: application.id }) + return created +} + +async function ensureUserForMicroservice (microservice, transaction) { + await ensureDefaultRules(transaction) + if (!microservice.applicationId) { + throw new Errors.ValidationError('Microservice must belong to an application to enable NATS') + } + + const account = await ensureAccountForApplication(microservice.applicationId, transaction) + const existingUser = await NatsUserManager.findOne({ microserviceUuid: microservice.uuid }, transaction) + if (existingUser) { + const existingAccount = await NatsAccountManager.findOne({ id: existingUser.accountId }, transaction) + if (!existingAccount || existingUser.accountId !== account.id) { + const reissued = await reissueUserForMicroservice(microservice.uuid, transaction) + return { account, user: reissued } + } + return { account: existingAccount, user: existingUser } + } + + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + + const userKp = createUser() + const userName = microservice.name + const defaultUserRule = await NatsUserRuleManager.findOne({ name: NatsSystemRules.MICROSERVICE_USER_RULE_NAME }, transaction) + const userRule = microservice.natsRuleId + ? await NatsUserRuleManager.findOne({ id: microservice.natsRuleId }, transaction) + : defaultUserRule + const userJwt = await encodeUser(userName, userKp, accountKp, _buildUserRuleClaims(userRule, {})) + const creds = fmtCreds(userJwt, userKp) + const credsString = Buffer.from(creds).toString('utf8') + + const application = await ApplicationManager.findOne({ id: microservice.applicationId }, transaction) + const credsSecretName = microserviceCredsSecretName(application ? application.name : 'app', microservice.name) + const accountName = application ? application.name : account.name + await _upsertOpaqueSecret(credsSecretName, _credsSecretData(accountName, userName, credsString), transaction) + + const natsUser = await NatsUserManager.create({ + name: userName, + publicKey: userKp.getPublicKey(), + jwt: userJwt, + credsSecretName: credsSecretName, + isBearer: false, + accountId: account.id, + microserviceUuid: microservice.uuid, + natsUserRuleId: userRule ? userRule.id : null + }, transaction) + + _triggerResolverArtifactsReconcile({ fogUuids: [microservice.iofogUuid] }) + return { account, user: natsUser } +} + +function _parseExpiresIn (expiresIn) { + if (!expiresIn) { + return 7 * 24 * 60 * 60 + } + const match = /^(\d+)([hdm])$/.exec(expiresIn) + if (!match) { + throw new Errors.ValidationError('expiresIn must be in format: ') + } + const value = Number(match[1]) + const unit = match[2] + if (!Number.isFinite(value) || value <= 0) { + throw new Errors.ValidationError('expiresIn must be greater than zero') + } + switch (unit) { + case 'h': + if (value > 24 * 365 * 3) { + throw new Errors.ValidationError('expiresIn cannot exceed 26280h (3 years)') + } + return value * 60 * 60 + case 'd': + if (value > 365 * 3) { + throw new Errors.ValidationError('expiresIn cannot exceed 1095d (3 years)') + } + return value * 24 * 60 * 60 + case 'm': + if (value > 36) { + throw new Errors.ValidationError('expiresIn cannot exceed 36m (3 years)') + } + return value * 30 * 24 * 60 * 60 + default: + throw new Errors.ValidationError('expiresIn must be in format: ') + } +} + +function _userClaimsWithExpiry (expiresIn, claims = {}) { + if (expiresIn == null) { + return { ...claims } + } + const expSeconds = _parseExpiresIn(expiresIn) + const exp = Math.floor(Date.now() / 1000) + expSeconds + return { ...claims, exp } +} + +async function createMqttBearerUser (applicationId, userName, expiresIn, natsRuleName, transaction) { + await ensureDefaultRules(transaction) + const account = await ensureAccountForApplication(applicationId, transaction) + const application = await ApplicationManager.findOne({ id: applicationId }, transaction) + const existingUser = await NatsUserManager.findOne({ accountId: account.id, name: userName }, transaction) + if (existingUser) { + return { account, user: existingUser, bearerJwt: existingUser.jwt } + } + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + + const userKp = createUser() + const userRule = await _resolveNatsUserRule( + natsRuleName, + NatsSystemRules.MQTT_BEARER_USER_RULE_NAME, + transaction + ) + const userJwt = await encodeUser(userName, userKp, accountKp, _buildUserRuleClaims(userRule, _userClaimsWithExpiry(expiresIn, { + bearer_token: true, + allowed_connection_types: ['MQTT'] + }))) + const creds = fmtCreds(userJwt, userKp) + const credsString = Buffer.from(creds).toString('utf8') + + const credsSecretName = mqttBearerSecretName(application ? application.name : `account-${account.id}`, userName) + const accountName = application ? application.name : account.name + await _upsertOpaqueSecret(credsSecretName, _credsSecretData(accountName, userName, credsString), transaction) + + const natsUser = await NatsUserManager.create({ + name: userName, + publicKey: userKp.getPublicKey(), + jwt: userJwt, + credsSecretName: credsSecretName, + isBearer: true, + accountId: account.id, + microserviceUuid: null, + natsUserRuleId: userRule ? userRule.id : null + }, transaction) + + return { account, user: natsUser, bearerJwt: userJwt } +} + +async function ensureDefaultRules (transaction) { + for (const accountRule of NatsSystemRules.getSystemAccountRuleDefinitions()) { + const data = { name: accountRule.name, ...accountRule } + if (Array.isArray(data.exports)) data.exports = JSON.stringify(data.exports) + if (Array.isArray(data.imports)) data.imports = JSON.stringify(data.imports) + await NatsAccountRuleManager.updateOrCreate({ name: accountRule.name }, data, transaction) + } + for (const userRule of NatsSystemRules.getSystemUserRuleDefinitions()) { + const data = _normalizeSystemUserRuleForPersistence(userRule) + await NatsUserRuleManager.updateOrCreate({ name: userRule.name }, { name: userRule.name, ...data }, transaction) + } +} + +async function createUserForAccount (accountId, userName, expiresIn, natsRuleName, microserviceUuid = null, transaction) { + await ensureDefaultRules(transaction) + const account = await NatsAccountManager.findOne({ id: accountId }, transaction) + if (!account) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, accountId)) + } + const existingUser = await NatsUserManager.findOne({ accountId: account.id, name: userName }, transaction) + if (existingUser) { + return { account, user: existingUser } + } + + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + + const userKp = createUser() + const userRule = await _resolveNatsUserRule( + natsRuleName, + NatsSystemRules.MICROSERVICE_USER_RULE_NAME, + transaction + ) + const userJwt = await encodeUser(userName, userKp, accountKp, _buildUserRuleClaims(userRule, _userClaimsWithExpiry(expiresIn))) + const creds = fmtCreds(userJwt, userKp) + const credsString = Buffer.from(creds).toString('utf8') + + const application = account.applicationId ? await ApplicationManager.findOne({ id: account.applicationId }, transaction) : null + const credsSecretName = `nats-creds-${slugifyName(application ? application.name : account.name)}-${slugifyName(userName)}` + const accountName = application ? application.name : account.name + await _upsertOpaqueSecret(credsSecretName, _credsSecretData(accountName, userName, credsString), transaction) + + if (microserviceUuid != null && typeof microserviceUuid !== 'string') { + microserviceUuid = null + } + const natsUser = await NatsUserManager.create({ + name: userName, + publicKey: userKp.getPublicKey(), + jwt: userJwt, + credsSecretName: credsSecretName, + isBearer: false, + accountId: account.id, + microserviceUuid: microserviceUuid, + natsUserRuleId: userRule ? userRule.id : null + }, transaction) + + return { account, user: natsUser } +} + +async function reissueAccountForApplication (applicationId, transaction) { + await ensureDefaultRules(transaction) + const application = await ApplicationManager.findOne({ id: applicationId }, transaction) + if (!application) { + return null + } + const account = await NatsAccountManager.findOne({ applicationId: application.id }, transaction) + if (!account) { + return null + } + + const operator = await ensureOperator(transaction) + const operatorSeed = await _loadSeedFromSecret(operator.seedSecretName, transaction) + const operatorKp = fromSeed(new TextEncoder().encode(operatorSeed)) + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + const defaultAccountRule = await NatsAccountRuleManager.findOne({ name: NatsSystemRules.APPLICATION_ACCOUNT_RULE_NAME }, transaction) + const accountRule = application.natsRuleId + ? await NatsAccountRuleManager.findOne({ id: application.natsRuleId }, transaction) + : defaultAccountRule + + const accountJwt = await _encodeAccountJwtWithRuleAndRevocations( + application.name, + accountKp, + operatorKp, + accountRule, + account.jwt + ) + await NatsAccountManager.update({ id: account.id }, { jwt: accountJwt }, transaction) + _triggerResolverArtifactsReconcile({ reason: 'account-created', applicationId }) + return NatsAccountManager.findOne({ id: account.id }, transaction) +} + +async function reissueUserForMicroservice (microserviceUuid, transaction, ...rest) { + const options = _triggerOptionsFromArgs(rest) + await ensureDefaultRules(transaction) + const microservice = await MicroserviceManager.findOne({ uuid: microserviceUuid }, transaction) + if (!microservice || !microservice.applicationId || !microservice.natsAccess) { + return null + } + + const account = await ensureAccountForApplication(microservice.applicationId, transaction) + const defaultUserRule = await NatsUserRuleManager.findOne({ name: NatsSystemRules.MICROSERVICE_USER_RULE_NAME }, transaction) + const userRule = microservice.natsRuleId + ? await NatsUserRuleManager.findOne({ id: microservice.natsRuleId }, transaction) + : defaultUserRule + const existingUser = await NatsUserManager.findOne({ microserviceUuid: microservice.uuid }, transaction) + + const currentRuleId = (userRule && userRule.id) || null + const existingRuleId = (existingUser && existingUser.natsUserRuleId != null) ? existingUser.natsUserRuleId : null + const sameRule = (existingRuleId === currentRuleId) + + if (!existingUser) { + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + const userKp = createUser() + const userJwt = await encodeUser(microservice.name, userKp, accountKp, _buildUserRuleClaims(userRule || defaultUserRule, {})) + const creds = fmtCreds(userJwt, userKp) + const credsString = Buffer.from(creds).toString('utf8') + const application = await ApplicationManager.findOne({ id: microservice.applicationId }, transaction) + const credsSecretName = microserviceCredsSecretName(application ? application.name : 'app', microservice.name) + const accountName = application ? application.name : account.name + await _upsertOpaqueSecret(credsSecretName, _credsSecretData(accountName, microservice.name, credsString), transaction) + await NatsUserManager.create({ + name: microservice.name, + publicKey: userKp.getPublicKey(), + jwt: userJwt, + credsSecretName: credsSecretName, + isBearer: false, + accountId: account.id, + microserviceUuid: microservice.uuid, + natsUserRuleId: currentRuleId + }, transaction) + _triggerResolverArtifactsReconcile({ reason: 'account-created', applicationId: microservice.applicationId, ...options }) + return NatsUserManager.findOne({ microserviceUuid: microservice.uuid }, transaction) + } + + if (existingUser.accountId !== account.id) { + const oldAccount = await NatsAccountManager.findOne({ id: existingUser.accountId }, transaction) + if (oldAccount) { + await _addRevocationToAccount(oldAccount, existingUser.publicKey, transaction) + if (options.triggerReconcile !== false && oldAccount.applicationId != null) { + _triggerResolverArtifactsReconcile({ reason: 'account-created', applicationId: oldAccount.applicationId, ...options }) + } + } + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + const userKp = createUser() + const userJwt = await encodeUser(microservice.name, userKp, accountKp, _buildUserRuleClaims(userRule || defaultUserRule, {})) + const creds = fmtCreds(userJwt, userKp) + const credsString = Buffer.from(creds).toString('utf8') + const application = await ApplicationManager.findOne({ id: microservice.applicationId }, transaction) + const fallbackSecretName = microserviceCredsSecretName(application ? application.name : 'app', microservice.name) + const credsSecretName = existingUser.credsSecretName || fallbackSecretName + const accountName = application ? application.name : account.name + await _upsertOpaqueSecret(credsSecretName, _credsSecretData(accountName, microservice.name, credsString), transaction) + await NatsUserManager.update({ id: existingUser.id }, { + name: microservice.name, + publicKey: userKp.getPublicKey(), + jwt: userJwt, + credsSecretName: credsSecretName, + accountId: account.id, + natsUserRuleId: currentRuleId + }, transaction) + _triggerResolverArtifactsReconcile({ reason: 'account-created', applicationId: microservice.applicationId, ...options }) + return NatsUserManager.findOne({ microserviceUuid: microservice.uuid }, transaction) + } + + if (!sameRule && userRule && userRule.id) { + const operator = await ensureOperator(transaction) + if (!operator) return null + const operatorSeed = await _loadSeedFromSecret(operator.seedSecretName, transaction) + const operatorKp = fromSeed(new TextEncoder().encode(operatorSeed)) + await _reissueOneUserForRule(existingUser, userRule.id, operatorKp, transaction) + _triggerResolverArtifactsReconcile({ reason: 'account-created', applicationId: microservice.applicationId, ...options }) + return NatsUserManager.findOne({ microserviceUuid: microservice.uuid }, transaction) + } + + _triggerResolverArtifactsReconcile({ reason: 'account-created', applicationId: microservice.applicationId, ...options }) + return NatsUserManager.findOne({ microserviceUuid: microservice.uuid }, transaction) +} + +async function ensureLeafUserForAccount (accountId, fogName, transaction, natsInstanceMicroserviceUuid = null) { + const leafUserName = `leaf-${fogName}` + const existing = await NatsUserManager.findOne({ accountId: accountId, name: leafUserName }, transaction) + if (existing) { + if (natsInstanceMicroserviceUuid != null && existing.microserviceUuid !== natsInstanceMicroserviceUuid) { + await NatsUserManager.update({ id: existing.id }, { microserviceUuid: natsInstanceMicroserviceUuid }, transaction) + return { user: await NatsUserManager.findOne({ id: existing.id }, transaction) } + } + return { user: existing } + } + try { + return await createUserForAccount(accountId, leafUserName, null, NatsSystemRules.DEFAULT_LEAF_USER_RULE_NAME, natsInstanceMicroserviceUuid, transaction) + } catch (err) { + if (err.name === 'SequelizeUniqueConstraintError') { + const user = await NatsUserManager.findOne({ accountId, name: leafUserName }, transaction) + if (user) { + logger.warn(`Leaf user already created by concurrent request, using existing user (accountId=${accountId}, name=${leafUserName})`) + return { user } + } + logger.error(`Unique constraint violation for leaf user but existing user not found (accountId=${accountId}, name=${leafUserName})`) + } + logger.error(`ensureLeafUserForAccount failed (accountId=${accountId}, leafUserName=${leafUserName}): ${err.message}`) + throw err + } +} + +async function reissueForAccountRule (accountRuleId, transaction) { + const applications = await ApplicationManager.findAll({ natsRuleId: accountRuleId }, transaction) + logger.info(`Reissuing account JWTs for rule ${accountRuleId}`) + for (const app of applications) { + const account = await NatsAccountManager.findOne({ applicationId: app.id }, transaction) + if (!account) { + continue + } + const operator = await ensureOperator(transaction) + const operatorSeed = await _loadSeedFromSecret(operator.seedSecretName, transaction) + const operatorKp = fromSeed(new TextEncoder().encode(operatorSeed)) + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + const rule = await NatsAccountRuleManager.findOne({ id: accountRuleId }, transaction) + const accountJwt = await _encodeAccountJwtWithRuleAndRevocations( + app.name, + accountKp, + operatorKp, + rule, + account.jwt + ) + await NatsAccountManager.update({ id: account.id }, { jwt: accountJwt }, transaction) + } + _triggerResolverArtifactsReconcile({ reason: 'account-rule-updated', accountRuleId }) +} + +/** + * Add a user public key to an account's JWT revocations and persist. Returns the account's applicationId for triggering. + */ +async function _addRevocationToAccount (account, publicKey, transaction) { + const operator = await ensureOperator(transaction) + const operatorSeed = await _loadSeedFromSecret(operator.seedSecretName, transaction) + const operatorKp = fromSeed(new TextEncoder().encode(operatorSeed)) + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + const app = account.applicationId ? await ApplicationManager.findOne({ id: account.applicationId }, transaction) : null + const accountRule = account.isSystem + ? await NatsAccountRuleManager.findOne({ name: NatsSystemRules.SYSTEM_ACCOUNT_RULE_NAME }, transaction) + : (app && app.natsRuleId + ? await NatsAccountRuleManager.findOne({ id: app.natsRuleId }, transaction) + : await NatsAccountRuleManager.findOne({ name: NatsSystemRules.APPLICATION_ACCOUNT_RULE_NAME }, transaction)) + const revocations = _extractAccountRevocations(account.jwt) + revocations[publicKey] = Math.floor(Date.now() / 1000) + const accountJwt = await encodeAccount( + account.name, + accountKp, + { ..._buildAccountRuleClaims(accountRule), revocations }, + { signer: operatorKp } + ) + await NatsAccountManager.update({ id: account.id }, { jwt: accountJwt }, transaction) + return account.applicationId +} + +async function _reissueOneUserForRule (user, userRuleId, operatorKp, transaction) { + const account = await NatsAccountManager.findOne({ id: user.accountId }, transaction) + if (!account) return + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + const app = account.applicationId ? await ApplicationManager.findOne({ id: account.applicationId }, transaction) : null + const accountRule = account.isSystem + ? await NatsAccountRuleManager.findOne({ name: NatsSystemRules.SYSTEM_ACCOUNT_RULE_NAME }, transaction) + : (app && app.natsRuleId + ? await NatsAccountRuleManager.findOne({ id: app.natsRuleId }, transaction) + : await NatsAccountRuleManager.findOne({ name: NatsSystemRules.APPLICATION_ACCOUNT_RULE_NAME }, transaction)) + const revocations = _extractAccountRevocations(account.jwt) + revocations[user.publicKey] = Math.floor(Date.now() / 1000) + const accountJwt = await encodeAccount( + account.name, + accountKp, + { ..._buildAccountRuleClaims(accountRule), revocations }, + { signer: operatorKp } + ) + await NatsAccountManager.update({ id: account.id }, { jwt: accountJwt }, transaction) + const userRule = await NatsUserRuleManager.findOne({ id: userRuleId }, transaction) + const userKp = createUser() + const userJwt = await encodeUser(user.name, userKp, accountKp, _buildUserRuleClaims(userRule, {})) + const creds = fmtCreds(userJwt, userKp) + const credsString = Buffer.from(creds).toString('utf8') + await _upsertOpaqueSecret(user.credsSecretName, _credsSecretData(account.name, user.name, credsString), transaction) + await NatsUserManager.update({ id: user.id }, { + jwt: userJwt, + publicKey: userKp.getPublicKey(), + natsUserRuleId: userRuleId + }, transaction) +} + +async function reissueForUserRule (userRuleId, transaction) { + const microservices = await MicroserviceManager.findAll({ natsRuleId: userRuleId }, transaction) + logger.info(`Reissuing user JWTs for rule ${userRuleId}`) + const operator = await ensureOperator(transaction) + const operatorSeed = await _loadSeedFromSecret(operator.seedSecretName, transaction) + const operatorKp = fromSeed(new TextEncoder().encode(operatorSeed)) + const processedUserIds = new Set() + + for (const ms of microservices) { + const user = await NatsUserManager.findOne({ microserviceUuid: ms.uuid }, transaction) + if (!user || processedUserIds.has(user.id)) continue + await _reissueOneUserForRule(user, userRuleId, operatorKp, transaction) + processedUserIds.add(user.id) + } + + const usersWithRuleId = await NatsUserManager.findAll({ natsUserRuleId: userRuleId }, transaction) + for (const user of usersWithRuleId || []) { + if (processedUserIds.has(user.id)) continue + await _reissueOneUserForRule(user, userRuleId, operatorKp, transaction) + processedUserIds.add(user.id) + } + _triggerResolverArtifactsReconcile({ reason: 'user-rule-updated', userRuleId }) +} + +async function revokeMicroserviceUser (microserviceUuid, transaction) { + const user = await NatsUserManager.findOne({ microserviceUuid }, transaction) + if (!user) { + return + } + const account = await NatsAccountManager.findOne({ id: user.accountId }, transaction) + if (!account) { + await NatsUserManager.delete({ id: user.id }, transaction) + return + } + + const operator = await ensureOperator(transaction) + const operatorSeed = await _loadSeedFromSecret(operator.seedSecretName, transaction) + const operatorKp = fromSeed(new TextEncoder().encode(operatorSeed)) + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + + const app = account.applicationId ? await ApplicationManager.findOne({ id: account.applicationId }, transaction) : null + const accountRule = account.isSystem + ? await NatsAccountRuleManager.findOne({ name: NatsSystemRules.SYSTEM_ACCOUNT_RULE_NAME }, transaction) + : (app && app.natsRuleId + ? await NatsAccountRuleManager.findOne({ id: app.natsRuleId }, transaction) + : await NatsAccountRuleManager.findOne({ name: NatsSystemRules.APPLICATION_ACCOUNT_RULE_NAME }, transaction)) + const revocations = _extractAccountRevocations(account.jwt) + revocations[user.publicKey] = Math.floor(Date.now() / 1000) + const accountJwt = await encodeAccount( + account.name, + accountKp, + { + ..._buildAccountRuleClaims(accountRule), + revocations + }, + { signer: operatorKp } + ) + await NatsAccountManager.update({ id: account.id }, { jwt: accountJwt }, transaction) + + try { + await SecretService.deleteSecretEndpoint(user.credsSecretName, transaction) + } catch (error) { + // best-effort secret cleanup + } + await NatsUserManager.delete({ id: user.id }, transaction) + _triggerResolverArtifactsReconcile({ reason: 'account-created', applicationId: account.applicationId }) +} + +async function deleteAccountForApplication (applicationId, transaction) { + const account = await NatsAccountManager.findOne({ applicationId }, transaction) + if (!account) { + return + } + const users = await NatsUserManager.findAll({ accountId: account.id }, transaction) + for (const user of users || []) { + if (user.credsSecretName) { + try { + await SecretService.deleteSecretEndpoint(user.credsSecretName, transaction) + } catch (error) { + // best-effort cleanup + } + } + await NatsUserManager.delete({ id: user.id }, transaction) + } + try { + await SecretService.deleteSecretEndpoint(account.seedSecretName, transaction) + } catch (error) { + // best-effort cleanup + } + await NatsAccountManager.delete({ id: account.id }, transaction) + _triggerResolverArtifactsReconcile({ reason: 'account-deleted', applicationId }) +} + +async function revokeUserByAccountAndName (accountId, userName, transaction) { + const user = await NatsUserManager.findOne({ accountId, name: userName }, transaction) + if (!user) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_NAME, userName)) + } + if (user.microserviceUuid) { + const microservice = await MicroserviceManager.findOne({ uuid: user.microserviceUuid }, transaction) + if (microservice) { + throw new Errors.ValidationError( + 'Cannot delete NATS user linked to an existing microservice. Disable natsAccess on the microservice or delete the microservice first.' + ) + } + } + + const account = await NatsAccountManager.findOne({ id: user.accountId }, transaction) + if (!account) { + await NatsUserManager.delete({ id: user.id }, transaction) + return + } + if (account.isSystem) { + throw new Errors.ValidationError('Cannot delete system account users') + } + + if (account.isLeafSystem) { + throw new Errors.ValidationError('Cannot delete leaf system account users') + } + + const operator = await ensureOperator(transaction) + const operatorSeed = await _loadSeedFromSecret(operator.seedSecretName, transaction) + const operatorKp = fromSeed(new TextEncoder().encode(operatorSeed)) + const accountSeed = await _loadSeedFromSecret(account.seedSecretName, transaction) + const accountKp = fromSeed(new TextEncoder().encode(accountSeed)) + + const app = account.applicationId ? await ApplicationManager.findOne({ id: account.applicationId }, transaction) : null + const accountRule = account.isSystem + ? await NatsAccountRuleManager.findOne({ name: NatsSystemRules.SYSTEM_ACCOUNT_RULE_NAME }, transaction) + : (app && app.natsRuleId + ? await NatsAccountRuleManager.findOne({ id: app.natsRuleId }, transaction) + : await NatsAccountRuleManager.findOne({ name: NatsSystemRules.APPLICATION_ACCOUNT_RULE_NAME }, transaction)) + const revocations = _extractAccountRevocations(account.jwt) + revocations[user.publicKey] = Math.floor(Date.now() / 1000) + const accountJwt = await encodeAccount( + account.name, + accountKp, + { + ..._buildAccountRuleClaims(accountRule), + revocations + }, + { signer: operatorKp } + ) + await NatsAccountManager.update({ id: account.id }, { jwt: accountJwt }, transaction) + + try { + await SecretService.deleteSecretEndpoint(user.credsSecretName, transaction) + } catch (error) { + // best-effort secret cleanup + } + await NatsUserManager.delete({ id: user.id }, transaction) + _triggerResolverArtifactsReconcile( + account.applicationId != null ? { reason: 'account-created', applicationId: account.applicationId } : {} + ) +} + +function scheduleRotateOperator () { + _runBackgroundTask('rotate-operator', async () => { + await module.exports.rotateOperator() + }) + return { scheduled: true } +} + +function scheduleReissueForAccountRule (accountRuleId) { + _runBackgroundTask(`reissue-account-rule-${accountRuleId}`, async () => { + await module.exports.reissueForAccountRule(accountRuleId) + }) + _triggerResolverArtifactsReconcile({ reason: 'account-rule-updated', accountRuleId }) + return { scheduled: true } +} + +function scheduleReissueForUserRule (userRuleId) { + _runBackgroundTask(`reissue-user-rule-${userRuleId}`, async () => { + await module.exports.reissueForUserRule(userRuleId) + }) + _triggerResolverArtifactsReconcile({ reason: 'user-rule-updated', userRuleId }) + return { scheduled: true } +} + +function scheduleReissueAccountsForApplications (applicationIds = []) { + _runBackgroundTask(`reissue-accounts-${applicationIds.length}`, async () => { + for (const applicationId of applicationIds) { + await module.exports.reissueAccountForApplication(applicationId) + } + }) + return { scheduled: true } +} + +function scheduleReissueUsersForMicroservices (microserviceUuids = []) { + _runBackgroundTask(`reissue-users-${microserviceUuids.length}`, async () => { + for (const microserviceUuid of microserviceUuids) { + const reconcileTriggerOptions = { triggerReconcile: false } + await module.exports.reissueUserForMicroservice(microserviceUuid, reconcileTriggerOptions) + } + }) + return { scheduled: true } +} + +module.exports = { + SYSTEM_ACCOUNT_NAME, + sysUserNameForServer, + leafSystemAccountName, + leafSystemAccountUserName, + ensureOperator: TransactionDecorator.generateTransaction(ensureOperator), + rotateOperator: TransactionDecorator.generateTransaction(rotateOperator), + ensureSystemAccount: TransactionDecorator.generateTransaction(ensureSystemAccount), + ensureSysUserForServer: TransactionDecorator.generateTransaction(ensureSysUserForServer), + ensureLeafSystemAccount: TransactionDecorator.generateTransaction(ensureLeafSystemAccount), + ensureLeafSystemAccountUser: TransactionDecorator.generateTransaction(ensureLeafSystemAccountUser), + ensureAccountForApplication: TransactionDecorator.generateTransaction(ensureAccountForApplication), + ensureUserForMicroservice: TransactionDecorator.generateTransaction(ensureUserForMicroservice), + createMqttBearerUser: TransactionDecorator.generateTransaction(createMqttBearerUser), + createUserForAccount: TransactionDecorator.generateTransaction(createUserForAccount), + ensureLeafUserForAccount: TransactionDecorator.generateTransaction(ensureLeafUserForAccount), + ensureDefaultRules: TransactionDecorator.generateTransaction(ensureDefaultRules), + reissueAccountForApplication: TransactionDecorator.generateTransaction(reissueAccountForApplication), + reissueUserForMicroservice: TransactionDecorator.generateTransaction(reissueUserForMicroservice), + reissueForAccountRule: TransactionDecorator.generateTransaction(reissueForAccountRule), + reissueForUserRule: TransactionDecorator.generateTransaction(reissueForUserRule), + revokeMicroserviceUser: TransactionDecorator.generateTransaction(revokeMicroserviceUser), + revokeUserByAccountAndName: TransactionDecorator.generateTransaction(revokeUserByAccountAndName), + deleteAccountForApplication: TransactionDecorator.generateTransaction(deleteAccountForApplication), + getLeafSystemArtifactSecretNames: TransactionDecorator.generateTransaction(getLeafSystemArtifactSecretNames), + deleteLeafSystemArtifactsForFog: TransactionDecorator.generateTransaction(deleteLeafSystemArtifactsForFog), + deleteServerSysUserForFog: TransactionDecorator.generateTransaction(deleteServerSysUserForFog), + scheduleRotateOperator, + scheduleReissueForAccountRule, + scheduleReissueForUserRule, + scheduleReissueAccountsForApplications, + scheduleReissueUsersForMicroservices +} diff --git a/src/services/nats-hub-service.js b/src/services/nats-hub-service.js new file mode 100644 index 000000000..822645848 --- /dev/null +++ b/src/services/nats-hub-service.js @@ -0,0 +1,72 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2023 Datasance Teknoloji A.S. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const Errors = require('../helpers/errors') +const Validator = require('../schemas') +const NatsInstanceManager = require('../data/managers/nats-instance-manager') +const TransactionDecorator = require('../decorators/transaction-decorator') +const NatsService = require('./nats-service') + +const DEFAULT_SERVER_PORT = 4222 +const DEFAULT_CLUSTER_PORT = 6222 +const DEFAULT_LEAF_PORT = 7422 +const DEFAULT_MQTT_PORT = 8883 +const DEFAULT_HTTP_PORT = 8222 +const DEFAULT_JS_STORAGE_SIZE = '10g' +const DEFAULT_JS_MEMORY_STORE_SIZE = '1g' + +async function getDefaultHub (transaction) { + const hub = await NatsInstanceManager.findOne({ isHub: true }, transaction) + if (!hub) { + throw new Errors.NotFoundError('NATS hub not found') + } + return { + host: hub.host, + serverPort: hub.serverPort, + clusterPort: hub.clusterPort, + leafPort: hub.leafPort, + mqttPort: hub.mqttPort, + httpPort: hub.httpPort + } +} + +async function upsertDefaultHub (hubData, transaction) { + await Validator.validate(hubData, Validator.schemas.natsHubCreate) + + const jsStorageSize = hubData.jsStorageSize != null && String(hubData.jsStorageSize).trim() !== '' + ? NatsService.normalizeJetstreamSize(hubData.jsStorageSize, DEFAULT_JS_STORAGE_SIZE) + : null + const jsMemoryStoreSize = hubData.jsMemoryStoreSize != null && String(hubData.jsMemoryStoreSize).trim() !== '' + ? NatsService.normalizeJetstreamSize(hubData.jsMemoryStoreSize, DEFAULT_JS_MEMORY_STORE_SIZE) + : null + + const createHubData = { + isHub: true, + isLeaf: false, + host: hubData.host, + serverPort: hubData.serverPort || DEFAULT_SERVER_PORT, + clusterPort: hubData.clusterPort || DEFAULT_CLUSTER_PORT, + leafPort: hubData.leafPort || DEFAULT_LEAF_PORT, + mqttPort: hubData.mqttPort || DEFAULT_MQTT_PORT, + httpPort: hubData.httpPort || DEFAULT_HTTP_PORT, + jsStorageSize: jsStorageSize || null, + jsMemoryStoreSize: jsMemoryStoreSize || null + } + + return NatsInstanceManager.updateOrCreate({ isHub: true }, createHubData, transaction) +} + +module.exports = { + getDefaultHub: TransactionDecorator.generateTransaction(getDefaultHub), + upsertDefaultHub: TransactionDecorator.generateTransaction(upsertDefaultHub) +} diff --git a/src/services/nats-service.js b/src/services/nats-service.js new file mode 100644 index 000000000..b36bab722 --- /dev/null +++ b/src/services/nats-service.js @@ -0,0 +1,1623 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2023 Datasance Teknoloji A.S. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const fs = require('fs') +const path = require('path') +const crypto = require('crypto') +const AppHelper = require('../helpers/app-helper') +const Errors = require('../helpers/errors') +const ErrorMessages = require('../helpers/error-messages') +const ConfigMapManager = require('../data/managers/config-map-manager') +const ConfigMapService = require('./config-map-service') +const VolumeMappingManager = require('../data/managers/volume-mapping-manager') +const MicroserviceManager = require('../data/managers/microservice-manager') +const MicroserviceCapAddManager = require('../data/managers/microservice-cap-add-manager') +const MicroserviceEnvManager = require('../data/managers/microservice-env-manager') +const MicroserviceHealthCheckManager = require('../data/managers/microservice-healthcheck-manager') +const MicroserviceStatusManager = require('../data/managers/microservice-status-manager') +const MicroserviceExecStatusManager = require('../data/managers/microservice-exec-status-manager') +const MicroservicePortManager = require('../data/managers/microservice-port-manager') +const VolumeMountService = require('./volume-mount-service') +const CatalogService = require('./catalog-service') +const CertificateService = require('./certificate-service') +const SecretService = require('./secret-service') +const NatsInstanceManager = require('../data/managers/nats-instance-manager') +const NatsConnectionManager = require('../data/managers/nats-connection-manager') +const NatsAccountManager = require('../data/managers/nats-account-manager') +const NatsReconcileTaskManager = require('../data/managers/nats-reconcile-task-manager') +const NatsUserManager = require('../data/managers/nats-user-manager') +const ApplicationManager = require('../data/managers/application-manager') +const NatsAuthService = require('./nats-auth-service') +const ChangeTrackingService = require('./change-tracking-service') +const FogManager = require('../data/managers/iofog-manager') +const databaseProvider = require('../data/providers/database-factory') +const config = require('../config') +const Constants = require('../helpers/constants') +const { ensureSystemApplication, getSystemMicroserviceName, slugifyName } = require('../helpers/system-naming') +const TransactionDecorator = require('../decorators/transaction-decorator') +const logger = require('../logger') +const K8sClient = require('../utils/k8s-client') +const { Op } = require('sequelize') + +const NATS_SITE_CA = 'nats-site-ca' +const NATS_CONFIG_DIR = '/etc/nats/config' +const NATS_JWT_DIR = '/home/runner/nats/jwt' +const NATS_JWT_MOUNT_DIR = '/tmp/nats/jwt' +const NATS_CERTS_DIR = '/etc/nats/certs' +const NATS_CREDS_DIR = '/etc/nats/creds' + +const DEFAULT_SERVER_PORT = 4222 +const DEFAULT_CLUSTER_PORT = 6222 +const DEFAULT_LEAF_PORT = 7422 +const DEFAULT_MQTT_PORT = 8883 +const DEFAULT_HTTP_PORT = 8222 +let natsReconcileRunning = false +let natsReconcilePending = false +let natsReconcileScheduled = false + +const _fogToken = (fog) => slugifyName((fog && fog.name) || (fog && fog.uuid) || 'fog') +const natsLocalCaName = (fog) => `nats-local-ca-${_fogToken(fog)}` +const natsLocalMQTTCertName = (fog) => `nats-mqtt-server-${_fogToken(fog)}` +const natsServerCertName = (fog) => `nats-server-${_fogToken(fog)}` +const natsServerConfigMap = (fog) => `nats-server-conf-${_fogToken(fog)}` +const natsLeafConfigMap = (fog) => `nats-leaf-conf-${_fogToken(fog)}` +const natsConfigMapName = (fog) => `nats-server-conf-${_fogToken(fog)}` +const NATS_CONFIG_KEY = 'server.conf' +const natsLeafCredsConfigMap = (fog) => `nats-leaf-creds-${_fogToken(fog)}` +const natsJwtBundleConfigMap = (fog) => `nats-jwt-bundle-${_fogToken(fog)}` +const natsJwtDirMount = (fog) => `nats-jwt-dir-${_fogToken(fog)}` +const natsJetstreamKeySecretName = (fog) => `nats-jetstream-key-${_fogToken(fog)}` +const K8S_NATS_SERVER_CONFIG_MAP = 'iofog-nats-config' +const K8S_NATS_JWT_BUNDLE_CONFIG_MAP = 'iofog-nats-jwt-bundle' + +async function _getSysUserCredsSecretNameForFog (fog, isHub, transaction) { + const systemAccount = await NatsAccountManager.findOne({ isSystem: true }, transaction) + if (!systemAccount) return null + const sysUserName = NatsAuthService.sysUserNameForServer(isHub, fog) + const user = await NatsUserManager.findOne({ accountId: systemAccount.id, name: sysUserName }, transaction) + return user ? user.credsSecretName : null +} + +function _isKubernetesControlPlane () { + const controlPlane = process.env.CONTROL_PLANE || config.get('app.ControlPlane') + return controlPlane && String(controlPlane).toLowerCase() === 'kubernetes' +} + +const JETSTREAM_SIZE_PATTERN = /^(\d+)\s*(m|mb|g|gb|t|tb)?$/i +const DEFAULT_JS_STORAGE_SIZE = '10g' +const DEFAULT_JS_MEMORY_STORE_SIZE = '1g' + +function _normalizeJetstreamSize (value, defaultValue) { + if (value === undefined || value === null || String(value).trim() === '') { + return defaultValue + } + const s = String(value).trim() + const match = s.match(JETSTREAM_SIZE_PATTERN) + if (!match) { + throw new Errors.ValidationError(`Invalid JetStream size: ${value}. Use a number with optional unit: m, mb, g, gb, t, tb (case-insensitive).`) + } + const num = match[1] + const unit = (match[2] || 'g').toLowerCase() + return `${num}${unit}` +} + +const readTemplate = (fileName) => { + const filePath = path.join(__dirname, '..', 'templates', 'nats', fileName) + return fs.readFileSync(filePath, 'utf8') +} + +const renderTemplate = (template, variables) => { + return Object.entries(variables).reduce((output, [key, value]) => { + if (value === undefined || value === null) { + return output + } + return output.split(`$${key}`).join(String(value)) + }, template) +} + +/** + * Escapes double quotes in s for use inside a double-quoted NATS config value. + * Caller must wrap the result in quotes in the template (e.g. key: "$JETSTREAM_KEY") + * so values that look like numbers (e.g. base64) or contain special chars parse as strings. + */ +function _escapeConfString (s) { + if (s == null) return '' + return String(s).replace(/"/g, '\\"') +} + +/** + * Deterministic hash of ConfigMap-style data object (key-order independent). + * Used to skip ConfigMap update when content is unchanged. + */ +function _configMapDataHash (data) { + if (data == null || typeof data !== 'object') { + return crypto.createHash('sha256').update(String(data)).digest('hex') + } + const sortedKeys = Object.keys(data).sort() + const canonical = JSON.stringify(sortedKeys.map(k => ({ k, v: data[k] }))) + return crypto.createHash('sha256').update(canonical).digest('hex') +} + +async function _ensureConfigMap (name, data, transaction) { + const existing = await ConfigMapManager.getConfigMap(name, transaction) + if (existing) { + const existingHash = _configMapDataHash(existing.data) + const newHash = _configMapDataHash(data) + if (existingHash === newHash) { + return + } + return ConfigMapService.updateConfigMapEndpoint(name, { data, immutable: false }, transaction) + } + return ConfigMapService.createConfigMapEndpoint({ name, data, immutable: false, useVault: true }, transaction) +} + +async function _ensureVolumeMount (name, opts, transaction) { + try { + await VolumeMountService.getVolumeMountEndpoint(name, transaction) + } catch (err) { + if (err.name !== 'NotFoundError') { + throw err + } + await VolumeMountService.createVolumeMountEndpoint({ name, ...opts }, transaction) + } +} + +async function _ensureVolumeMapping (microserviceUuid, hostDestination, containerDestination, accessMode, type, transaction) { + const existing = await VolumeMappingManager.findOne({ + microserviceUuid, + hostDestination, + containerDestination, + type + }, transaction) + if (!existing) { + await VolumeMappingManager.create({ + microserviceUuid, + hostDestination, + containerDestination, + accessMode, + type + }, transaction) + return true + } + return false +} + +async function _replaceMicroserviceEnv (microserviceUuid, env, transaction) { + await MicroserviceEnvManager.delete({ microserviceUuid }, transaction) + for (const entry of env) { + await MicroserviceEnvManager.create({ + microserviceUuid, + key: entry.key, + value: entry.value, + valueFromSecret: entry.valueFromSecret, + valueFromConfigMap: entry.valueFromConfigMap + }, transaction) + } +} + +function _normalizePortSet (ports) { + const set = new Set([].concat(ports).map(p => Number(p)).filter(p => !Number.isNaN(p))) + return [...set].sort((a, b) => a - b) +} + +async function _ensureNatsPorts (microserviceUuid, ports, transaction, iofogUuid) { + const desired = _normalizePortSet(ports) + const existing = await MicroservicePortManager.findAll({ microserviceUuid }, transaction) + const current = _normalizePortSet((existing || []).map(p => p.portInternal != null ? p.portInternal : p.portExternal)) + const same = desired.length === current.length && desired.every((p, i) => p === current[i]) + if (same) { + return + } + for (const port of existing) { + await MicroservicePortManager.delete({ id: port.id }, transaction) + } + for (const port of desired) { + await MicroservicePortManager.create({ + microserviceUuid, + portInternal: port, + portExternal: port + }, transaction) + } + if (iofogUuid) { + await ChangeTrackingService.update(iofogUuid, ChangeTrackingService.events.microserviceList, transaction) + } +} + +async function _ensureNatsCertificates (fog, transaction) { + async function ensureCA (name, subject) { + try { + await CertificateService.getCAEndpoint(name, transaction) + } catch (err) { + if (err.name !== 'NotFoundError') { + throw err + } + await CertificateService.createCAEndpoint({ + name, + subject: subject, + expiration: 60, + type: 'self-signed' + }, transaction) + } + } + + async function ensureCert (name, subject, hosts, caName) { + try { + await CertificateService.getCertificateEndpoint(name, transaction) + } catch (err) { + if (err.name !== 'NotFoundError') { + throw err + } + await CertificateService.createCertificateEndpoint({ + name, + subject: subject, + hosts: hosts.join(','), + ca: { + type: 'direct', + secretName: caName + }, + expiration: 60 + }, transaction) + } + } + + await ensureCA(NATS_SITE_CA, NATS_SITE_CA) + await ensureCA(natsLocalCaName(fog), natsLocalCaName(fog)) + + const hosts = [fog.host, fog.ipAddress, fog.ipAddressExternal].filter(Boolean) + if (hosts.length === 0) { + hosts.push('localhost') + } + const serverCertName = natsServerCertName(fog) + const mqttCertName = natsLocalMQTTCertName(fog) + + await ensureCert(serverCertName, serverCertName, hosts, NATS_SITE_CA) + await ensureCert(mqttCertName, mqttCertName, hosts, natsLocalCaName(fog)) + + return { + serverCertName, + mqttCertName + } +} + +async function _buildJwtBundle (fog, forLeaf = false, transaction) { + const jwtBundle = {} + if (forLeaf) { + const leafSystemAccount = await NatsAuthService.ensureLeafSystemAccount(fog, transaction) + jwtBundle[`${leafSystemAccount.publicKey}.jwt`] = leafSystemAccount.jwt + const appIds = await _getLeafAppIds(fog, transaction) + for (const appId of appIds) { + const account = await NatsAuthService.ensureAccountForApplication(appId, transaction) + jwtBundle[`${account.publicKey}.jwt`] = account.jwt + } + } else { + await NatsAuthService.ensureSystemAccount(transaction) + const systemAccount = await NatsAccountManager.findOne({ isSystem: true }, transaction) + if (systemAccount) { + jwtBundle[`${systemAccount.publicKey}.jwt`] = systemAccount.jwt + } + const microservices = await MicroserviceManager.findAll({ iofogUuid: fog.uuid }, transaction) + const appIds = [...new Set(microservices.map(ms => ms.applicationId).filter(Boolean))] + for (const appId of appIds) { + const app = await ApplicationManager.findOne({ id: appId }, transaction) + if (!app || !app.natsAccess) continue + const account = await NatsAuthService.ensureAccountForApplication(appId, transaction) + jwtBundle[`${account.publicKey}.jwt`] = account.jwt + } + } + return jwtBundle +} + +async function _buildHubJwtBundle (transaction) { + const jwtBundle = {} + await NatsAuthService.ensureSystemAccount(transaction) + const systemAccount = await NatsAccountManager.findOne({ isSystem: true }, transaction) + if (systemAccount) { + jwtBundle[`${systemAccount.publicKey}.jwt`] = systemAccount.jwt + } + const applicationsWithNats = await ApplicationManager.findAll({ natsAccess: true }, transaction) + for (const app of applicationsWithNats || []) { + const account = await NatsAccountManager.findOne({ applicationId: app.id }, transaction) + if (account) { + jwtBundle[`${account.publicKey}.jwt`] = account.jwt + } + } + return jwtBundle +} + +async function _getLeafAppIds (fog, transaction) { + const microservices = await MicroserviceManager.findAll({ iofogUuid: fog.uuid }, transaction) + const appIds = [...new Set(microservices.map(ms => ms.applicationId).filter(Boolean))] + const nonSystemAppIds = [] + for (const appId of appIds) { + const app = await ApplicationManager.findOne({ id: appId }, transaction) + if (app && !app.isSystem && app.natsAccess) { + nonSystemAppIds.push(appId) + } + } + return nonSystemAppIds +} + +/** + * Build JWT bundle for a fog using preloaded maps (used inside reconcile to avoid per-fog DB). + * @param {object} fog + * @param {boolean} forLeaf + * @param {{ applicationsWithNatsById: Map, accountByAppId: Map, systemAccount: object|null, microservicesByFog: Map }} maps + * @param {object} transaction + */ +async function _buildJwtBundleFromMaps (fog, forLeaf, maps, transaction) { + const { applicationsWithNatsById, accountByAppId, systemAccount, microservicesByFog } = maps + const jwtBundle = {} + const fogMicroservices = microservicesByFog.get(fog.uuid) || [] + const appIds = [...new Set(fogMicroservices.map(ms => ms.applicationId).filter(Boolean))] + + if (forLeaf) { + const leafSystemAccount = await NatsAuthService.ensureLeafSystemAccount(fog, transaction) + jwtBundle[`${leafSystemAccount.publicKey}.jwt`] = leafSystemAccount.jwt + for (const appId of appIds) { + const app = applicationsWithNatsById.get(appId) + if (!app || app.isSystem || !app.natsAccess) continue + let account = accountByAppId.get(appId) + if (!account) { + account = await NatsAuthService.ensureAccountForApplication(appId, transaction) + } + jwtBundle[`${account.publicKey}.jwt`] = account.jwt + } + } else { + await NatsAuthService.ensureSystemAccount(transaction) + const sysAccount = systemAccount || await NatsAccountManager.findOne({ isSystem: true }, transaction) + if (sysAccount) { + jwtBundle[`${sysAccount.publicKey}.jwt`] = sysAccount.jwt + } + for (const appId of appIds) { + const app = applicationsWithNatsById.get(appId) + if (!app || !app.natsAccess) continue + let account = accountByAppId.get(appId) + if (!account) { + account = await NatsAuthService.ensureAccountForApplication(appId, transaction) + } + jwtBundle[`${account.publicKey}.jwt`] = account.jwt + } + } + return jwtBundle +} + +async function _buildLeafCredsConfigMap (fog, natsInstance, transaction) { + const upstreamConnections = await NatsConnectionManager.findAllWithNats( + { sourceNats: natsInstance.id }, + transaction + ) + if (!upstreamConnections || upstreamConnections.length === 0) { + return + } + + const appIds = await _getLeafAppIds(fog, transaction) + const credsData = {} + for (const appId of appIds) { + const account = await NatsAuthService.ensureAccountForApplication(appId, transaction) + const { user } = await NatsAuthService.ensureLeafUserForAccount(account.id, slugifyName(fog.name), transaction, fog.natsMicroserviceUuid || null) + try { + const secret = await SecretService.getSecretEndpoint(user.credsSecretName, transaction) + if (secret && secret.data) { + const credsKey = Object.keys(secret.data).find((k) => k.endsWith('.creds')) || `${slugifyName(account.name)}/${slugifyName(user.name)}.creds` + const content = secret.data[credsKey] + if (content) { + const value = typeof content === 'string' ? content : Buffer.from(content, 'base64').toString('utf8') + credsData[`${slugifyName(account.name)}/${slugifyName(user.name)}.creds`] = value + } + } + } catch (err) { + if (err.name !== 'NotFoundError') { + throw err + } + } + } + + const { account: leafSystemAccount, user: leafSystemUser } = await NatsAuthService.ensureLeafSystemAccountUser(fog, transaction) + try { + const secret = await SecretService.getSecretEndpoint(leafSystemUser.credsSecretName, transaction) + if (secret && secret.data) { + const credsKey = `${slugifyName(leafSystemAccount.name)}/${slugifyName(leafSystemUser.name)}.creds` + const content = secret.data[credsKey] + if (content) { + const value = typeof content === 'string' ? content : Buffer.from(content, 'base64').toString('utf8') + credsData[credsKey] = value + } + } + } catch (err) { + if (err.name !== 'NotFoundError') { + throw err + } + } + + if (Object.keys(credsData).length === 0) { + return + } + + const leafCredsMapName = natsLeafCredsConfigMap(fog) + const existing = await ConfigMapManager.getConfigMap(leafCredsMapName, transaction) + const credsDataUnchanged = existing && _configMapDataHash(existing.data) === _configMapDataHash(credsData) + if (!credsDataUnchanged) { + if (existing) { + await ConfigMapService.updateConfigMapEndpoint(leafCredsMapName, { data: credsData, immutable: false }, transaction) + } else { + await ConfigMapService.createConfigMapEndpoint({ name: leafCredsMapName, data: credsData, immutable: false, useVault: true }, transaction) + } + } + + await _ensureVolumeMount(leafCredsMapName, { configMapName: leafCredsMapName }, transaction) + await VolumeMountService.linkVolumeMountEndpoint(leafCredsMapName, [fog.uuid], transaction) + await _ensureVolumeMapping(fog.natsMicroserviceUuid, leafCredsMapName, NATS_CREDS_DIR, 'ro', 'volumeMount', transaction) +} + +async function _buildLeafRemotes (fog, natsInstance, transaction) { + await _buildLeafCredsConfigMap(fog, natsInstance, transaction) +} + +/** + * Ensures leaf user and creds configmap for a fog that has a NATS leaf instance. + * Call after creating or updating a microservice with natsAccess so the leaf gets creds for that app. + * Uses the same transaction so the new/updated microservice is visible to _getLeafAppIds. + */ +async function ensureLeafCredsForFog (fogUuid, transaction) { + const fog = await FogManager.findOne({ uuid: fogUuid }, transaction) + if (!fog) { + return + } + const natsInstance = await NatsInstanceManager.findByFog(fog.uuid, transaction) + if (!natsInstance) { + return + } + const natsMicroservice = await MicroserviceManager.findOne({ + iofogUuid: fog.uuid, + name: getSystemMicroserviceName('nats') + }, transaction) + if (natsMicroservice) { + fog.natsMicroserviceUuid = natsMicroservice.uuid + } + if (natsInstance.isLeaf) { + await _buildLeafRemotes(fog, natsInstance, transaction) + const jwtBundle = await _buildJwtBundle(fog, natsInstance.isLeaf, transaction) + await _ensureConfigMap(natsJwtBundleConfigMap(fog), jwtBundle, transaction) + } +} + +async function _computeLeafRemotesForInstance (fog, natsInstance, transaction, certName) { + const remotes = [] + const upstreamConnections = await NatsConnectionManager.findAllWithNats( + { sourceNats: natsInstance.id }, + transaction + ) + if (!upstreamConnections || upstreamConnections.length === 0) { + return remotes + } + const tlsConfig = certName ? { + ca_file: `${NATS_CERTS_DIR}/${certName}/ca.crt`, + cert_file: `${NATS_CERTS_DIR}/${certName}/tls.crt`, + key_file: `${NATS_CERTS_DIR}/${certName}/tls.key`, + verify: true, + handshake_first: true, + timeout: '3s' + } : undefined + const appIds = await _getLeafAppIds(fog, transaction) + for (const appId of appIds) { + const account = await NatsAuthService.ensureAccountForApplication(appId, transaction) + for (const upstream of upstreamConnections) { + if (!upstream.dest || !upstream.dest.host) { + continue + } + const port = upstream.dest.leafPort || DEFAULT_LEAF_PORT + const leafUserName = `leaf-${slugifyName(fog.name)}` + const remote = { + urls: [`tls://${upstream.dest.host}:${port}`], + account: account.publicKey, + credentials: `${NATS_CREDS_DIR}/${slugifyName(account.name)}/${slugifyName(leafUserName)}.creds` + } + if (tlsConfig) { + remote.tls = tlsConfig + } + remotes.push(remote) + } + } + return remotes +} + +// Routes matching this pattern are considered created by the K8s operator and are preserved when patching the hub ConfigMap. +const DEFAULT_OPERATOR_ROUTE_PATTERN = /nats-headless/ + +function _isOperatorRoute (route) { + if (typeof route !== 'string') return false + return DEFAULT_OPERATOR_ROUTE_PATTERN.test(route) +} + +function mergeK8sHubClusterRoutes (currentRoutes, desiredControllerRoutes) { + const operatorRoutes = (currentRoutes || []).filter(r => typeof r === 'string' && _isOperatorRoute(r)) + return [...operatorRoutes, ...(desiredControllerRoutes || [])] +} + +async function _getControllerManagedClusterRoutes (transaction) { + const allServerInstances = await NatsInstanceManager.findAll({ isLeaf: false }, transaction) + const routes = [] + for (const inst of allServerInstances || []) { + if (!inst.host || inst.iofogUuid == null) { + continue + } + routes.push(`nats://${inst.host}:${inst.clusterPort || DEFAULT_CLUSTER_PORT}`) + } + return routes +} + +async function _computeClusterRoutesForInstance (natsInstance, transaction) { + const allServerInstances = await NatsInstanceManager.findAll({ isLeaf: false }, transaction) + const routes = [] + for (const inst of allServerInstances || []) { + if (!inst.host) continue + routes.push(`nats://${inst.host}:${inst.clusterPort || DEFAULT_CLUSTER_PORT}`) + } + return routes +} + +async function _patchK8sHubConfigMapClusterRoutes (desiredControllerRoutes, transaction) { + const configMap = await K8sClient.getConfigMap(K8S_NATS_SERVER_CONFIG_MAP, { ignoreNotFound: true }) + if (!configMap || !configMap.data) { + logger.debug(`Hub ConfigMap ${K8S_NATS_SERVER_CONFIG_MAP} not found or empty (expected before operator creates it)`) + return + } + const configKey = NATS_CONFIG_KEY + const content = configMap.data[configKey] + if (!content) { + throw new Error(`Key ${configKey} not found in ConfigMap ${K8S_NATS_SERVER_CONFIG_MAP}`) + } + const routesMatch = content.match(/routes:\s*(\[[^\]]*\])/m) + if (!routesMatch) { + throw new Error(`Could not find routes in ${K8S_NATS_SERVER_CONFIG_MAP}`) + } + let currentRoutes + try { + currentRoutes = JSON.parse(routesMatch[1]) + } catch (e) { + throw new Error(`Invalid routes JSON in ${K8S_NATS_SERVER_CONFIG_MAP}: ${e.message}`) + } + if (!Array.isArray(currentRoutes)) { + currentRoutes = [] + } + const newRoutes = mergeK8sHubClusterRoutes(currentRoutes, desiredControllerRoutes) + const newRoutesJson = JSON.stringify(newRoutes) + const newContent = content.replace(/routes:\s*\[[^\]]*\]/m, `routes: ${newRoutesJson}`) + await K8sClient.patchConfigMap(K8S_NATS_SERVER_CONFIG_MAP, { data: { [configKey]: newContent } }, { ignoreNotFound: true }) +} + +function _clusterConfigRequiresRebuild (oldRoutes, newRoutes) { + const oldLen = (oldRoutes && oldRoutes.length) || 0 + const newLen = (newRoutes && newRoutes.length) || 0 + if (oldLen === 0 && newLen > 0) { + return true + } + if (oldLen > 0 && newLen < oldLen) { + const oldSet = new Set(oldRoutes || []) + const everyNewInOld = (newRoutes || []).every(r => oldSet.has(r)) + return everyNewInOld + } + return false +} + +async function _renderAndPersistNatsConfig (fog, natsInstance, certName, mqttCertName, configMapName, configKey, template, isHub, isServerMode, transaction) { + const systemAccount = isServerMode + ? await NatsAuthService.ensureSystemAccount(transaction) + : await NatsAuthService.ensureLeafSystemAccount(fog, transaction) + const operator = await NatsAuthService.ensureOperator(transaction) + const clusterRoutes = (isHub || isServerMode) ? await _computeClusterRoutesForInstance(natsInstance, transaction) : [] + if ((isHub || isServerMode) && clusterRoutes.length === 1) { + template = readTemplate('server-no-cluster.conf') + } + const leafRemotes = isServerMode ? [] : await _computeLeafRemotesForInstance(fog, natsInstance, transaction, certName) + const jetstreamKey = await _ensureJetstreamKey(fog, transaction) + const jetstreamDomain = isHub || isServerMode + ? (process.env.CONTROLLER_NAMESPACE || config.get('app.namespace')) + : fog.name + const leafAdvertiseHose = fog.host || fog.ipAddress || fog.ipAddressExternal + const jsMaxMemory = _normalizeJetstreamSize(natsInstance.jsMemoryStoreSize, DEFAULT_JS_MEMORY_STORE_SIZE) + const jsMaxFile = _normalizeJetstreamSize(natsInstance.jsStorageSize, DEFAULT_JS_STORAGE_SIZE) + const variables = { + OPERATOR_JWT: operator ? operator.jwt : undefined, + SYSTEM_ACCOUNT: systemAccount.publicKey, + NATS_CLUSTER_ROUTES: JSON.stringify(clusterRoutes), + NATS_LEAF_REMOTES: JSON.stringify(leafRemotes), + CONTROLLER_NAME: (process.env.CONTROLLER_NAME || config.get('app.name')), + JETSTREAM_DOMAIN: jetstreamDomain, + JETSTREAM_KEY: _escapeConfString(jetstreamKey.jsk), + JETSTREAM_PREV_KEY: _escapeConfString(jetstreamKey.prevKey || ''), + NATS_SERVER_PORT: natsInstance.serverPort, + NATS_LEAF_PORT: natsInstance.leafPort, + NATS_LEAF_ADVERTISE: leafAdvertiseHose, + NATS_CLUSTER_PORT: natsInstance.clusterPort, + NATS_MQTT_PORT: natsInstance.mqttPort, + NATS_HTTP_PORT: natsInstance.httpPort, + NATS_SSL_DIR: NATS_CERTS_DIR, + NATS_CERT_NAME: certName, + NATS_MQTT_CERT_NAME: mqttCertName, + NATS_JWT_DIR: NATS_JWT_DIR, + NATS_JS_MAX_MEMORY_STORE: jsMaxMemory, + NATS_JS_MAX_FILE_STORE: jsMaxFile + } + const renderedTemplate = renderTemplate(template, variables) + await _ensureConfigMap(configMapName, { [configKey]: renderedTemplate }, transaction) + return renderedTemplate +} + +async function _ensureJetstreamKey (fog, transaction) { + const secretName = natsJetstreamKeySecretName(fog) + try { + const secret = await SecretService.getSecretEndpoint(secretName, transaction) + if (secret && secret.data && secret.data.jsk) { + return { secretName, jsk: secret.data.jsk } + } + } catch (error) { + if (error.name !== 'NotFoundError') { + throw error + } + } + + const key = crypto.randomBytes(32).toString('base64') + await SecretService.createSecretEndpoint({ + name: secretName, + type: 'Opaque', + data: { jsk: key } + }, transaction) + return { secretName, jsk: key } +} + +async function _validateAndReturnUpstreamNats (upstreamNatsIds, isSystemFog, defaultHub, transaction) { + if (!upstreamNatsIds) { + if (!defaultHub) { + if (isSystemFog) { + return [] + } + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_NATS, Constants.DEFAULT_NATS_HUB_NAME)) + } + + const allSystemFogs = await FogManager.findAll({ isSystem: true }, transaction) + const systemFogNats = [] + for (const systemFog of allSystemFogs) { + const systemFogNatsInstance = await NatsInstanceManager.findOne({ + iofogUuid: systemFog.uuid + }, transaction) + if (systemFogNatsInstance) { + systemFogNats.push(systemFogNatsInstance) + } + } + + const combinedNats = [defaultHub] + for (const systemFogNatsInstance of systemFogNats) { + if (systemFogNatsInstance.id !== defaultHub.id) { + combinedNats.push(systemFogNatsInstance) + } + } + + return combinedNats + } + + const upstreamNats = [] + for (const upstreamId of upstreamNatsIds) { + let upstreamNatsInstance = upstreamId === Constants.DEFAULT_NATS_HUB_NAME + ? defaultHub + : await NatsInstanceManager.findOne({ iofogUuid: upstreamId }, transaction) + if (!upstreamNatsInstance && upstreamId !== Constants.DEFAULT_NATS_HUB_NAME) { + const fog = await FogManager.findOne({ name: upstreamId }, transaction) + if (!fog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_NATS, upstreamId)) + } + upstreamNatsInstance = await NatsInstanceManager.findOne({ iofogUuid: fog.uuid }, transaction) + } + if (!upstreamNatsInstance) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_NATS, upstreamId)) + } + if (upstreamNatsInstance.isLeaf) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_UPSTREAM_NATS, upstreamId)) + } + upstreamNats.push(upstreamNatsInstance) + } + return upstreamNats +} + +async function _ensureNatsMicroservice (fog, mode, transaction) { + const application = await ensureSystemApplication(fog, transaction) + const name = getSystemMicroserviceName('nats') + let microservice = await MicroserviceManager.findOne({ + name, + applicationId: application.id + }, transaction) + + if (!microservice) { + const catalog = await CatalogService.getNatsCatalogItem(transaction) + if (!catalog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_CATALOG_ITEM_ID, 'NATs')) + } + const data = { + uuid: AppHelper.generateUUID(), + name: name, + config: '{}', + catalogItemId: catalog.id, + iofogUuid: fog.uuid, + hostNetworkMode: false, + isPrivileged: false, + logSize: 1, + schedule: 1, + configLastUpdated: Date.now(), + applicationId: application.id + } + const capAddValues = [ + { capAdd: 'NET_RAW' } + ] + microservice = await MicroserviceManager.create(data, transaction) + await MicroserviceStatusManager.create({ microserviceUuid: microservice.uuid }, transaction) + await MicroserviceExecStatusManager.create({ microserviceUuid: microservice.uuid }, transaction) + for (const capAdd of capAddValues) { + await MicroserviceCapAddManager.create({ + microserviceUuid: data.uuid, + capAdd: capAdd.capAdd + }, transaction) + } + const jetstreamMappingCreated = await _ensureVolumeMapping(microservice.uuid, `${fog.name}-nats-jetstream`, '/home/runner/data', 'rw', 'volume', transaction) + microservice._volumeMappingCreated = jetstreamMappingCreated + } + + fog.natsMicroserviceUuid = microservice.uuid + + const defaultHealthCheck = { + test: ['CMD-SHELL', "curl -f http://localhost:8222/healthz | grep -q 'status.*ok' || exit 1"], + interval: 30, + timeout: 10, + startPeriod: 60, + retries: 3 + } + const existingHealthCheck = await MicroserviceHealthCheckManager.findOne( + { microserviceUuid: microservice.uuid }, + transaction + ) + const healthCheckData = { + microserviceUuid: microservice.uuid, + test: JSON.stringify(defaultHealthCheck.test), + interval: defaultHealthCheck.interval, + timeout: defaultHealthCheck.timeout, + startPeriod: defaultHealthCheck.startPeriod, + retries: defaultHealthCheck.retries + } + if (existingHealthCheck) { + await MicroserviceHealthCheckManager.update( + { microserviceUuid: microservice.uuid }, + { + test: healthCheckData.test, + interval: healthCheckData.interval, + timeout: healthCheckData.timeout, + startPeriod: healthCheckData.startPeriod, + retries: healthCheckData.retries + }, + transaction + ) + } else { + await MicroserviceHealthCheckManager.create(healthCheckData, transaction) + } + + return microservice +} + +/** + * Removes leaf-only artifacts when a fog transitions from leaf to server: volume mappings, + * mount endpoints, leaf JWT bundle and leaf creds ConfigMaps, and DB leaf system account/user. + * Call only when instance was leaf and is now server. + */ +async function _removeLeafOnlyArtifactsForFog (fog, microservice, transaction) { + const leafArtifacts = await NatsAuthService.getLeafSystemArtifactSecretNames(fog, transaction) + const mountNamesToRemove = [ + natsJwtBundleConfigMap(fog), + natsLeafCredsConfigMap(fog) + ] + if (leafArtifacts && leafArtifacts.credsSecretName) { + mountNamesToRemove.push(leafArtifacts.credsSecretName) + } + for (const mountName of mountNamesToRemove) { + await VolumeMappingManager.delete({ + microserviceUuid: microservice.uuid, + hostDestination: mountName, + type: 'volumeMount' + }, transaction) + try { + await VolumeMountService.unlinkVolumeMountEndpoint(mountName, [fog.uuid], transaction) + } catch (error) { + if (error.name !== 'NotFoundError') throw error + } + try { + const linkedFogs = await VolumeMountService.findVolumeMountedFogNodes(mountName, transaction) + if (!linkedFogs || linkedFogs.length === 0) { + await VolumeMountService.deleteVolumeMountEndpoint(mountName, transaction) + } + } catch (error) { + if (error.name !== 'NotFoundError') throw error + } + } + for (const configMapName of [natsJwtBundleConfigMap(fog), natsLeafCredsConfigMap(fog)]) { + try { + await ConfigMapService.deleteConfigMapEndpoint(configMapName, transaction) + } catch (error) { + if (error.name !== 'NotFoundError') throw error + } + } + await NatsAuthService.deleteLeafSystemArtifactsForFog(fog, transaction) +} + +async function ensureNatsForFog (fog, natsConfig, transaction) { + const mode = (natsConfig && natsConfig.mode) || 'leaf' + if (mode === 'none') { + return null + } + + const existingHub = await NatsInstanceManager.findOne({ isHub: true }, transaction) + let isHub + let isLeaf + if (_isKubernetesControlPlane()) { + isHub = false + isLeaf = (mode === 'leaf') + } else { + isHub = (existingHub && existingHub.iofogUuid === fog.uuid) || (!existingHub && fog.isSystem === true && mode === 'server') + isLeaf = (mode === 'leaf') + } + + const serverPort = (natsConfig && natsConfig.serverPort) || DEFAULT_SERVER_PORT + const leafPort = (natsConfig && natsConfig.leafPort) || DEFAULT_LEAF_PORT + const clusterPort = (natsConfig && natsConfig.clusterPort) || DEFAULT_CLUSTER_PORT + const mqttPort = (natsConfig && natsConfig.mqttPort) || DEFAULT_MQTT_PORT + const httpPort = (natsConfig && natsConfig.httpPort) || DEFAULT_HTTP_PORT + + const { serverCertName, mqttCertName } = await _ensureNatsCertificates(fog, transaction) + const configMapName = natsConfigMapName(fog) + const configKey = NATS_CONFIG_KEY + const template = !isLeaf ? readTemplate('server.conf') : readTemplate('leaf.conf') + const certName = serverCertName + + const jwtBundleConfigMapName = isLeaf ? natsJwtBundleConfigMap(fog) : K8S_NATS_JWT_BUNDLE_CONFIG_MAP + if (isLeaf) { + const jwtBundle = await _buildJwtBundle(fog, true, transaction) + await _ensureConfigMap(natsJwtBundleConfigMap(fog), jwtBundle, transaction) + } else { + const fullJwtBundle = await _buildHubJwtBundle(transaction) + await _ensureConfigMap(K8S_NATS_JWT_BUNDLE_CONFIG_MAP, fullJwtBundle, transaction) + } + + const microserviceResult = await _ensureNatsMicroservice(fog, mode, transaction) + const microservice = microserviceResult + let anyVolumeMappingCreated = !!(microservice && microservice._volumeMappingCreated) + + const jetstreamKey = await _ensureJetstreamKey(fog, transaction) + const sysAccountName = isLeaf ? NatsAuthService.leafSystemAccountName(fog) : NatsAuthService.SYSTEM_ACCOUNT_NAME + const sysUserName = isLeaf ? NatsAuthService.leafSystemAccountUserName(fog) : NatsAuthService.sysUserNameForServer(isHub, fog) + const sysCredPath = `${NATS_CREDS_DIR}/${slugifyName(sysAccountName)}/${slugifyName(sysUserName)}.creds` + const env = [ + { key: 'JETSTREAM_KEY', value: jetstreamKey.jsk, valueFromSecret: `${jetstreamKey.secretName}/jsk` }, + { key: 'JETSTREAM_PREV_KEY', value: '' }, + { key: 'NATS_JWT_DIR', value: NATS_JWT_DIR }, + { key: 'NATS_JWT_MOUNT_DIR', value: NATS_JWT_MOUNT_DIR }, + { key: 'NATS_CREDS_DIR', value: NATS_CREDS_DIR }, + { key: 'NATS_SYS_USER_CRED_PATH', value: sysCredPath }, + { key: 'NATS_SSL_DIR', value: NATS_CERTS_DIR }, + { key: 'NATS_CERT_NAME', value: certName }, + { key: 'NATS_MQTT_CERT_NAME', value: mqttCertName }, + { key: 'NATS_CONF', value: `${NATS_CONFIG_DIR}/${configKey}` }, + { key: 'NATS_SERVER_PORT', value: String(serverPort) }, + { key: 'NATS_LEAF_PORT', value: String(leafPort) }, + { key: 'NATS_CLUSTER_PORT', value: String(clusterPort) }, + { key: 'NATS_MQTT_PORT', value: String(mqttPort) }, + { key: 'NATS_HTTP_PORT', value: String(httpPort) }, + { key: 'NATS_MONITOR_PORT', value: String(httpPort) }, + { key: 'NATS_JETSTREAM_STORE_DIR', value: '/home/runner/data' }, + { key: 'NATS_SERVER_MODE', value: `${mode}` } + ] + + const instance = await NatsInstanceManager.findByFog(fog.uuid, transaction) + let oldRoutesByInstanceId = null + let oldRoutesForCurrent = [] + if (!isLeaf) { + const allServerInstances = await NatsInstanceManager.findAll({ isLeaf: false }, transaction) + oldRoutesByInstanceId = new Map() + for (const inst of allServerInstances || []) { + oldRoutesByInstanceId.set(inst.id, await _computeClusterRoutesForInstance(inst, transaction)) + } + oldRoutesForCurrent = instance ? (oldRoutesByInstanceId.get(instance.id) || []) : [] + } + const jsStorageSizeRaw = (natsConfig && natsConfig.jsStorageSize) != null ? String(natsConfig.jsStorageSize).trim() : null + const jsMemoryStoreSizeRaw = (natsConfig && natsConfig.jsMemoryStoreSize) != null ? String(natsConfig.jsMemoryStoreSize).trim() : null + if (jsStorageSizeRaw !== undefined && jsStorageSizeRaw !== null && jsStorageSizeRaw !== '') { + _normalizeJetstreamSize(jsStorageSizeRaw, DEFAULT_JS_STORAGE_SIZE) + } + if (jsMemoryStoreSizeRaw !== undefined && jsMemoryStoreSizeRaw !== null && jsMemoryStoreSizeRaw !== '') { + _normalizeJetstreamSize(jsMemoryStoreSizeRaw, DEFAULT_JS_MEMORY_STORE_SIZE) + } + const jsStorageSize = (jsStorageSizeRaw !== undefined && jsStorageSizeRaw !== null && jsStorageSizeRaw !== '') + ? jsStorageSizeRaw + : (instance && (instance.jsStorageSize != null && instance.jsStorageSize !== '')) ? instance.jsStorageSize : DEFAULT_JS_STORAGE_SIZE + const jsMemoryStoreSize = (jsMemoryStoreSizeRaw !== undefined && jsMemoryStoreSizeRaw !== null && jsMemoryStoreSizeRaw !== '') + ? jsMemoryStoreSizeRaw + : (instance && (instance.jsMemoryStoreSize != null && instance.jsMemoryStoreSize !== '')) ? instance.jsMemoryStoreSize : DEFAULT_JS_MEMORY_STORE_SIZE + const instanceData = { + iofogUuid: fog.uuid, + isLeaf, + isHub, + host: fog.host, + serverPort, + leafPort, + clusterPort, + mqttPort, + httpPort, + configMapName: configMapName, + jwtDirMountName: natsJwtDirMount(fog), + certSecretName: certName, + jsStorageSize: jsStorageSize || DEFAULT_JS_STORAGE_SIZE, + jsMemoryStoreSize: jsMemoryStoreSize || DEFAULT_JS_MEMORY_STORE_SIZE + } + let savedInstance = instance + if (savedInstance) { + await NatsInstanceManager.update({ id: savedInstance.id }, instanceData, transaction) + savedInstance = await NatsInstanceManager.findOne({ id: savedInstance.id }, transaction) + } else { + savedInstance = await NatsInstanceManager.create(instanceData, transaction) + } + + if (instance && instance.isLeaf && !savedInstance.isLeaf && microservice) { + await _removeLeafOnlyArtifactsForFog(fog, microservice, transaction) + } + + let upstreamIds = natsConfig && natsConfig.upstreamNatsServers + if (typeof upstreamIds === 'string') { + try { + upstreamIds = JSON.parse(upstreamIds) + } catch (error) { + upstreamIds = [] + } + } + const defaultHub = await NatsInstanceManager.findOne({ isHub: true }, transaction) + const upstreamNats = await _validateAndReturnUpstreamNats(upstreamIds, fog.isSystem === true, defaultHub, transaction) + + const existingConnections = await NatsConnectionManager.findAllWithNats( + { sourceNats: savedInstance.id }, + transaction + ) + const existingDestIds = new Set(existingConnections.map(conn => conn.dest && conn.dest.id).filter(Boolean)) + const desiredDestIds = new Set(upstreamNats.map(node => node.id)) + for (const connection of existingConnections) { + if (connection.dest && !desiredDestIds.has(connection.dest.id)) { + await NatsConnectionManager.delete({ id: connection.id }, transaction) + } + } + for (const upstream of upstreamNats) { + if (!existingDestIds.has(upstream.id)) { + await NatsConnectionManager.create({ sourceNats: savedInstance.id, destNats: upstream.id }, transaction) + } + } + + await _renderAndPersistNatsConfig( + fog, + savedInstance, + certName, + mqttCertName, + configMapName, + configKey, + template, + isHub, + !savedInstance.isLeaf, + transaction + ) + + if (_isKubernetesControlPlane() && !savedInstance.isLeaf && savedInstance.host) { + try { + const desiredControllerRoutes = await _getControllerManagedClusterRoutes(transaction) + await _patchK8sHubConfigMapClusterRoutes(desiredControllerRoutes, transaction) + } catch (err) { + logger.warn(`Failed to patch Kubernetes NATS hub ConfigMap cluster routes: ${err.message}`) + } + } + + if (!savedInstance.isLeaf) { + const newRoutesForCurrent = await _computeClusterRoutesForInstance(savedInstance, transaction) + if (_clusterConfigRequiresRebuild(oldRoutesForCurrent, newRoutesForCurrent)) { + const natsMicroservice = await MicroserviceManager.findOne({ iofogUuid: fog.uuid, name: getSystemMicroserviceName('nats') }, transaction) + if (natsMicroservice) { + await MicroserviceManager.update({ uuid: natsMicroservice.uuid }, { rebuild: true }, transaction) + await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.microserviceList, transaction) + } + } + const allServerInstancesNow = await NatsInstanceManager.findAll({ isLeaf: false }, transaction) + const otherInstances = (allServerInstancesNow || []).filter(i => i.id !== savedInstance.id) + if (otherInstances.length > 0) { + const otherFogUuids = otherInstances.map((i) => i.iofogUuid).filter(Boolean) + await enqueueReconcileTask({ reason: 'cluster-routes-changed', fogUuids: otherFogUuids }, transaction) + } + } + + await _ensureVolumeMount(configMapName, { configMapName: configMapName }, transaction) + await _ensureVolumeMount(natsJwtDirMount(fog), { configMapName: jwtBundleConfigMapName }, transaction) + await _ensureVolumeMount(certName, { secretName: certName }, transaction) + await _ensureVolumeMount(mqttCertName, { secretName: mqttCertName }, transaction) + + await VolumeMountService.linkVolumeMountEndpoint(configMapName, [fog.uuid], transaction) + await VolumeMountService.linkVolumeMountEndpoint(natsJwtDirMount(fog), [fog.uuid], transaction) + await VolumeMountService.linkVolumeMountEndpoint(certName, [fog.uuid], transaction) + await VolumeMountService.linkVolumeMountEndpoint(mqttCertName, [fog.uuid], transaction) + + anyVolumeMappingCreated = (await _ensureVolumeMapping(microservice.uuid, configMapName, NATS_CONFIG_DIR, 'ro', 'volumeMount', transaction)) || anyVolumeMappingCreated + anyVolumeMappingCreated = (await _ensureVolumeMapping(microservice.uuid, natsJwtDirMount(fog), NATS_JWT_MOUNT_DIR, 'rw', 'volumeMount', transaction)) || anyVolumeMappingCreated + anyVolumeMappingCreated = (await _ensureVolumeMapping(microservice.uuid, certName, `${NATS_CERTS_DIR}/${certName}`, 'ro', 'volumeMount', transaction)) || anyVolumeMappingCreated + anyVolumeMappingCreated = (await _ensureVolumeMapping(microservice.uuid, mqttCertName, `${NATS_CERTS_DIR}/${mqttCertName}`, 'ro', 'volumeMount', transaction)) || anyVolumeMappingCreated + + if (isHub) { + const { user: hubSysUser } = await NatsAuthService.ensureSysUserForServer({ isHub: true }, transaction) + const credsSecretName = hubSysUser.credsSecretName + await _ensureVolumeMount(credsSecretName, { secretName: credsSecretName }, transaction) + await VolumeMountService.linkVolumeMountEndpoint(credsSecretName, [fog.uuid], transaction) + anyVolumeMappingCreated = (await _ensureVolumeMapping(microservice.uuid, credsSecretName, NATS_CREDS_DIR, 'ro', 'volumeMount', transaction)) || anyVolumeMappingCreated + } else if (!savedInstance.isLeaf) { + const { user: serverSysUser } = await NatsAuthService.ensureSysUserForServer({ isHub: false, fog }, transaction) + const credsSecretName = serverSysUser.credsSecretName + await _ensureVolumeMount(credsSecretName, { secretName: credsSecretName }, transaction) + await VolumeMountService.linkVolumeMountEndpoint(credsSecretName, [fog.uuid], transaction) + anyVolumeMappingCreated = (await _ensureVolumeMapping(microservice.uuid, credsSecretName, NATS_CREDS_DIR, 'ro', 'volumeMount', transaction)) || anyVolumeMappingCreated + } else { + const sysCredsSecretName = await _getSysUserCredsSecretNameForFog(fog, false, transaction) + if (sysCredsSecretName) { + await VolumeMappingManager.delete({ + microserviceUuid: microservice.uuid, + hostDestination: sysCredsSecretName, + type: 'volumeMount' + }, transaction) + try { + await VolumeMountService.unlinkVolumeMountEndpoint(sysCredsSecretName, [fog.uuid], transaction) + } catch (err) { + if (err.name !== 'NotFoundError') { + throw err + } + } + } + await _buildLeafRemotes(fog, savedInstance, transaction) + } + + await _replaceMicroserviceEnv(microservice.uuid, env, transaction) + await _ensureNatsPorts(microservice.uuid, [serverPort, clusterPort, leafPort, mqttPort, httpPort], transaction, fog.uuid) + + if (anyVolumeMappingCreated) { + await MicroserviceManager.update({ uuid: microservice.uuid }, { rebuild: true }, transaction) + } + await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.microserviceList, transaction) + + return microservice +} + +async function cleanupNatsForFog (fog, transaction) { + const natsInstance = await NatsInstanceManager.findByFog(fog.uuid, transaction) + const mountNames = [ + natsConfigMapName(fog), + natsJwtDirMount(fog), + natsLeafCredsConfigMap(fog), + natsServerCertName(fog), + natsLocalMQTTCertName(fog) + ] + let sysCredsSecretName = null + if (natsInstance && !natsInstance.isLeaf) { + sysCredsSecretName = await _getSysUserCredsSecretNameForFog(fog, !!natsInstance.isHub, transaction) + if (sysCredsSecretName) { + mountNames.push(sysCredsSecretName) + } + } + const configMapNames = [ + natsConfigMapName(fog), + ...(natsInstance && natsInstance.isLeaf ? [natsJwtBundleConfigMap(fog)] : []), + natsLeafCredsConfigMap(fog), + natsServerConfigMap(fog), + natsLeafConfigMap(fog) + ] + const secretNames = [ + natsServerCertName(fog), + natsLocalMQTTCertName(fog), + natsJetstreamKeySecretName(fog), + natsLocalCaName(fog) + ] + if (sysCredsSecretName) { + secretNames.push(sysCredsSecretName) + } + if (natsInstance && natsInstance.isLeaf) { + const leafArtifacts = await NatsAuthService.getLeafSystemArtifactSecretNames(fog, transaction) + if (leafArtifacts) { + if (leafArtifacts.credsSecretName) { + mountNames.push(leafArtifacts.credsSecretName) + secretNames.push(leafArtifacts.credsSecretName) + } + if (leafArtifacts.seedSecretName) { + secretNames.push(leafArtifacts.seedSecretName) + } + } + } + + logger.info(`Cleaning up NATS artifacts for fog ${fog.uuid}`) + const wasLeaf = !!(natsInstance && natsInstance.isLeaf) + const wasServer = !!(natsInstance && !natsInstance.isLeaf) + const wasHub = !!(natsInstance && natsInstance.isHub) + if (natsInstance) { + await NatsConnectionManager.delete({ sourceNats: natsInstance.id }, transaction) + await NatsConnectionManager.delete({ destNats: natsInstance.id }, transaction) + await NatsInstanceManager.delete({ id: natsInstance.id }, transaction) + if (_isKubernetesControlPlane() && !natsInstance.isLeaf) { + try { + const desiredControllerRoutes = await _getControllerManagedClusterRoutes(transaction) + await _patchK8sHubConfigMapClusterRoutes(desiredControllerRoutes, transaction) + try { + await K8sClient.rolloutStatefulSet('nats') + } catch (rolloutErr) { + logger.warn(`Failed to rollout NATS StatefulSet after hub ConfigMap patch: ${rolloutErr.message}`) + } + } catch (err) { + logger.warn(`Failed to patch Kubernetes NATS hub ConfigMap cluster routes after cleanup: ${err.message}`) + } + } + if (!natsInstance.isLeaf) { + const remainingServers = await NatsInstanceManager.findAll({ isLeaf: false }, transaction) + if (remainingServers && remainingServers.length > 0) { + const remainingFogUuids = remainingServers.map((s) => s.iofogUuid).filter(Boolean) + await enqueueReconcileTask({ reason: 'server-deleted', fogUuids: remainingFogUuids }, transaction) + } + } + } + + const fogMicroservices = await MicroserviceManager.findAll({ iofogUuid: fog.uuid }, transaction) + for (const microservice of fogMicroservices) { + for (const mountName of mountNames) { + await VolumeMappingManager.delete({ + microserviceUuid: microservice.uuid, + hostDestination: mountName, + type: 'volumeMount' + }, transaction) + } + } + + for (const mountName of mountNames) { + try { + await VolumeMountService.unlinkVolumeMountEndpoint(mountName, [fog.uuid], transaction) + } catch (error) { + if (error.name !== 'NotFoundError') { + throw error + } + } + + try { + const linkedFogs = await VolumeMountService.findVolumeMountedFogNodes(mountName, transaction) + if (!linkedFogs || linkedFogs.length === 0) { + await VolumeMountService.deleteVolumeMountEndpoint(mountName, transaction) + } + } catch (error) { + if (error.name !== 'NotFoundError') { + throw error + } + } + } + + for (const configMapName of configMapNames) { + try { + await ConfigMapService.deleteConfigMapEndpoint(configMapName, transaction) + } catch (error) { + if (error.name !== 'NotFoundError') { + throw error + } + } + } + + for (const secretName of secretNames) { + try { + await SecretService.deleteSecretEndpoint(secretName, transaction) + } catch (error) { + if (error.name !== 'NotFoundError') { + throw error + } + } + } + + if (wasLeaf) { + await NatsAuthService.deleteLeafSystemArtifactsForFog(fog, transaction) + } + if (wasServer) { + await NatsAuthService.deleteServerSysUserForFog(fog, wasHub, transaction) + } +} + +function _getAffectedFogUuidsForApplication (applicationId, natsInstanceByFog, microservicesByFog) { + const out = new Set() + for (const [fogUuid, ni] of natsInstanceByFog) { + if (!ni.isLeaf) out.add(fogUuid) + } + for (const [fogUuid, msList] of microservicesByFog) { + if (msList.some(ms => ms.applicationId === applicationId)) out.add(fogUuid) + } + return out +} + +function _getAffectedFogUuidsForAccountRule (accountRuleId, natsInstanceByFog, microservicesByFog, applicationsWithNatsById) { + const appIds = [] + for (const [appId, app] of applicationsWithNatsById) { + if (app.natsRuleId === accountRuleId) appIds.push(appId) + } + const out = new Set() + for (const [fogUuid, ni] of natsInstanceByFog) { + if (!ni.isLeaf) out.add(fogUuid) + } + for (const [fogUuid, msList] of microservicesByFog) { + if (msList.some(ms => appIds.includes(ms.applicationId))) out.add(fogUuid) + } + return out +} + +async function _getAffectedFogUuidsForUserRule (userRuleId, natsInstanceByFog, transaction) { + const out = new Set() + for (const [fogUuid, ni] of natsInstanceByFog) { + if (!ni.isLeaf) out.add(fogUuid) + } + const microservicesWithRule = await MicroserviceManager.findAll({ natsRuleId: userRuleId }, transaction) + for (const ms of microservicesWithRule || []) { + if (ms.iofogUuid) out.add(ms.iofogUuid) + } + const natsUserEntity = NatsUserManager.getEntity() + if (natsUserEntity.rawAttributes && natsUserEntity.rawAttributes.natsUserRuleId) { + const usersWithRule = await NatsUserManager.findAll({ natsUserRuleId: userRuleId }, transaction) + for (const u of usersWithRule || []) { + if (u.microserviceUuid) { + const ms = await MicroserviceManager.findOne({ uuid: u.microserviceUuid }, transaction) + if (ms && ms.iofogUuid) out.add(ms.iofogUuid) + } + } + } + return out +} + +async function _reconcileResolverArtifactsOnce (options = {}, transaction) { + const NatsAuthServiceRuntime = require('./nats-auth-service') + + const fogs = await FogManager.findAll({}, transaction) + const applicationsWithNats = await ApplicationManager.findAll({ natsAccess: true }, transaction) + const appIdsFromNatsApps = (applicationsWithNats || []).map((a) => a.id) + const applicationsWithNatsById = new Map((applicationsWithNats || []).map((a) => [a.id, a])) + + const natsInstances = await NatsInstanceManager.findAll({}, transaction) + const natsInstanceByFog = new Map() + for (const ni of natsInstances || []) { + if (ni.iofogUuid) { + natsInstanceByFog.set(ni.iofogUuid, ni) + } + } + + const microservices = appIdsFromNatsApps.length > 0 + ? await MicroserviceManager.findAll({ applicationId: { [Op.in]: appIdsFromNatsApps } }, transaction) + : [] + const microservicesByFog = new Map() + for (const ms of microservices) { + if (ms.iofogUuid) { + if (!microservicesByFog.has(ms.iofogUuid)) { + microservicesByFog.set(ms.iofogUuid, []) + } + microservicesByFog.get(ms.iofogUuid).push(ms) + } + } + + let candidateFogs + const fogFilter = Array.isArray(options.fogUuids) && options.fogUuids.length > 0 ? new Set(options.fogUuids) : null + const reason = options.reason || 'auth-mutation' + if (fogFilter) { + candidateFogs = fogs.filter((fog) => fogFilter.has(fog.uuid)) + } else if ((reason === 'account-created' || reason === 'account-deleted') && options.applicationId != null) { + const affected = _getAffectedFogUuidsForApplication(options.applicationId, natsInstanceByFog, microservicesByFog) + candidateFogs = fogs.filter((f) => affected.has(f.uuid)) + } else if (reason === 'account-rule-updated' && options.accountRuleId != null) { + const affected = _getAffectedFogUuidsForAccountRule(options.accountRuleId, natsInstanceByFog, microservicesByFog, applicationsWithNatsById) + candidateFogs = fogs.filter((f) => affected.has(f.uuid)) + } else if (reason === 'user-rule-updated' && options.userRuleId != null) { + const affected = await _getAffectedFogUuidsForUserRule(options.userRuleId, natsInstanceByFog, transaction) + candidateFogs = fogs.filter((f) => affected.has(f.uuid)) + } else if (reason === 'system-account-created') { + candidateFogs = fogs.filter((f) => { + const ni = natsInstanceByFog.get(f.uuid) + return ni && !ni.isLeaf + }) + } else { + candidateFogs = fogs + } + logger.info(`Reconciling NATS resolver artifacts for ${candidateFogs.length} fog(s)`) + + const skipReissueForAccountDeleted = (reason === 'account-deleted') + const candidateFogUuids = candidateFogs.map((f) => f.uuid) + + const natsAccounts = appIdsFromNatsApps.length > 0 + ? await NatsAccountManager.findAll({ applicationId: { [Op.in]: appIdsFromNatsApps } }, transaction) + : [] + const accountByAppId = new Map((natsAccounts || []).map((a) => [a.applicationId, a])) + + const reconcileTriggerOptions = { triggerReconcile: false } + await NatsAuthServiceRuntime.ensureSystemAccount(transaction, reconcileTriggerOptions) + const systemAccount = await NatsAccountManager.findOne({ isSystem: true }, transaction) + + const systemNatsMicroservices = candidateFogUuids.length > 0 + ? await MicroserviceManager.findAll({ + name: getSystemMicroserviceName('nats'), + iofogUuid: { [Op.in]: candidateFogUuids } + }, transaction) + : [] + const systemNatsMicroserviceByFog = new Map((systemNatsMicroservices || []).map((m) => [m.iofogUuid, m])) + + const maps = { + applicationsWithNatsById, + accountByAppId, + systemAccount, + microservicesByFog + } + + const fullServerJwtBundle = await _buildHubJwtBundle(transaction) + await _ensureConfigMap(K8S_NATS_JWT_BUNDLE_CONFIG_MAP, fullServerJwtBundle, transaction) + + for (const fog of candidateFogs) { + const natsMicroservice = systemNatsMicroserviceByFog.get(fog.uuid) + if (natsMicroservice) { + fog.natsMicroserviceUuid = natsMicroservice.uuid + } + + const fogMicroservices = microservicesByFog.get(fog.uuid) || [] + if (!skipReissueForAccountDeleted) { + for (const microservice of fogMicroservices) { + if (!microservice.natsAccess || !microservice.applicationId) continue + const app = applicationsWithNatsById.get(microservice.applicationId) + if (!app || !app.natsAccess) continue + await NatsAuthServiceRuntime.reissueUserForMicroservice(microservice.uuid, transaction, reconcileTriggerOptions) + } + } + + const natsInstance = natsInstanceByFog.get(fog.uuid) + if (!natsInstance) { + continue + } + try { + const isHub = !!natsInstance.isHub + const isServerMode = !natsInstance.isLeaf + if (natsInstance.isLeaf) { + const leafJwtBundle = await _buildJwtBundleFromMaps(fog, true, maps, transaction) + await _ensureConfigMap(natsJwtBundleConfigMap(fog), leafJwtBundle, transaction) + } else { + await _ensureVolumeMount(natsJwtDirMount(fog), { configMapName: K8S_NATS_JWT_BUNDLE_CONFIG_MAP }, transaction) + await VolumeMountService.linkVolumeMountEndpoint(natsJwtDirMount(fog), [fog.uuid], transaction) + if (fog.natsMicroserviceUuid) { + await _ensureVolumeMapping(fog.natsMicroserviceUuid, natsJwtDirMount(fog), NATS_JWT_MOUNT_DIR, 'rw', 'volumeMount', transaction) + } + } + if (natsInstance.isLeaf && fog.natsMicroserviceUuid) { + await _buildLeafRemotes(fog, natsInstance, transaction) + } + + const certName = natsInstance.certSecretName || natsServerCertName(fog) + const mqttCertName = natsLocalMQTTCertName(fog) + const configMapName = natsInstance.configMapName || natsConfigMapName(fog) + const configKey = NATS_CONFIG_KEY + const template = isServerMode ? readTemplate('server.conf') : readTemplate('leaf.conf') + await _renderAndPersistNatsConfig( + fog, + natsInstance, + certName, + mqttCertName, + configMapName, + configKey, + template, + isHub, + isServerMode, + transaction + ) + if (isServerMode && (reason === 'server-deleted' || reason === 'cluster-routes-changed') && fog.natsMicroserviceUuid) { + await MicroserviceManager.update({ uuid: fog.natsMicroserviceUuid }, { rebuild: true }, transaction) + await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.microserviceList, transaction) + } + if (isHub && fog.natsMicroserviceUuid) { + const { user: hubSysUser } = await NatsAuthServiceRuntime.ensureSysUserForServer({ isHub: true }, transaction) + const credsSecretName = hubSysUser.credsSecretName + await _ensureVolumeMount(credsSecretName, { secretName: credsSecretName }, transaction) + await VolumeMountService.linkVolumeMountEndpoint(credsSecretName, [fog.uuid], transaction) + await _ensureVolumeMapping(fog.natsMicroserviceUuid, credsSecretName, NATS_CREDS_DIR, 'ro', 'volumeMount', transaction) + } + } catch (error) { + logger.error(`Failed to reconcile NATS artifacts for fog ${fog.uuid}: ${error.message}`) + } + } + + if (_isKubernetesControlPlane()) { + try { + const existing = await K8sClient.getConfigMap(K8S_NATS_JWT_BUNDLE_CONFIG_MAP, { ignoreNotFound: true }) + const existingData = existing && existing.data ? existing.data : null + const newHash = _configMapDataHash(fullServerJwtBundle) + const unchanged = existingData && _configMapDataHash(existingData) === newHash + if (!unchanged) { + await K8sClient.patchConfigMap(K8S_NATS_JWT_BUNDLE_CONFIG_MAP, { data: fullServerJwtBundle }, { ignoreNotFound: true }) + } + } catch (err) { + logger.warn(`Failed to patch Kubernetes NATS hub JWT bundle ConfigMap: ${err.message}`) + } + } +} + +const REASON_VALUES = ['auth-mutation', 'account-created', 'account-deleted', 'account-rule-updated', 'user-rule-updated', 'server-deleted', 'cluster-routes-changed', 'system-account-created'] + +async function _computeAffectedFogUuidsForEnqueue (options, transaction) { + const reason = options.reason || 'auth-mutation' + const fogs = await FogManager.findAll({}, transaction) + const applicationsWithNats = await ApplicationManager.findAll({ natsAccess: true }, transaction) + const appIdsFromNatsApps = (applicationsWithNats || []).map((a) => a.id) + const applicationsWithNatsById = new Map((applicationsWithNats || []).map((a) => [a.id, a])) + const natsInstances = await NatsInstanceManager.findAll({}, transaction) + const natsInstanceByFog = new Map() + for (const ni of natsInstances || []) { + if (ni.iofogUuid) natsInstanceByFog.set(ni.iofogUuid, ni) + } + const microservices = appIdsFromNatsApps.length > 0 + ? await MicroserviceManager.findAll({ applicationId: { [Op.in]: appIdsFromNatsApps } }, transaction) + : [] + const microservicesByFog = new Map() + for (const ms of microservices) { + if (ms.iofogUuid) { + if (!microservicesByFog.has(ms.iofogUuid)) microservicesByFog.set(ms.iofogUuid, []) + microservicesByFog.get(ms.iofogUuid).push(ms) + } + } + const fogUuids = fogs.map((f) => f.uuid) + if (reason === 'server-deleted' || reason === 'cluster-routes-changed') { + return [] + } + if (reason === 'auth-mutation') { + return fogUuids + } + if (reason === 'system-account-created') { + const serverFogUuids = fogUuids.filter((uuid) => { + const ni = natsInstanceByFog.get(uuid) + return ni && !ni.isLeaf + }) + return serverFogUuids + } + if ((reason === 'account-created' || reason === 'account-deleted') && options.applicationId != null) { + const affected = _getAffectedFogUuidsForApplication(options.applicationId, natsInstanceByFog, microservicesByFog) + return fogUuids.filter((u) => affected.has(u)) + } + if (reason === 'account-rule-updated' && options.accountRuleId != null) { + const affected = _getAffectedFogUuidsForAccountRule(options.accountRuleId, natsInstanceByFog, microservicesByFog, applicationsWithNatsById) + return fogUuids.filter((u) => affected.has(u)) + } + if (reason === 'user-rule-updated' && options.userRuleId != null) { + const affected = await _getAffectedFogUuidsForUserRule(options.userRuleId, natsInstanceByFog, transaction) + return fogUuids.filter((u) => affected.has(u)) + } + return fogUuids +} + +function _chunkFogUuids (fogUuids, chunkSize) { + const chunks = [] + for (let i = 0; i < fogUuids.length; i += chunkSize) { + chunks.push(fogUuids.slice(i, i + chunkSize)) + } + return chunks.length ? chunks : [[]] +} + +async function enqueueReconcileTask (options = {}, transaction) { + if (transaction.fakeTransaction) { + return databaseProvider.sequelize.transaction((t) => enqueueReconcileTask(options, t)) + } + const reason = REASON_VALUES.includes(options.reason) ? options.reason : 'auth-mutation' + const applicationId = options.applicationId != null ? options.applicationId : null + const accountRuleId = options.accountRuleId != null ? options.accountRuleId : null + const userRuleId = options.userRuleId != null ? options.userRuleId : null + const scope = { reason, applicationId, accountRuleId, userRuleId } + + let affectedFogUuids + if (Array.isArray(options.fogUuids) && options.fogUuids.length > 0) { + affectedFogUuids = options.fogUuids + } else { + affectedFogUuids = await _computeAffectedFogUuidsForEnqueue({ ...options, reason }, transaction) + } + const chunkSize = Math.max(1, config.get('settings.natsReconcileChunkSize', 1)) + const chunks = _chunkFogUuids(affectedFogUuids, chunkSize) + + const Entity = NatsReconcileTaskManager.getEntity() + await Entity.destroy({ + where: { + reason: scope.reason, + applicationId: scope.applicationId, + accountRuleId: scope.accountRuleId, + userRuleId: scope.userRuleId, + status: { [Op.in]: ['pending', 'in_progress'] } + }, + transaction + }) + + for (const chunk of chunks) { + await NatsReconcileTaskManager.create({ + reason: scope.reason, + applicationId: scope.applicationId, + accountRuleId: scope.accountRuleId, + userRuleId: scope.userRuleId, + fogUuids: chunk.join(','), + status: 'pending' + }, transaction) + } +} + +async function claimNextTask (controllerUuid, stalenessSeconds) { + return NatsReconcileTaskManager.claimNext(controllerUuid, stalenessSeconds) +} + +async function reconcileResolverArtifacts (options = {}, transaction) { + if (natsReconcileRunning) { + natsReconcilePending = true + return { scheduled: true } + } + + natsReconcileRunning = true + try { + do { + natsReconcilePending = false + await _reconcileResolverArtifactsOnce(options, transaction) + } while (natsReconcilePending) + return { scheduled: false } + } finally { + natsReconcileRunning = false + } +} + +function isReconcileRunning () { + return natsReconcileRunning +} + +function setReconcilePending () { + natsReconcilePending = true +} + +function scheduleResolverArtifactsReconcile (options = {}) { + if (natsReconcileRunning) { + natsReconcilePending = true + return { scheduled: true } + } + if (natsReconcileScheduled) { + natsReconcilePending = true + return { scheduled: true } + } + natsReconcileScheduled = true + setImmediate(async () => { + natsReconcileScheduled = false + try { + await module.exports.reconcileResolverArtifacts(options) + } catch (error) { + logger.error(`Background NATS reconcile failed: ${error.message}`) + } + }) + return { scheduled: true } +} + +function normalizeJetstreamSize (value, defaultValue) { + return _normalizeJetstreamSize(value, defaultValue) +} + +module.exports = { + ensureNatsForFog: TransactionDecorator.generateTransaction(ensureNatsForFog), + reconcileResolverArtifacts: TransactionDecorator.generateTransaction(reconcileResolverArtifacts), + scheduleResolverArtifactsReconcile: scheduleResolverArtifactsReconcile, + enqueueReconcileTask: TransactionDecorator.generateTransaction(enqueueReconcileTask), + claimNextTask, + cleanupNatsForFog: TransactionDecorator.generateTransaction(cleanupNatsForFog), + ensureLeafCredsForFog: TransactionDecorator.generateTransaction(ensureLeafCredsForFog), + isReconcileRunning, + setReconcilePending, + normalizeJetstreamSize, + mergeK8sHubClusterRoutes +} diff --git a/src/services/rbac-service.js b/src/services/rbac-service.js index 7262a4bd0..1c4891c65 100644 --- a/src/services/rbac-service.js +++ b/src/services/rbac-service.js @@ -15,6 +15,7 @@ const RbacRoleManager = require('../data/managers/rbac-role-manager') const RbacRoleBindingManager = require('../data/managers/rbac-role-binding-manager') const RbacServiceAccountManager = require('../data/managers/rbac-service-account-manager') const MicroserviceManager = require('../data/managers/microservice-manager') +const ApplicationManager = require('../data/managers/application-manager') const TransactionDecorator = require('../decorators/transaction-decorator') const Errors = require('../helpers/errors') const Validator = require('../schemas/index') @@ -33,32 +34,22 @@ function validateNotSystemRole (roleName) { } /** - * Helper function to notify microservices when a service account is updated - * Finds all microservices linked to the service account and triggers change tracking - * @param {number} serviceAccountId - ID of the updated service account + * Notify microservice when a service account linked to a microservice is updated + * @param {Object} serviceAccount - Service account object (must have microserviceUuid if linked to a microservice) * @param {object} transaction - Database transaction */ -async function _notifyMicroservicesForServiceAccountUpdate (serviceAccountId, transaction) { +async function _notifyMicroservicesForServiceAccountUpdate (serviceAccount, transaction) { + const microserviceUuid = serviceAccount.microserviceUuid || (serviceAccount.get && serviceAccount.get('microserviceUuid')) + if (!microserviceUuid) { + return + } try { - const microservices = await MicroserviceManager.findAll({ - serviceAccountId: serviceAccountId - }, transaction) - - if (microservices && microservices.length > 0) { - const iofogUuids = microservices - .map(ms => ms.iofogUuid) - .filter(uuid => uuid !== null && uuid !== undefined) - - for (const iofogUuid of iofogUuids) { - try { - await ChangeTrackingService.update(iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) - } catch (error) { - logger.error(`Failed to update change tracking for fog ${iofogUuid} after service account update:`, error.message) - } - } + const microservice = await MicroserviceManager.findOne({ uuid: microserviceUuid }, transaction) + if (microservice && microservice.iofogUuid) { + await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) } } catch (error) { - logger.error(`Failed to notify microservices for service account update (ID: ${serviceAccountId}):`, error.message) + logger.error(`Failed to notify microservice for service account update (microserviceUuid: ${microserviceUuid}):`, error.message) } } @@ -138,12 +129,14 @@ async function updateRoleEndpoint (name, roleData, transaction) { // Find all service accounts that reference this role using roleId for efficient querying const serviceAccounts = await RbacServiceAccountManager.findAll({ roleId: roleId }, transaction) for (const sa of serviceAccounts) { - // Trigger update to refresh cache and ensure roleId is set - await RbacServiceAccountManager.updateServiceAccount(sa.name, { - roleRef: sa.roleRef - }, transaction) - // Notify linked microservices - await _notifyMicroservicesForServiceAccountUpdate(sa.id, transaction) + const application = sa.applicationId ? await ApplicationManager.findOne({ id: sa.applicationId }, transaction) : null + const appName = application ? application.name : null + if (appName) { + await RbacServiceAccountManager.updateServiceAccount(appName, sa.name, { + roleRef: sa.roleRef + }, transaction) + } + await _notifyMicroservicesForServiceAccountUpdate(sa, transaction) } } @@ -205,17 +198,17 @@ async function deleteRoleBindingEndpoint (name, transaction) { } // ServiceAccount Management -async function listServiceAccountsEndpoint (transaction) { - const serviceAccounts = await RbacServiceAccountManager.listServiceAccounts(transaction) +async function listServiceAccountsEndpoint (applicationName, transaction) { + const serviceAccounts = await RbacServiceAccountManager.listServiceAccounts(transaction, { applicationName }) return { serviceAccounts: serviceAccounts } } -async function getServiceAccountEndpoint (name, transaction) { - const sa = await RbacServiceAccountManager.getServiceAccount(name, transaction) +async function getServiceAccountEndpoint (appName, name, transaction) { + const sa = await RbacServiceAccountManager.getServiceAccount(appName, name, transaction) if (!sa) { - throw new Errors.NotFoundError(`ServiceAccount '${name}' not found`) + throw new Errors.NotFoundError(`ServiceAccount '${name}' not found in application '${appName}'`) } return { serviceAccount: sa @@ -223,7 +216,6 @@ async function getServiceAccountEndpoint (name, transaction) { } async function createServiceAccountEndpoint (saData, transaction) { - // Validate schema await Validator.validate(saData, Validator.schemas.serviceAccountCreate) const sa = await RbacServiceAccountManager.createServiceAccount(saData, transaction) @@ -232,39 +224,32 @@ async function createServiceAccountEndpoint (saData, transaction) { } } -async function updateServiceAccountEndpoint (name, saData, transaction) { - // Validate schema +async function updateServiceAccountEndpoint (appName, name, saData, transaction) { await Validator.validate(saData, Validator.schemas.serviceAccountUpdate) - const sa = await RbacServiceAccountManager.updateServiceAccount(name, saData, transaction) + const sa = await RbacServiceAccountManager.updateServiceAccount(appName, name, saData, transaction) - // Notify linked microservices about the service account update - await _notifyMicroservicesForServiceAccountUpdate(sa.id, transaction) + await _notifyMicroservicesForServiceAccountUpdate(sa, transaction) return { serviceAccount: sa } } -async function deleteServiceAccountEndpoint (name, transaction) { - // Get service account first to check if it exists and get its ID - const sa = await RbacServiceAccountManager.getServiceAccount(name, transaction) +async function deleteServiceAccountEndpoint (appName, name, transaction) { + const sa = await RbacServiceAccountManager.getServiceAccount(appName, name, transaction) if (!sa) { - throw new Errors.NotFoundError(`ServiceAccount '${name}' not found`) + throw new Errors.NotFoundError(`ServiceAccount '${name}' not found in application '${appName}'`) } - // Check if any microservice is referencing this service account - const referencingMicroservice = await MicroserviceManager.findOne({ - serviceAccountId: sa.id - }, transaction) - - if (referencingMicroservice) { + if (sa.microserviceUuid) { + const microservice = await MicroserviceManager.findOne({ uuid: sa.microserviceUuid }, transaction) throw new Errors.ConflictError( - `Cannot delete ServiceAccount '${name}' because it is referenced by microservice '${referencingMicroservice.name}' (uuid: ${referencingMicroservice.uuid}). Please delete or update the microservice first.` + `Cannot delete ServiceAccount '${name}' because it is referenced by microservice '${microservice ? microservice.name : 'unknown'}' (uuid: ${sa.microserviceUuid}). Please delete or update the microservice first.` ) } - await RbacServiceAccountManager.deleteServiceAccount(name, transaction) + await RbacServiceAccountManager.deleteServiceAccount(appName, name, transaction) return { message: `ServiceAccount '${name}' deleted successfully` } diff --git a/src/services/router-connection-service.js b/src/services/router-connection-service.js index 2fff22492..fbc12275d 100644 --- a/src/services/router-connection-service.js +++ b/src/services/router-connection-service.js @@ -2,6 +2,7 @@ const rhea = require('rhea') const config = require('../config') const logger = require('../logger') const RouterManager = require('../data/managers/router-manager') +const FogManager = require('../data/managers/iofog-manager') const CertificateService = require('./certificate-service') const SecretService = require('./secret-service') const os = require('os') @@ -262,7 +263,11 @@ class RouterConnectionService { return 'default-router-local-ca' } const router = await this._getDefaultRouterRecord() - return `${router.iofogUuid}-local-ca` + const fog = await FogManager.findOne({ uuid: router.iofogUuid }, this.fakeTransaction) + if (!fog) { + throw new Error('Router not found. Please ensure router is provisioned.') + } + return `router-local-ca-${fog.name}` } _buildControllerHosts () { diff --git a/src/services/router-service.js b/src/services/router-service.js index f7b7dd8c2..25bad1a09 100644 --- a/src/services/router-service.js +++ b/src/services/router-service.js @@ -21,7 +21,6 @@ const MicroserviceManager = require('../data/managers/microservice-manager') const MicroserviceCapAddManager = require('../data/managers/microservice-cap-add-manager') const MicroserviceStatusManager = require('../data/managers/microservice-status-manager') const MicroserviceExecStatusManager = require('../data/managers/microservice-exec-status-manager') -const ApplicationManager = require('../data/managers/application-manager') const MicroservicePortManager = require('../data/managers/microservice-port-manager') const RouterConnectionManager = require('../data/managers/router-connection-manager') const RouterManager = require('../data/managers/router-manager') @@ -35,6 +34,10 @@ const FogManager = require('../data/managers/iofog-manager') const config = require('../config') const VolumeMountService = require('./volume-mount-service') const VolumeMappingManager = require('../data/managers/volume-mapping-manager') +const { + ensureSystemApplication, + getSystemMicroserviceName +} = require('../helpers/system-naming') const SITE_CONFIG_VERSION = 'pot' const SITE_CONFIG_NAMESPACE = process.env.CONTROLLER_NAMESPACE || config.get('app.namespace') @@ -79,7 +82,14 @@ async function validateAndReturnUpstreamRouters (upstreamRouterIds, isSystemFog, const upstreamRouters = [] for (const upstreamRouterId of upstreamRouterIds) { - const upstreamRouter = upstreamRouterId === Constants.DEFAULT_ROUTER_NAME ? defaultRouter : await RouterManager.findOne({ iofogUuid: upstreamRouterId }, transaction) + let upstreamRouter = upstreamRouterId === Constants.DEFAULT_ROUTER_NAME ? defaultRouter : await RouterManager.findOne({ iofogUuid: upstreamRouterId }, transaction) + if (!upstreamRouter && upstreamRouterId !== Constants.DEFAULT_ROUTER_NAME) { + const fog = await FogManager.findOne({ name: upstreamRouterId }, transaction) + if (!fog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_ROUTER, upstreamRouterId)) + } + upstreamRouter = await RouterManager.findOne({ iofogUuid: fog.uuid }, transaction) + } if (!upstreamRouter) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_ROUTER, upstreamRouterId)) } @@ -113,7 +123,7 @@ async function createRouterForFog (fogData, uuid, upstreamRouters, transaction) for (const upstreamRouter of upstreamRouters) { await RouterConnectionManager.create({ sourceRouter: router.id, destRouter: upstreamRouter.id }, transaction) - const connectorConfig = _getRouterConnectorConfig(isEdge, upstreamRouter, uuid) + const connectorConfig = await _getRouterConnectorConfig(isEdge, upstreamRouter, uuid, transaction) microserviceConfig.connectors[connectorConfig.name] = connectorConfig } @@ -242,10 +252,11 @@ async function updateConfig (routerID, containerEngine, transaction) { ) for (const upstreamRouterConnection of upstreamRoutersConnections) { - const connectorConfig = _getRouterConnectorConfig( + const connectorConfig = await _getRouterConnectorConfig( router.isEdge, upstreamRouterConnection.dest, - router.iofogUuid + router.iofogUuid, + transaction ) newConfig.connectors[connectorConfig.name] = connectorConfig } @@ -332,14 +343,14 @@ function _createRouterPorts (routerMicroserviceUuid, port, transaction) { async function _createRouterMicroservice (isEdge, uuid, microserviceConfig, transaction) { const routerCatalog = await CatalogService.getRouterCatalogItem(transaction) const hostNetworkMode = !isEdge - const routerApplicationData = { - name: `system-${uuid.toLowerCase()}`, - isActivated: true, - isSystem: true + const fog = await FogManager.findOne({ uuid }, transaction) + if (!fog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, uuid)) } + const application = await ensureSystemApplication(fog, transaction) const routerMicroserviceData = { uuid: AppHelper.generateUUID(), - name: `router-${uuid.toLowerCase()}`, + name: getSystemMicroserviceName('router'), config: JSON.stringify(microserviceConfig), catalogItemId: routerCatalog.id, iofogUuid: uuid, @@ -375,9 +386,8 @@ async function _createRouterMicroservice (isEdge, uuid, microserviceConfig, tran const capAddValues = [ { capAdd: 'NET_RAW' } ] - let application = await ApplicationManager.findOne({ name: routerApplicationData.name }, transaction) if (!application) { - application = await ApplicationManager.create(routerApplicationData, transaction) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, `system-${fog.name}`)) } routerMicroserviceData.applicationId = application.id const routerMicroservice = await MicroserviceManager.create(routerMicroserviceData, transaction) @@ -402,19 +412,31 @@ async function _createRouterMicroservice (isEdge, uuid, microserviceConfig, tran return routerMicroservice } -function _getRouterConnectorConfig (isEdge, dest, uuid) { +async function _getRouterConnectorConfig (isEdge, dest, uuid, transaction) { + const fog = await FogManager.findOne({ uuid }, transaction) + if (!fog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, uuid)) + } const config = { name: dest.iofogUuid || Constants.DEFAULT_ROUTER_NAME, role: isEdge ? 'edge' : 'inter-router', host: dest.host, port: (isEdge ? dest.edgeRouterPort : dest.interRouterPort).toString(), - sslProfile: `${uuid}-site-server` + sslProfile: `router-site-server-${fog.name}` } return config } async function _getRouterMicroserviceConfig (isEdge, uuid, messagingPort, interRouterPort, edgeRouterPort, containerEngine, transaction) { + const fog = await FogManager.findOne({ uuid }, transaction) + if (!fog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, uuid)) + } + // Get SSL secrets for all profiles + const siteServerSecret = await SecretManager.getSecret(`router-site-server-${fog.name}`, transaction) + const localServerSecret = await SecretManager.getSecret(`router-local-server-${fog.name}`, transaction) + const localAgentSecret = await SecretManager.getSecret(`router-local-agent-${fog.name}`, transaction) let platform = 'docker' if (containerEngine === 'podman') { platform = 'podman' @@ -459,11 +481,6 @@ async function _getRouterMicroserviceConfig (isEdge, uuid, messagingPort, interR caCertFile: SYSTEM_DEFAULT_CA_PATH } - // Get SSL secrets for all profiles and add path-based sslProfiles (no base64) - const siteServerSecret = await SecretManager.getSecret(`${uuid}-site-server`, transaction) - const localServerSecret = await SecretManager.getSecret(`${uuid}-local-server`, transaction) - const localAgentSecret = await SecretManager.getSecret(`${uuid}-local-agent`, transaction) - function addSslProfileFromSecret (profileName, secret) { if (!secret) return const profile = { name: profileName } @@ -479,9 +496,9 @@ async function _getRouterMicroserviceConfig (isEdge, uuid, messagingPort, interR config.sslProfiles[profileName] = profile } - addSslProfileFromSecret(`${uuid}-site-server`, siteServerSecret) - addSslProfileFromSecret(`${uuid}-local-server`, localServerSecret) - addSslProfileFromSecret(`${uuid}-local-agent`, localAgentSecret) + addSslProfileFromSecret(`router-site-server-${fog.name}`, siteServerSecret) + addSslProfileFromSecret(`router-local-server-${fog.name}`, localServerSecret) + addSslProfileFromSecret(`router-local-agent-${fog.name}`, localAgentSecret) // Add default AMQP listener (internal) config.listeners[`${uuid}-amqp`] = { @@ -499,7 +516,7 @@ async function _getRouterMicroserviceConfig (isEdge, uuid, messagingPort, interR role: 'normal', authenticatePeer: true, saslMechanisms: 'EXTERNAL', - sslProfile: `${uuid}-local-server` + sslProfile: `router-local-server-${fog.name}` } config.listeners[`${uuid}-amqps`] = amqpsListener @@ -512,7 +529,7 @@ async function _getRouterMicroserviceConfig (isEdge, uuid, messagingPort, interR role: 'inter-router', authenticatePeer: true, saslMechanisms: 'EXTERNAL', - sslProfile: `${uuid}-site-server` + sslProfile: `router-site-server-${fog.name}` } config.listeners[`${uuid}-inter-router`] = interRouterListener @@ -524,7 +541,7 @@ async function _getRouterMicroserviceConfig (isEdge, uuid, messagingPort, interR role: 'edge', authenticatePeer: true, saslMechanisms: 'EXTERNAL', - sslProfile: `${uuid}-site-server` + sslProfile: `router-site-server-${fog.name}` } config.listeners[`${uuid}-edge`] = edgeListener } @@ -532,14 +549,18 @@ async function _getRouterMicroserviceConfig (isEdge, uuid, messagingPort, interR return config } -const ROUTER_SSL_PROFILE_NAMES = (uuid) => [ - `${uuid}-site-server`, - `${uuid}-local-server`, - `${uuid}-local-agent` +const ROUTER_SSL_PROFILE_NAMES = (name) => [ + `router-site-server-${name}`, + `router-local-server-${name}`, + `router-local-agent-${name}` ] async function _ensureRouterSslVolumeMountsAndMappings (iofogUuid, routerMicroserviceUuid, transaction, doCleanup = false) { - const profileNames = ROUTER_SSL_PROFILE_NAMES(iofogUuid) + const fog = await FogManager.findOne({ uuid: iofogUuid }, transaction) + if (!fog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, iofogUuid)) + } + const profileNames = ROUTER_SSL_PROFILE_NAMES(fog.name) const profileNamesWithSecret = new Set() for (const name of profileNames) { diff --git a/src/services/routing-service.js b/src/services/routing-service.js deleted file mode 100644 index f6cb1fdc4..000000000 --- a/src/services/routing-service.js +++ /dev/null @@ -1,219 +0,0 @@ -/* - * ******************************************************************************* - * * Copyright (c) 2023 Datasance Teknoloji A.S. - * * - * * This program and the accompanying materials are made available under the - * * terms of the Eclipse Public License v. 2.0 which is available at - * * http://www.eclipse.org/legal/epl-2.0 - * * - * * SPDX-License-Identifier: EPL-2.0 - * ******************************************************************************* - * - */ - -const AppHelper = require('../helpers/app-helper') -const ChangeTrackingService = require('../services/change-tracking-service') -const Errors = require('../helpers/errors') -const ErrorMessages = require('../helpers/error-messages') -const MicroserviceManager = require('../data/managers/microservice-manager') -const ApplicationManager = require('../data/managers/application-manager') -const RoutingManager = require('../data/managers/routing-manager') -const TransactionDecorator = require('../decorators/transaction-decorator') -const Validator = require('../schemas') - -async function getRoutings (isCLI, transaction) { - const routes = await RoutingManager.findAllPopulated({}, transaction) - return { routes: routes.map(r => ({ - application: r.application.name, - name: r.name, - from: r.sourceMicroservice.name, - to: r.destMicroservice.name, - // API retrocompatibility - sourceMicroserviceUuid: r.sourceMicroservice.uuid, - destMicroserviceUuid: r.destMicroservice.uuid - })) } -} - -async function getRouting (appName, name, isCLI, transaction) { - const application = await ApplicationManager.findOne({ name: appName }, transaction) - if (!application) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_NAME, appName)) - } - const route = await RoutingManager.findOnePopulated({ name, applicationId: application.id }, transaction) - if (!route) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_ROUTING_NAME, name)) - } - return { - application: route.application.name, - name: route.name, - from: route.sourceMicroservice.name, - to: route.destMicroservice.name, - // API retrocompatibility - sourceMicroserviceUuid: route.sourceMicroservice.uuid, - destMicroserviceUuid: route.destMicroservice.uuid - } -} - -async function _validateRouteMsvc (routingData, isCLI, transaction) { - // Retro compatibility logic - if (routingData.sourceMicroserviceUuid) { - const sourceWhere = { uuid: routingData.sourceMicroserviceUuid } - const sourceMicroservice = await MicroserviceManager.findOne(sourceWhere, transaction) - if (!sourceMicroservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_SOURCE_MICROSERVICE_NAME, routingData.sourceMicroserviceUuid)) - } - - const destWhere = { uuid: routingData.destMicroserviceUuid } - const destMicroservice = await MicroserviceManager.findOne(destWhere, transaction) - if (!destMicroservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_DEST_MICROSERVICE_NAME, routingData.destMicroserviceUuid)) - } - return { sourceMicroservice, destMicroservice } - } else { - const applicationWhere = isCLI ? { name: routingData.application } : { name: routingData.application } - const application = await ApplicationManager.findOne(applicationWhere, transaction) - if (!application) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, routingData.application)) - } - - const sourceWhere = { name: routingData.from, applicationId: application.id } - const sourceMicroservice = await MicroserviceManager.findOne(sourceWhere, transaction) - if (!sourceMicroservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_SOURCE_MICROSERVICE_NAME, routingData.from)) - } - - const destWhere = { name: routingData.to, applicationId: application.id } - const destMicroservice = await MicroserviceManager.findOne(destWhere, transaction) - if (!destMicroservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_DEST_MICROSERVICE_NAME, routingData.to)) - } - return { sourceMicroservice, destMicroservice } - } -} - -async function createRouting (routingData, isCLI, transaction) { - await Validator.validate(routingData, Validator.schemas.routingCreate) - - const { sourceMicroservice, destMicroservice } = await _validateRouteMsvc(routingData, isCLI, transaction) - - return _createRoute(sourceMicroservice, destMicroservice, routingData, transaction) -} - -async function updateRouting (appName, routeName, routeData, isCLI, transaction) { - await Validator.validate(routeData, Validator.schemas.routingUpdate) - const application = await ApplicationManager.findOne({ name: appName }, transaction) - if (!application) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_NAME, appName)) - } - - const oldRoute = await RoutingManager.findOnePopulated({ name: routeName, applicationId: application.id }, transaction) - if (!oldRoute) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_ROUTING_NAME, routeName)) - } - - const { sourceMicroservice, destMicroservice } = await _validateRouteMsvc({ ...routeData, application: oldRoute.application.name }, isCLI, transaction) - - const updateRebuildMs = { - rebuild: true - } - - const updateRouteData = { - name: routeData.name || oldRoute.name, - sourceMicroserviceUuid: sourceMicroservice.uuid, - destMicroserviceUuid: destMicroservice.uuid - } - - if (sourceMicroservice.uuid !== oldRoute.sourceMicroserviceUuid) { - // Update change tracking of oldMsvc - await ChangeTrackingService.update(oldRoute.sourceMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) - - // Update new source msvc - await MicroserviceManager.update({ uuid: sourceMicroservice.uuid }, updateRebuildMs, transaction) - await ChangeTrackingService.update(sourceMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) - } - if (destMicroservice.uuid !== oldRoute.destMicroserviceUuid) { - // Update change tracking of oldMsvc - await ChangeTrackingService.update(oldRoute.destMicroserviceUuid.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) - - // Update new dest msvc - await MicroserviceManager.update({ uuid: destMicroservice.uuid }, updateRebuildMs, transaction) - await ChangeTrackingService.update(destMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) - } - - await RoutingManager.update({ id: oldRoute.id }, updateRouteData, transaction) -} - -async function _createRoute (sourceMicroservice, destMicroservice, routeData, transaction) { - if (!sourceMicroservice.iofogUuid || !destMicroservice.iofogUuid) { - throw new Errors.ValidationError('fog not set') - } - if (sourceMicroservice.applicationId !== destMicroservice.applicationId) { - throw new Errors.ValidationError('microservices on different applications') - } - - const route = await RoutingManager.findOne({ - sourceMicroserviceUuid: sourceMicroservice.uuid, - destMicroserviceUuid: destMicroservice.uuid - }, transaction) - if (route) { - throw new Errors.DuplicatePropertyError('route already exists') - } - - return _createSimpleRoute(sourceMicroservice, destMicroservice, routeData, transaction) -} - -async function deleteRouting (appName, name, isCLI, transaction) { - const application = await ApplicationManager.findOne({ name: appName }, transaction) - if (!application) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_NAME, appName)) - } - const route = await RoutingManager.findOne({ name, applicationId: application.id }, transaction) - if (!route) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.ROUTE_NOT_FOUND)) - } - - await _deleteSimpleRoute(route, transaction) -} - -async function _createSimpleRoute (sourceMicroservice, destMicroservice, routeData, transaction) { - // create new route - const createRouteData = { - ...routeData, - sourceMicroserviceUuid: sourceMicroservice.uuid, - destMicroserviceUuid: destMicroservice.uuid, - applicationId: sourceMicroservice.applicationId - } - - const newRoute = await RoutingManager.create(createRouteData, transaction) - await _switchOnUpdateFlagsForMicroservicesInRoute(sourceMicroservice, destMicroservice, transaction) - return newRoute -} - -async function _deleteSimpleRoute (route, transaction) { - await RoutingManager.delete({ id: route.id }, transaction) - - const sourceMsvc = await MicroserviceManager.findOne({ uuid: route.sourceMicroserviceUuid }, transaction) - const destMsvc = await MicroserviceManager.findOne({ uuid: route.destMicroserviceUuid }, transaction) - - await ChangeTrackingService.update(sourceMsvc.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) - await ChangeTrackingService.update(destMsvc.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) -} - -async function _switchOnUpdateFlagsForMicroservicesInRoute (sourceMicroservice, destMicroservice, transaction) { - const updateRebuildMs = { - rebuild: true - } - await MicroserviceManager.update({ uuid: sourceMicroservice.uuid }, updateRebuildMs, transaction) - await MicroserviceManager.update({ uuid: destMicroservice.uuid }, updateRebuildMs, transaction) - - await ChangeTrackingService.update(sourceMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) - await ChangeTrackingService.update(destMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) -} - -module.exports = { - getRouting: TransactionDecorator.generateTransaction(getRouting), - getRoutings: TransactionDecorator.generateTransaction(getRoutings), - createRouting: TransactionDecorator.generateTransaction(createRouting), - updateRouting: TransactionDecorator.generateTransaction(updateRouting), - deleteRouting: TransactionDecorator.generateTransaction(deleteRouting) -} diff --git a/src/services/secret-service.js b/src/services/secret-service.js index 312758e60..97e3eeccd 100644 --- a/src/services/secret-service.js +++ b/src/services/secret-service.js @@ -11,6 +11,7 @@ * */ +const crypto = require('crypto') const TransactionDecorator = require('../decorators/transaction-decorator') const SecretManager = require('../data/managers/secret-manager') const MicroserviceManager = require('../data/managers/microservice-manager') @@ -50,6 +51,19 @@ function validateSecretData (type, data) { } } +/** + * Deterministic hash of secret data object (key-order independent). + * Used to skip secret update when content is unchanged. + */ +function _secretDataHash (data) { + if (data == null || typeof data !== 'object') { + return crypto.createHash('sha256').update(String(data)).digest('hex') + } + const sortedKeys = Object.keys(data).sort() + const canonical = JSON.stringify(sortedKeys.map(k => ({ k, v: data[k] }))) + return crypto.createHash('sha256').update(canonical).digest('hex') +} + async function createSecretEndpoint (secretData, transaction) { const validation = await Validator.validate(secretData, Validator.schemas.secretCreate) if (!validation.valid) { @@ -102,6 +116,43 @@ async function updateSecretEndpoint (secretName, secretData, transaction) { } } +/** + * Update secret only if data has changed. Skips update and change-tracking when content is identical. + * Use for NATS creds/seeds to avoid unnecessary volume mount version bumps and agent churn. + */ +async function updateSecretEndpointIfChanged (secretName, secretData, transaction) { + const validation = await Validator.validate(secretData, Validator.schemas.secretUpdate) + if (!validation.valid) { + throw new Errors.ValidationError(validation.error) + } + + const existingSecret = await SecretManager.findOne({ name: secretName }, transaction) + if (!existingSecret) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.SECRET_NOT_FOUND, secretName)) + } + + if (existingSecret.type !== secretData.type) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.SECRET_TYPE_MISMATCH, secretName, existingSecret.type, secretData.type)) + } + + validateSecretData(existingSecret.type, secretData.data) + + const existingData = existingSecret.data || {} + const existingHash = _secretDataHash(existingData) + const newHash = _secretDataHash(secretData.data) + if (existingHash === newHash) { + return { + id: existingSecret.id, + name: existingSecret.name, + type: existingSecret.type, + created_at: existingSecret.created_at, + updated_at: existingSecret.updated_at + } + } + + return updateSecretEndpoint(secretName, secretData, transaction) +} + async function getSecretEndpoint (secretName, transaction) { const secret = await SecretManager.getSecret(secretName, transaction) if (!secret) { @@ -270,6 +321,7 @@ async function _updateMicroservicesUsingSecret (secretName, transaction) { module.exports = { createSecretEndpoint: TransactionDecorator.generateTransaction(createSecretEndpoint), updateSecretEndpoint: TransactionDecorator.generateTransaction(updateSecretEndpoint), + updateSecretEndpointIfChanged: TransactionDecorator.generateTransaction(updateSecretEndpointIfChanged), getSecretEndpoint: TransactionDecorator.generateTransaction(getSecretEndpoint), listSecretsEndpoint: TransactionDecorator.generateTransaction(listSecretsEndpoint), deleteSecretEndpoint: TransactionDecorator.generateTransaction(deleteSecretEndpoint) diff --git a/src/services/services-service.js b/src/services/services-service.js index 6f2dc7281..da4bc45ee 100644 --- a/src/services/services-service.js +++ b/src/services/services-service.js @@ -27,9 +27,13 @@ const FogManager = require('../data/managers/iofog-manager') const TagsManager = require('../data/managers/tags-manager') const ChangeTrackingService = require('./change-tracking-service') const ApplicationManager = require('../data/managers/application-manager') +const { + ensureSystemApplication, + getSystemMicroserviceName +} = require('../helpers/system-naming') // const { Op } = require('sequelize') -const K8S_ROUTER_CONFIG_MAP = 'pot-router' +const K8S_ROUTER_CONFIG_MAP = 'iofog-router' const SERVICE_ANNOTATION_TAG = 'service.datasance.com/tag' // Map service tags to string array @@ -121,7 +125,7 @@ async function validateNonK8sType (serviceConfig) { } async function _validateServiceName (serviceConfig) { - if (serviceConfig.name.toLowerCase() === 'controller' || serviceConfig.name.toLowerCase() === 'router' || serviceConfig.name.toLowerCase() === 'router-internal' || serviceConfig.name.toLowerCase() === 'docker' || serviceConfig.name.toLowerCase() === 'podman' || serviceConfig.name.toLowerCase() === 'kubernetes') { + if (serviceConfig.name.toLowerCase() === 'controller' || serviceConfig.name.toLowerCase() === 'router' || serviceConfig.name.toLowerCase() === 'router-internal' || serviceConfig.name.toLowerCase() === 'docker' || serviceConfig.name.toLowerCase() === 'podman' || serviceConfig.name.toLowerCase() === 'kubernetes' || serviceConfig.name.toLowerCase() === 'nats' || serviceConfig.name.toLowerCase() === 'nats-headless' || serviceConfig.name.toLowerCase() === 'nats-server') { throw new Errors.ValidationError('Service name cannot be "controller" or "router" or "router-internal" or "docker"') } } @@ -349,8 +353,16 @@ async function _buildTcpListener (serviceConfig, fogNodeUuid = null) { // Helper function to get router microservice by fog node UUID async function _getRouterMicroservice (fogNodeUuid, transaction) { - const routerName = `router-${fogNodeUuid.toLowerCase()}` - const routerMicroservice = await MicroserviceManager.findOne({ name: routerName }, transaction) + const fog = await FogManager.findOne({ uuid: fogNodeUuid }, transaction) + if (!fog) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogNodeUuid)) + } + const application = await ensureSystemApplication(fog, transaction) + const routerName = getSystemMicroserviceName('router') + const routerMicroservice = await MicroserviceManager.findOne({ + name: routerName, + applicationId: application.id + }, transaction) if (!routerMicroservice) { throw new Errors.NotFoundError(`Router microservice not found: ${routerName}`) } @@ -943,15 +955,9 @@ async function _updateK8sService (serviceConfig, transaction) { // Helper function to delete Kubernetes service async function _deleteK8sService (serviceName) { try { - await K8sClient.deleteService(serviceName) + await K8sClient.deleteService(serviceName, { ignoreNotFound: true }) } catch (error) { - // If it's a 404 (Not Found), log a warning and continue - if (error.response && error.response.status === 404) { - logger.warn(`K8s service ${serviceName} not found during delete. It may have already been deleted.`) - } else { - // For other errors, you may want to log and rethrow, or just log as warning - logger.warn(`Failed to delete K8s service ${serviceName}: ${error.message}`) - } + logger.warn(`Failed to delete K8s service ${serviceName}: ${error.message}`) // Do not throw, so the flow continues } } diff --git a/src/services/volume-mount-service.js b/src/services/volume-mount-service.js index 21193e231..801bb8b1b 100644 --- a/src/services/volume-mount-service.js +++ b/src/services/volume-mount-service.js @@ -151,6 +151,8 @@ async function linkVolumeMountEndpoint (name, fogUuids, transaction) { const volumeMount = await getVolumeMountEndpoint(name, transaction) + const alreadyLinked = new Set(await findVolumeMountedFogNodes(name, transaction)) + for (const fogUuid of fogUuids) { const agent = await FogManager.findOne({ uuid: fogUuid }, transaction) if (!agent) { @@ -159,8 +161,10 @@ async function linkVolumeMountEndpoint (name, fogUuids, transaction) { await agent.addVolumeMount(volumeMount.uuid, transaction) } - // Update change tracking for all linked fog nodes - await _updateChangeTrackingForFogs(fogUuids, transaction) + const newlyLinked = fogUuids.filter((uuid) => !alreadyLinked.has(uuid)) + if (newlyLinked.length > 0) { + await _updateChangeTrackingForFogs(newlyLinked, transaction) + } return getVolumeMountEndpoint(name, transaction) } diff --git a/src/services/yaml-parser-service.js b/src/services/yaml-parser-service.js index a67c2f492..7cfeeab5a 100644 --- a/src/services/yaml-parser-service.js +++ b/src/services/yaml-parser-service.js @@ -21,6 +21,7 @@ async function parseAppYAML (app) { const application = { ...app, isActivated: app.isActivated || true, + natsConfig: lget(app, 'natsConfig', undefined), microservices: await Promise.all((app.microservices || []).map(async (m) => parseMicroserviceYAML(m))) } return application @@ -359,12 +360,11 @@ const parseMicroserviceYAML = async (microservice) => { env: parseEnvVariables(lget(microservice, 'container.env', [])), images, extraHosts: lget(microservice, 'container.extraHosts', []), - ...microservice.msRoutes, - pubTags: lget(microservice, 'msRoutes.pubTags', []), - subTags: lget(microservice, 'msRoutes.subTags', []), application: microservice.application, schedule: lget(microservice, 'schedule', 50), - serviceAccount: lget(microservice, 'serviceAccount', undefined) + serviceAccount: lget(microservice, 'serviceAccount', undefined), + natsEnabled: lget(microservice, 'natsEnabled', undefined), + natsConfig: lget(microservice, 'natsConfig', undefined) } _deleteUndefinedFields(microserviceData) return microserviceData @@ -463,12 +463,15 @@ async function parseServiceAccountFile (fileContent) { if (doc.metadata == null) { throw new Errors.ValidationError('Invalid YAML format: metadata is required') } + if (!doc.metadata.applicationName) { + throw new Errors.ValidationError('ServiceAccount YAML must have metadata.applicationName') + } if (!doc.roleRef || !doc.roleRef.name) { throw new Errors.ValidationError('ServiceAccount must have a roleRef with a name') } return { name: doc.metadata.name, - // namespace removed - not stored in database (controller manages single namespace) + applicationName: doc.metadata.applicationName, roleRef: doc.roleRef } } catch (error) { @@ -510,6 +513,154 @@ async function parseCertificateFile (fileContent) { } } +function _pickDefined (obj) { + const out = {} + for (const [k, v] of Object.entries(obj)) { + if (v !== undefined) out[k] = v + } + return out +} + +function _natsAccountRuleSpecToModel (spec) { + if (!spec || typeof spec !== 'object') { + return {} + } + const limits = spec.limits || {} + const defaultPerms = spec.default_permissions || {} + const pub = defaultPerms.pub || {} + const sub = defaultPerms.sub || {} + const resp = defaultPerms.resp || {} + const raw = { + description: spec.description, + infoUrl: spec.info_url !== undefined ? spec.info_url : spec.infoUrl, + maxConnections: spec.maxConnections != null ? spec.maxConnections : limits.conn, + maxLeafNodeConnections: spec.maxLeafNodeConnections != null ? spec.maxLeafNodeConnections : limits.leaf, + maxData: spec.maxData != null ? spec.maxData : limits.data, + maxExports: spec.maxExports != null ? spec.maxExports : limits.exports, + maxImports: spec.maxImports != null ? spec.maxImports : limits.imports, + maxMsgPayload: spec.maxMsgPayload != null ? spec.maxMsgPayload : limits.payload, + maxSubscriptions: spec.maxSubscriptions != null ? spec.maxSubscriptions : limits.subs, + exportsAllowWildcards: spec.exportsAllowWildcards != null ? spec.exportsAllowWildcards : limits.wildcards, + disallowBearer: spec.disallowBearer != null ? spec.disallowBearer : limits.disallow_bearer, + respMax: spec.respMax != null ? spec.respMax : resp.max, + respTtl: spec.respTtl != null ? spec.respTtl : resp.ttl, + imports: Array.isArray(spec.imports) ? spec.imports : undefined, + exports: Array.isArray(spec.exports) ? spec.exports : undefined, + memStorage: spec.memStorage != null ? spec.memStorage : limits.mem_storage, + diskStorage: spec.diskStorage != null ? spec.diskStorage : limits.disk_storage, + streams: spec.streams != null ? spec.streams : limits.streams, + consumer: spec.consumer != null ? spec.consumer : limits.consumer, + maxAckPending: spec.maxAckPending != null ? spec.maxAckPending : limits.max_ack_pending, + memMaxStreamBytes: spec.memMaxStreamBytes != null ? spec.memMaxStreamBytes : limits.mem_max_stream_bytes, + diskMaxStreamBytes: spec.diskMaxStreamBytes != null ? spec.diskMaxStreamBytes : limits.disk_max_stream_bytes, + maxBytesRequired: spec.maxBytesRequired != null ? spec.maxBytesRequired : limits.max_bytes_required, + tieredLimits: typeof spec.tieredLimits === 'object' ? spec.tieredLimits : (spec.tiered_limits && typeof spec.tiered_limits === 'object' ? spec.tiered_limits : undefined), + pubAllow: Array.isArray(spec.pubAllow) ? spec.pubAllow : (Array.isArray(pub.allow) ? pub.allow : undefined), + pubDeny: Array.isArray(spec.pubDeny) ? spec.pubDeny : (Array.isArray(pub.deny) ? pub.deny : undefined), + subAllow: Array.isArray(spec.subAllow) ? spec.subAllow : (Array.isArray(sub.allow) ? sub.allow : undefined), + subDeny: Array.isArray(spec.subDeny) ? spec.subDeny : (Array.isArray(sub.deny) ? sub.deny : undefined) + } + return _pickDefined(raw) +} + +function _natsUserRuleSpecToModel (spec) { + if (!spec || typeof spec !== 'object') { + return {} + } + const pub = spec.pub || {} + const sub = spec.sub || {} + const resp = spec.resp || {} + const raw = { + description: spec.description, + maxSubscriptions: spec.maxSubscriptions != null ? spec.maxSubscriptions : spec.subs, + maxPayload: spec.maxPayload != null ? spec.maxPayload : spec.payload, + maxData: spec.maxData, + bearerToken: spec.bearerToken != null ? spec.bearerToken : spec.bearer_token, + proxyRequired: spec.proxyRequired != null ? spec.proxyRequired : spec.proxy_required, + allowedConnectionTypes: Array.isArray(spec.allowedConnectionTypes) ? spec.allowedConnectionTypes : (Array.isArray(spec.allowed_connection_types) ? spec.allowed_connection_types : undefined), + src: Array.isArray(spec.src) ? spec.src : undefined, + times: Array.isArray(spec.times) ? spec.times : undefined, + timesLocation: spec.timesLocation != null ? spec.timesLocation : (spec.times_location != null ? spec.times_location : spec.locale), + respMax: spec.respMax != null ? spec.respMax : resp.max, + respTtl: spec.respTtl != null ? spec.respTtl : resp.ttl, + pubAllow: Array.isArray(spec.pubAllow) ? spec.pubAllow : (Array.isArray(pub.allow) ? pub.allow : undefined), + pubDeny: Array.isArray(spec.pubDeny) ? spec.pubDeny : (Array.isArray(pub.deny) ? pub.deny : undefined), + subAllow: Array.isArray(spec.subAllow) ? spec.subAllow : (Array.isArray(sub.allow) ? sub.allow : undefined), + subDeny: Array.isArray(spec.subDeny) ? spec.subDeny : (Array.isArray(sub.deny) ? sub.deny : undefined), + tags: Array.isArray(spec.tags) ? spec.tags : undefined + } + return _pickDefined(raw) +} + +async function parseNatsAccountRuleFile (fileContent, options = {}) { + try { + const doc = yaml.load(fileContent) + if (!doc || doc.kind !== 'NatsAccountRule') { + throw new Errors.ValidationError(`Invalid kind ${doc && doc.kind}, expected NatsAccountRule`) + } + if (doc.metadata == null || doc.spec == null) { + throw new Errors.ValidationError('Invalid YAML format: metadata and spec are required') + } + if (options.isUpdate && options.ruleName && doc.metadata.name !== options.ruleName) { + throw new Errors.ValidationError(`Rule name in YAML (${doc.metadata.name}) doesn't match endpoint path (${options.ruleName})`) + } + const modelFields = _natsAccountRuleSpecToModel(doc.spec) + const result = { + name: doc.metadata.name, + ...doc.spec, + ...modelFields + } + delete result.jetstreamEnabled + delete result.jetstream + delete result.limits + delete result.default_permissions + delete result.info_url + delete result.tiered_limits + return result + } catch (error) { + if (error instanceof Errors.ValidationError) { + throw error + } + throw new Errors.ValidationError(`Error parsing NATS account rule YAML: ${error.message}`) + } +} + +async function parseNatsUserRuleFile (fileContent, options = {}) { + try { + const doc = yaml.load(fileContent) + if (!doc || doc.kind !== 'NatsUserRule') { + throw new Errors.ValidationError(`Invalid kind ${doc && doc.kind}, expected NatsUserRule`) + } + if (doc.metadata == null || doc.spec == null) { + throw new Errors.ValidationError('Invalid YAML format: metadata and spec are required') + } + if (options.isUpdate && options.ruleName && doc.metadata.name !== options.ruleName) { + throw new Errors.ValidationError(`Rule name in YAML (${doc.metadata.name}) doesn't match endpoint path (${options.ruleName})`) + } + const modelFields = _natsUserRuleSpecToModel(doc.spec) + const result = { + name: doc.metadata.name, + ...doc.spec, + ...modelFields + } + delete result.pub + delete result.sub + delete result.resp + delete result.allowed_connection_types + delete result.bearer_token + delete result.proxy_required + delete result.times_location + delete result.subs + delete result.payload + return result + } catch (error) { + if (error instanceof Errors.ValidationError) { + throw error + } + throw new Errors.ValidationError(`Error parsing NATS user rule YAML: ${error.message}`) + } +} + module.exports = { parseAppTemplateFile: parseAppTemplateFile, parseAppFile: parseAppFile, @@ -518,6 +669,8 @@ module.exports = { parseVolumeMountFile: parseVolumeMountFile, parseConfigMapFile: parseConfigMapFile, parseCertificateFile: parseCertificateFile, + parseNatsAccountRuleFile: parseNatsAccountRuleFile, + parseNatsUserRuleFile: parseNatsUserRuleFile, parseServiceFile: parseServiceFile, parseRoleFile: parseRoleFile, parseRoleBindingFile: parseRoleBindingFile, diff --git a/src/templates/nats/leaf.conf b/src/templates/nats/leaf.conf new file mode 100644 index 000000000..889ce111f --- /dev/null +++ b/src/templates/nats/leaf.conf @@ -0,0 +1,43 @@ +port: $NATS_SERVER_PORT +server_name: $SELFNAME +pid_file: /home/runner/run/nats.pid +http_port: $NATS_HTTP_PORT + +# Operator +operator = $OPERATOR_JWT + +# System account +system_account = $SYSTEM_ACCOUNT + +jetstream: { + store_dir: /home/runner/data + domain: $JETSTREAM_DOMAIN + max_memory_store: $NATS_JS_MAX_MEMORY_STORE + max_file_store: $NATS_JS_MAX_FILE_STORE + cipher: chachapoly + key: "$JETSTREAM_KEY" + prev_encryption_key: "$JETSTREAM_PREV_KEY" +} + +leafnodes: { + reconnect: "10s" + remotes: $NATS_LEAF_REMOTES +} + +mqtt: { + port: $NATS_MQTT_PORT + tls: { + ca_file: "$NATS_SSL_DIR/$NATS_MQTT_CERT_NAME/ca.crt" + cert_file: "$NATS_SSL_DIR/$NATS_MQTT_CERT_NAME/tls.crt" + key_file: "$NATS_SSL_DIR/$NATS_MQTT_CERT_NAME/tls.key" + handshake_first: true + timeout: "3s" + } +} + +resolver: { + type: full + dir: "$NATS_JWT_DIR" + allow_delete: false + interval: "10m" +} diff --git a/src/templates/nats/server-no-cluster.conf b/src/templates/nats/server-no-cluster.conf new file mode 100644 index 000000000..d223aa41f --- /dev/null +++ b/src/templates/nats/server-no-cluster.conf @@ -0,0 +1,52 @@ +port: $NATS_SERVER_PORT +server_name: $SELFNAME +pid_file: /home/runner/run/nats.pid +http_port: $NATS_HTTP_PORT + +# Operator +operator = $OPERATOR_JWT + +# System account +system_account = $SYSTEM_ACCOUNT + +jetstream: { + store_dir: /home/runner/data + domain: $JETSTREAM_DOMAIN + max_memory_store: $NATS_JS_MAX_MEMORY_STORE + max_file_store: $NATS_JS_MAX_FILE_STORE + cipher: chachapoly + key: "$JETSTREAM_KEY" + prev_encryption_key: "$JETSTREAM_PREV_KEY" +} + +leafnodes: { + port: $NATS_LEAF_PORT + advertise: $NATS_LEAF_ADVERTISE + tls: { + ca_file: "$NATS_SSL_DIR/$NATS_CERT_NAME/ca.crt" + cert_file: "$NATS_SSL_DIR/$NATS_CERT_NAME/tls.crt" + key_file: "$NATS_SSL_DIR/$NATS_CERT_NAME/tls.key" + handshake_first: true + verify: true + handshake_first: true + timeout: "3s" + } +} + +mqtt: { + port: $NATS_MQTT_PORT + tls: { + ca_file: "$NATS_SSL_DIR/$NATS_MQTT_CERT_NAME/ca.crt" + cert_file: "$NATS_SSL_DIR/$NATS_MQTT_CERT_NAME/tls.crt" + key_file: "$NATS_SSL_DIR/$NATS_MQTT_CERT_NAME/tls.key" + handshake_first: true + timeout: "3s" + } +} + +resolver: { + type: full + dir: "$NATS_JWT_DIR" + allow_delete: false + interval: "2m" +} diff --git a/src/templates/nats/server.conf b/src/templates/nats/server.conf new file mode 100644 index 000000000..6e8150906 --- /dev/null +++ b/src/templates/nats/server.conf @@ -0,0 +1,66 @@ +port: $NATS_SERVER_PORT +server_name: $SELFNAME +pid_file: /home/runner/run/nats.pid +http_port: $NATS_HTTP_PORT + +# Operator +operator = $OPERATOR_JWT + +# System account +system_account = $SYSTEM_ACCOUNT + +jetstream: { + store_dir: /home/runner/data + domain: $JETSTREAM_DOMAIN + max_memory_store: $NATS_JS_MAX_MEMORY_STORE + max_file_store: $NATS_JS_MAX_FILE_STORE + cipher: chachapoly + key: "$JETSTREAM_KEY" + prev_encryption_key: "$JETSTREAM_PREV_KEY" +} + +cluster: { + name: $CONTROLLER_NAME + port: $NATS_CLUSTER_PORT + no_advertise: true + routes: $NATS_CLUSTER_ROUTES + tls: { + ca_file: "$NATS_SSL_DIR/$NATS_CERT_NAME/ca.crt" + cert_file: "$NATS_SSL_DIR/$NATS_CERT_NAME/tls.crt" + key_file: "$NATS_SSL_DIR/$NATS_CERT_NAME/tls.key" + handshake_first: true + verify: true + timeout: "3s" + } +} + +leafnodes: { + port: $NATS_LEAF_PORT + advertise: $NATS_LEAF_ADVERTISE + tls: { + ca_file: "$NATS_SSL_DIR/$NATS_CERT_NAME/ca.crt" + cert_file: "$NATS_SSL_DIR/$NATS_CERT_NAME/tls.crt" + key_file: "$NATS_SSL_DIR/$NATS_CERT_NAME/tls.key" + handshake_first: true + verify: true + timeout: "3s" + } +} + +mqtt: { + port: $NATS_MQTT_PORT + tls: { + ca_file: "$NATS_SSL_DIR/$NATS_MQTT_CERT_NAME/ca.crt" + cert_file: "$NATS_SSL_DIR/$NATS_MQTT_CERT_NAME/tls.crt" + key_file: "$NATS_SSL_DIR/$NATS_MQTT_CERT_NAME/tls.key" + handshake_first: true + timeout: "3s" + } +} + +resolver: { + type: full + dir: "$NATS_JWT_DIR" + allow_delete: false + interval: "2m" +} diff --git a/src/utils/k8s-client.js b/src/utils/k8s-client.js index 7cbdabe34..afbd7597c 100644 --- a/src/utils/k8s-client.js +++ b/src/utils/k8s-client.js @@ -10,7 +10,7 @@ function checkKubernetesEnvironment () { } if (checkKubernetesEnvironment()) { - CONTROLLER_NAMESPACE = process.env.CONTROLLER_NAMESPACE + CONTROLLER_NAMESPACE = process.env.CONTROLLER_NAMESPACE || config.get('app.namespace') // Validate that CONTROLLER_NAMESPACE is set when in Kubernetes mode if (!CONTROLLER_NAMESPACE) { @@ -20,97 +20,180 @@ if (checkKubernetesEnvironment()) { } let k8sApi = null +let k8sAppsApi = null +let k8sModule = null +let kubeConfig = null + +async function getK8sModule () { + if (!k8sModule) { + k8sModule = await import('@kubernetes/client-node') + } + return k8sModule +} async function initializeK8sClient () { if (!k8sApi) { logger.debug('Initializing Kubernetes client') - const k8s = require('@kubernetes/client-node') - const kubeConfig = new k8s.KubeConfig() + const k8s = await getK8sModule() + kubeConfig = new k8s.KubeConfig() - // Use the in-cluster configuration - kubeConfig.loadFromCluster() - // kubeConfig.loadFromDefault() + // Use local kubeconfig when requested (e.g. integration tests); otherwise in-cluster + if (process.env.K8S_USE_LOCAL_KUBECONFIG === 'true' || process.env.K8S_USE_LOCAL_KUBECONFIG === '1') { + kubeConfig.loadFromDefault() + } else { + kubeConfig.loadFromCluster() + } k8sApi = kubeConfig.makeApiClient(k8s.CoreV1Api) + k8sAppsApi = kubeConfig.makeApiClient(k8s.AppsV1Api) logger.info('Kubernetes client initialized successfully') } return k8sApi } -async function getSecret (secretName) { +async function getK8sAppsApi () { + await initializeK8sClient() + return k8sAppsApi +} + +/** + * Returns true if the error indicates a Kubernetes 404 Not Found. + * Handles both axios-style (error.response.status) and body.code/body.reason. + */ +function isK8sNotFound (error) { + if (!error) return false + if (error.response && error.response.status === 404) return true + const body = error.body || (error.response && error.response.body) + if (body && (body.code === 404 || body.reason === 'NotFound')) return true + return false +} + +/** + * Returns true if the error indicates a Kubernetes 409 Conflict. + */ +function isK8sConflict (error) { + if (!error) return false + if (error.response && error.response.status === 409) return true + const body = error.body || (error.response && error.response.body) + if (body && (body.code === 409 || body.reason === 'Conflict')) return true + return false +} + +function _normalizeK8sError (error, context) { + const message = error && (error.message || String(error)) + logger.error(`${context}: ${message}`) + if (error && typeof error.body !== 'undefined') { + logger.error(`Error details: ${JSON.stringify(error.body)}`) + } +} + +function _responseBody (response) { + return response && (response.body !== undefined ? response.body : response) +} + +async function getSecret (secretName, options = {}) { + const { ignoreNotFound = false } = options logger.debug(`Getting secret: ${secretName} in namespace: ${CONTROLLER_NAMESPACE}`) try { const api = await initializeK8sClient() - const response = await api.readNamespacedSecret(secretName, CONTROLLER_NAMESPACE) + const response = await api.readNamespacedSecret({ name: secretName, namespace: CONTROLLER_NAMESPACE }) logger.info(`Successfully retrieved secret: ${secretName}`) - return response.body + return _responseBody(response) } catch (error) { - logger.error(`Failed to get secret ${secretName}: ${error.message}`) + if (ignoreNotFound && isK8sNotFound(error)) { + logger.warn(`Secret ${secretName} not found (expected in some flows)`) + return null + } + _normalizeK8sError(error, `Failed to get secret ${secretName}`) throw error } } -async function getService (serviceName) { +async function getService (serviceName, options = {}) { + const { ignoreNotFound = false } = options logger.debug(`Getting service: ${serviceName} in namespace: ${CONTROLLER_NAMESPACE}`) try { const api = await initializeK8sClient() - const response = await api.readNamespacedService(serviceName, CONTROLLER_NAMESPACE) + const response = await api.readNamespacedService({ name: serviceName, namespace: CONTROLLER_NAMESPACE }) logger.info(`Successfully retrieved service: ${serviceName}`) - return response.body + return _responseBody(response) } catch (error) { - logger.error(`Failed to get service ${serviceName}: ${error.message}`) + if (ignoreNotFound && isK8sNotFound(error)) { + logger.warn(`Service ${serviceName} not found (expected in some flows)`) + return null + } + _normalizeK8sError(error, `Failed to get service ${serviceName}`) throw error } } // ConfigMap methods -async function getConfigMap (configMapName) { +async function getConfigMap (configMapName, options = {}) { + const { ignoreNotFound = false } = options logger.debug(`Getting ConfigMap: ${configMapName} in namespace: ${CONTROLLER_NAMESPACE}`) try { const api = await initializeK8sClient() - const response = await api.readNamespacedConfigMap(configMapName, CONTROLLER_NAMESPACE) + const response = await api.readNamespacedConfigMap({ name: configMapName, namespace: CONTROLLER_NAMESPACE }) logger.info(`Successfully retrieved ConfigMap: ${configMapName}`) - return response.body + return _responseBody(response) } catch (error) { - logger.error(`Failed to get ConfigMap ${configMapName}: ${error.message}`) + if (ignoreNotFound && isK8sNotFound(error)) { + logger.warn(`ConfigMap ${configMapName} not found (expected in some flows)`) + return null + } + _normalizeK8sError(error, `Failed to get ConfigMap ${configMapName}`) throw error } } -async function patchConfigMap (configMapName, patchData) { +function _jsonPointerEscape (key) { + return key.replace(/~/g, '~0').replace(/\//g, '~1') +} + +async function patchConfigMap (configMapName, patchData, options = {}) { + const { ignoreNotFound = false } = options logger.debug(`Patching ConfigMap: ${configMapName} in namespace: ${CONTROLLER_NAMESPACE}`) try { const api = await initializeK8sClient() + const k8s = await getK8sModule() - // Create JSON Patch operation with formatted JSON - const patch = [ - { - op: 'replace', - path: '/data/skrouterd.json', - value: typeof patchData.data['skrouterd.json'] === 'string' - ? JSON.stringify(JSON.parse(patchData.data['skrouterd.json']), null, 2) - : JSON.stringify(patchData.data['skrouterd.json'], null, 2) + const data = patchData.data || {} + const patch = Object.entries(data).map(([key, value]) => { + const path = '/data/' + _jsonPointerEscape(key) + let strValue = typeof value === 'string' ? value : JSON.stringify(value) + if (key === 'skrouterd.json' && typeof value !== 'string') { + strValue = JSON.stringify(value, null, 2) + } else if (key === 'skrouterd.json' && typeof value === 'string') { + try { + strValue = JSON.stringify(JSON.parse(value), null, 2) + } catch (_) { + strValue = value + } } - ] - - const { body: configMap } = await api.patchNamespacedConfigMap( - configMapName, - CONTROLLER_NAMESPACE, - patch, - undefined, - undefined, - undefined, - undefined, - undefined, - { headers: { 'content-type': 'application/json-patch+json' } } + return { op: 'replace', path, value: strValue } + }) + + if (patch.length === 0) { + logger.warn('patchConfigMap called with no data keys') + const response = await api.readNamespacedConfigMap({ name: configMapName, namespace: CONTROLLER_NAMESPACE }) + return _responseBody(response) + } + + const patchOptions = (typeof k8s.setHeaderOptions === 'function' && k8s.PatchStrategy) != null + ? k8s.setHeaderOptions('Content-Type', k8s.PatchStrategy.JsonPatch) + : { headers: { 'Content-Type': 'application/json-patch+json' } } + + const response = await api.patchNamespacedConfigMap( + { name: configMapName, namespace: CONTROLLER_NAMESPACE, body: patch }, + patchOptions ) logger.info(`Successfully patched ConfigMap: ${configMapName}`) - return configMap + return _responseBody(response) } catch (error) { - logger.error(`Failed to patch ConfigMap ${configMapName}: ${error.message}`) - if (error.response) { - logger.error(`Response status: ${error.response.status}`) - logger.error(`Response body: ${JSON.stringify(error.response.body)}`) + if (ignoreNotFound && isK8sNotFound(error)) { + logger.warn(`ConfigMap ${configMapName} not found (expected in some flows, e.g. before operator creates it)`) + return null } + _normalizeK8sError(error, `Failed to patch ConfigMap ${configMapName}`) throw error } } @@ -120,11 +203,12 @@ async function getNamespacedServices () { logger.debug(`Listing services in namespace: ${CONTROLLER_NAMESPACE}`) try { const api = await initializeK8sClient() - const response = await api.listNamespacedService(CONTROLLER_NAMESPACE) - logger.info(`Successfully retrieved ${response.body.items.length} services in namespace: ${CONTROLLER_NAMESPACE}`) - return response.body + const response = await api.listNamespacedService({ namespace: CONTROLLER_NAMESPACE }) + const body = _responseBody(response) + logger.info(`Successfully retrieved ${body && body.items ? body.items.length : 0} services in namespace: ${CONTROLLER_NAMESPACE}`) + return body } catch (error) { - logger.error(`Failed to list services in namespace ${CONTROLLER_NAMESPACE}: ${error.message}`) + _normalizeK8sError(error, `Failed to list services in namespace ${CONTROLLER_NAMESPACE}`) throw error } } @@ -133,28 +217,34 @@ async function createService (serviceSpec) { logger.debug(`Creating service in namespace: ${CONTROLLER_NAMESPACE}`) try { const api = await initializeK8sClient() - const response = await api.createNamespacedService(CONTROLLER_NAMESPACE, serviceSpec) - logger.info(`Successfully created service: ${response.body.metadata.name} in namespace: ${CONTROLLER_NAMESPACE}`) - return response.body + const response = await api.createNamespacedService({ namespace: CONTROLLER_NAMESPACE, body: serviceSpec }) + const body = _responseBody(response) + logger.info(`Successfully created service: ${body && body.metadata ? body.metadata.name : '?'} in namespace: ${CONTROLLER_NAMESPACE}`) + return body } catch (error) { - logger.error(`Failed to create service in namespace ${CONTROLLER_NAMESPACE}: ${error.message}`) - if (error.response) { - logger.error(`Response status: ${error.response.status}`) - logger.error(`Response body: ${JSON.stringify(error.response.body)}`) + if (isK8sConflict(error)) { + logger.warn(`Service already exists (409 Conflict) in namespace ${CONTROLLER_NAMESPACE}`) + } else { + _normalizeK8sError(error, `Failed to create service in namespace ${CONTROLLER_NAMESPACE}`) } throw error } } -async function deleteService (serviceName) { +async function deleteService (serviceName, options = {}) { + const { ignoreNotFound = false } = options logger.debug(`Deleting service: ${serviceName} in namespace: ${CONTROLLER_NAMESPACE}`) try { const api = await initializeK8sClient() - const response = await api.deleteNamespacedService(serviceName, CONTROLLER_NAMESPACE) + const response = await api.deleteNamespacedService({ name: serviceName, namespace: CONTROLLER_NAMESPACE }) logger.info(`Successfully deleted service: ${serviceName} from namespace: ${CONTROLLER_NAMESPACE}`) - return response.body + return _responseBody(response) } catch (error) { - logger.error(`Failed to delete service ${serviceName}: ${error.message}`) + if (ignoreNotFound && isK8sNotFound(error)) { + logger.warn(`Service ${serviceName} not found during delete (may have already been deleted)`) + return null + } + _normalizeK8sError(error, `Failed to delete service ${serviceName}`) throw error } } @@ -169,17 +259,18 @@ async function updateService (serviceName, patchData) { logger.debug(`Updating service: ${serviceName} in namespace: ${CONTROLLER_NAMESPACE}`) try { const api = await initializeK8sClient() + const k8s = await getK8sModule() const patch = [] // Update spec fields - if (patchData.spec.type) { + if (patchData.spec && patchData.spec.type) { patch.push({ op: 'replace', path: '/spec/type', value: patchData.spec.type }) } - if (patchData.spec.selector) { + if (patchData.spec && patchData.spec.selector) { patch.push({ op: 'replace', path: '/spec/selector', value: patchData.spec.selector }) } - if (patchData.spec.ports) { + if (patchData.spec && patchData.spec.ports) { patch.push({ op: 'replace', path: '/spec/ports', value: patchData.spec.ports }) } @@ -187,24 +278,22 @@ async function updateService (serviceName, patchData) { if (patchData.metadata && patchData.metadata.annotations) { patch.push({ op: 'replace', path: '/metadata/annotations', value: patchData.metadata.annotations }) } + + const patchOptions = (typeof k8s.setHeaderOptions === 'function' && k8s.PatchStrategy) != null + ? k8s.setHeaderOptions('Content-Type', k8s.PatchStrategy.JsonPatch) + : { headers: { 'Content-Type': 'application/json-patch+json' } } + const response = await api.patchNamespacedService( - serviceName, - CONTROLLER_NAMESPACE, - patch, - undefined, - undefined, - undefined, - undefined, - undefined, - { headers: { 'Content-Type': 'application/json-patch+json' } } + { name: serviceName, namespace: CONTROLLER_NAMESPACE, body: patch }, + patchOptions ) logger.info(`Successfully updated service: ${serviceName} in namespace: ${CONTROLLER_NAMESPACE}`) - return response.body + return _responseBody(response) } catch (error) { - logger.error(`Failed to update service ${serviceName}: ${error.message}`) - if (error.response) { - logger.error(`Response status: ${error.response.status}`) - logger.error(`Response body: ${JSON.stringify(error.response.body)}`) + if (isK8sNotFound(error)) { + logger.warn(`Service ${serviceName} not found during update`) + } else { + _normalizeK8sError(error, `Failed to update service ${serviceName}`) } throw error } @@ -223,8 +312,8 @@ async function watchLoadBalancerIP (serviceName, maxRetries = 10, retryInterval for (let attempt = 0; attempt < maxRetries; attempt++) { try { - const response = await api.readNamespacedService(serviceName, CONTROLLER_NAMESPACE) - const service = response.body + const response = await api.readNamespacedService({ name: serviceName, namespace: CONTROLLER_NAMESPACE }) + const service = _responseBody(response) // Check if the service type is LoadBalancer if (service.spec && service.spec.type === 'LoadBalancer') { @@ -252,8 +341,11 @@ async function watchLoadBalancerIP (serviceName, maxRetries = 10, retryInterval // Wait before next retry await new Promise(resolve => setTimeout(resolve, retryInterval)) } catch (error) { - logger.error(`Error getting LoadBalancer IP for service ${serviceName}: ${error.message}`) - // Wait before next retry even if there's an error + if (isK8sNotFound(error)) { + logger.warn(`Service ${serviceName} not found while watching LoadBalancer IP`) + } else { + logger.error(`Error getting LoadBalancer IP for service ${serviceName}: ${error && error.message ? error.message : error}`) + } await new Promise(resolve => setTimeout(resolve, retryInterval)) } } @@ -262,7 +354,58 @@ async function watchLoadBalancerIP (serviceName, maxRetries = 10, retryInterval return null } +/** + * Trigger a rollout of a StatefulSet by patching the pod template annotation + * kubectl.kubernetes.io/restartedAt to the current timestamp (RFC3339). + * There is no direct rollout API; changing the pod template causes the controller to rolling-update. + * @param {string} statefulSetName - Name of the StatefulSet + * @returns {Promise} The patched StatefulSet + */ +async function rolloutStatefulSet (statefulSetName) { + if (!CONTROLLER_NAMESPACE) { + throw new Error('CONTROLLER_NAMESPACE is not set; cannot rollout StatefulSet') + } + logger.debug(`Rolling out StatefulSet: ${statefulSetName} in namespace: ${CONTROLLER_NAMESPACE}`) + try { + const api = await getK8sAppsApi() + const k8s = await getK8sModule() + const restartedAt = new Date().toISOString() + const patch = { + spec: { + template: { + metadata: { + annotations: { + 'kubectl.kubernetes.io/restartedAt': restartedAt + } + } + } + } + } + const patchOptions = (typeof k8s.setHeaderOptions === 'function' && k8s.PatchStrategy) != null + ? k8s.setHeaderOptions('Content-Type', 'application/merge-patch+json') + : { headers: { 'Content-Type': 'application/merge-patch+json' } } + const response = await api.patchNamespacedStatefulSet( + { name: statefulSetName, namespace: CONTROLLER_NAMESPACE, body: patch }, + patchOptions + ) + const body = _responseBody(response) + logger.info(`Successfully rolled out StatefulSet: ${statefulSetName}`) + return body + } catch (error) { + if (isK8sNotFound(error)) { + logger.warn(`StatefulSet ${statefulSetName} not found during rollout`) + } else if (isK8sConflict(error)) { + logger.warn(`StatefulSet ${statefulSetName} conflict during rollout (409)`) + } else { + _normalizeK8sError(error, `Failed to rollout StatefulSet ${statefulSetName}`) + } + throw error + } +} + module.exports = { + isK8sNotFound, + isK8sConflict, getSecret, getService, getConfigMap, @@ -272,5 +415,6 @@ module.exports = { deleteService, updateService, watchLoadBalancerIP, - checkKubernetesEnvironment + checkKubernetesEnvironment, + rolloutStatefulSet } diff --git a/src/websocket/server.js b/src/websocket/server.js index 16c49bddc..8ede8b036 100644 --- a/src/websocket/server.js +++ b/src/websocket/server.js @@ -1,6 +1,6 @@ const WebSocket = require('ws') const config = require('../config') -const logger = require('../logger') +const baseLogger = require('../logger') const Errors = require('../helpers/errors') const SessionManager = require('./session-manager') const LogSessionManager = require('./log-session-manager') @@ -19,6 +19,7 @@ const MicroserviceLogStatusManager = require('../data/managers/microservice-log- const FogLogStatusManager = require('../data/managers/fog-log-status-manager') const ChangeTrackingService = require('../services/change-tracking-service') const FogManager = require('../data/managers/iofog-manager') +const FogStates = require('../enums/fog-state') const MESSAGE_TYPES = { STDIN: 0, @@ -35,6 +36,115 @@ const MESSAGE_TYPES = { const EventService = require('../services/event-service') +let processErrorHandlersRegistered = false + +function safeSerializeForLog (value) { + try { + return JSON.parse(JSON.stringify(value)) + } catch (error) { + return { + serializationError: error.message, + type: value && value.constructor ? value.constructor.name : typeof value, + asString: String(value) + } + } +} + +function formatErrorForLog (errorLike) { + if (errorLike instanceof Error) { + return { + type: 'Error', + name: errorLike.name, + message: errorLike.message, + stack: errorLike.stack, + cause: errorLike.cause ? formatErrorForLog(errorLike.cause) : undefined + } + } + + if (typeof errorLike === 'string') { + return { + type: 'string', + message: errorLike + } + } + + if (typeof errorLike === 'object' && errorLike !== null) { + return { + type: errorLike.constructor ? errorLike.constructor.name : 'object', + details: safeSerializeForLog(errorLike) + } + } + + return { + type: typeof errorLike, + details: errorLike + } +} + +function normalizeErrorLogArgs (args) { + if (!Array.isArray(args) || args.length === 0) { + return args + } + + const [first, ...rest] = args + + if (args.length === 1) { + if (first instanceof Error) { + return [{ + msg: first.message || 'Error', + error: formatErrorForLog(first) + }] + } + return args + } + + if (typeof first === 'string') { + const payload = { msg: first } + const context = {} + const additional = [] + + for (const item of rest) { + if (item instanceof Error && !payload.error) { + payload.error = formatErrorForLog(item) + continue + } + + if (typeof item === 'object' && item !== null) { + Object.assign(context, safeSerializeForLog(item)) + continue + } + + additional.push(item) + } + + if (Object.keys(context).length > 0) { + payload.context = context + } + if (additional.length > 0) { + payload.args = additional + } + + return [payload] + } + + return args +} + +function createSafeLogger (loggerInstance) { + return new Proxy(loggerInstance, { + get (target, prop, receiver) { + const original = Reflect.get(target, prop, receiver) + if (prop !== 'error' || typeof original !== 'function') { + return original + } + + return (...args) => original.apply(target, normalizeErrorLogArgs(args)) + } + }) +} + +const logger = createSafeLogger(baseLogger) + class WebSocketServer { constructor () { this.wss = null @@ -212,22 +322,29 @@ class WebSocketServer { } }) - // Add global error handler for the server - process.on('uncaughtException', (error) => { - logger.error('Uncaught exception in WebSocket server:' + JSON.stringify({ - error: error.message, - stack: error.stack - })) - // Don't let the error crash the process - }) + // Register process-level handlers once to avoid duplicate logs. + if (!processErrorHandlersRegistered) { + process.on('uncaughtException', (error) => { + logger.error({ + msg: 'Uncaught exception in process (registered by WebSocket server)', + error: formatErrorForLog(error) + }) + // Don't let the error crash the process + }) - process.on('unhandledRejection', (reason, promise) => { - logger.error('Unhandled rejection in WebSocket server:' + JSON.stringify({ - reason: reason, - promise: promise - })) - // Don't let the error crash the process - }) + process.on('unhandledRejection', (reason, promise) => { + logger.error({ + msg: 'Unhandled rejection in process (registered by WebSocket server)', + reason: formatErrorForLog(reason), + promise: { + type: promise && promise.constructor ? promise.constructor.name : typeof promise + } + }) + // Don't let the error crash the process + }) + + processErrorHandlersRegistered = true + } this.sessionManager.startCleanup() } @@ -2318,10 +2435,24 @@ class WebSocketServer { if (microserviceUuid) { // Validate microservice and check if it matches expected system type await this.validateMicroservice(microserviceUuid, expectSystem, transaction) + + const statusArr = await MicroserviceStatusManager.findAllExcludeFields({ + microserviceUuid: microserviceUuid + }, transaction) + if (!statusArr || statusArr.length === 0) { + throw new Errors.NotFoundError('Microservice status not found') + } + const status = statusArr[0] + if (status.status !== microserviceState.RUNNING) { + throw new Errors.ValidationError('Microservice is not running') + } } if (fogUuid) { - await this.validateFog(fogUuid, transaction) + const fog = await this.validateFog(fogUuid, transaction) + if (fog.daemonStatus !== FogStates.RUNNING) { + throw new Errors.ValidationError('Fog is not running') + } } // 3. RBAC Authorization is handled at route level, so we just validate resources here diff --git a/test/src/controllers/microservices-controller.test.js b/test/src/controllers/microservices-controller.test.js index 1922919e7..e227628b2 100644 --- a/test/src/controllers/microservices-controller.test.js +++ b/test/src/controllers/microservices-controller.test.js @@ -32,9 +32,6 @@ describe('Microservices Controller', () => { publicMode: true, }, ]) - def('routes', () => [ - 'testAnotherUuid', - ]) def('req', () => ({ body: { @@ -47,7 +44,6 @@ describe('Microservices Controller', () => { logSize: $logSize, volumeMappings: $volumeMappings, ports: $ports, - routes: $routes, }, })) @@ -70,7 +66,6 @@ describe('Microservices Controller', () => { logSize: $logSize, volumeMappings: $volumeMappings, ports: $ports, - routes: $routes, }, $user, false) }) @@ -281,86 +276,6 @@ describe('Microservices Controller', () => { }) }) - describe('.createMicroserviceRouteEndPoint()', () => { - def('user', () => 'user!') - def('uuid', () => 'testUuid') - def('receiverUuid', () => 'testReceiverUuid') - - def('req', () => ({ - params: { - uuid: $uuid, - receiverUuid: $receiverUuid, - }, - })) - def('response', () => Promise.resolve()) - def('subject', () => $subject.createMicroserviceRouteEndPoint($req, $user)) - - beforeEach(() => { - $sandbox.stub(MicroservicesService, 'createRouteEndPoint').returns($response) - }) - - it('calls MicroservicesService.createRouteEndPoint with correct args', async () => { - await $subject - expect(MicroservicesService.createRouteEndPoint).to.have.been.calledWith($uuid, $receiverUuid, $user, false) - }) - - context('when MicroservicesService#createRouteEndPoint fails', () => { - const error = 'Error!' - - def('response', () => Promise.reject(error)) - - it(`fails with "${error}"`, () => { - return expect($subject).to.be.rejectedWith(error) - }) - }) - - context('when MicroservicesService#createRouteEndPoint succeeds', () => { - it(`succeeds`, () => { - return expect($subject).to.eventually.equal(undefined) - }) - }) - }) - - describe('deleteMicroserviceRouteEndPoint()', () => { - def('user', () => 'user!') - def('uuid', () => 'testUuid') - def('receiverUuid', () => 'testReceiverUuid') - - def('req', () => ({ - params: { - uuid: $uuid, - receiverUuid: $receiverUuid, - }, - })) - def('response', () => Promise.resolve()) - def('subject', () => $subject.deleteMicroserviceRouteEndPoint($req, $user)) - - beforeEach(() => { - $sandbox.stub(MicroservicesService, 'deleteRouteEndPoint').returns($response) - }) - - it('calls MicroservicesService.deleteRouteEndPoint with correct args', async () => { - await $subject - expect(MicroservicesService.deleteRouteEndPoint).to.have.been.calledWith($uuid, $receiverUuid, $user, false) - }) - - context('when MicroservicesService#deleteRouteEndPoint fails', () => { - const error = 'Error!' - - def('response', () => Promise.reject(error)) - - it(`fails with "${error}"`, () => { - return expect($subject).to.be.rejectedWith(error) - }) - }) - - context('when MicroservicesService#deleteRouteEndPoint succeeds', () => { - it(`succeeds`, () => { - return expect($subject).to.eventually.equal(undefined) - }) - }) - }) - describe('createMicroservicePortMappingEndPoint.()', () => { def('user', () => 'user!') def('uuid', () => 'testUuid') diff --git a/test/src/controllers/nats-controller.test.js b/test/src/controllers/nats-controller.test.js new file mode 100644 index 000000000..c2ef51e21 --- /dev/null +++ b/test/src/controllers/nats-controller.test.js @@ -0,0 +1,379 @@ +const { expect } = require('chai') +const sinon = require('sinon') + +const NatsController = require('../../../src/controllers/nats-controller') +const NatsApiService = require('../../../src/services/nats-api-service') +const Errors = require('../../../src/helpers/errors') + +describe('NATS Controller', () => { + def('subject', () => NatsController) + def('sandbox', () => sinon.createSandbox()) + + afterEach(() => $sandbox.restore()) + + describe('.getOperatorEndPoint()', () => { + const operator = { + name: 'datasance', + publicKey: 'OPUB123', + jwt: 'OPJWT' + } + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'getOperator').returns(Promise.resolve(operator)) + }) + + it('should return operator metadata', async () => { + const response = await $subject.getOperatorEndPoint() + expect(response).to.eql({ + name: operator.name, + publicKey: operator.publicKey, + jwt: operator.jwt + }) + }) + }) + + describe('.rotateOperatorEndPoint()', () => { + const operator = { + name: 'datasance', + publicKey: 'OPUB456', + jwt: 'OPJWT2' + } + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'rotateOperator').returns(Promise.resolve(operator)) + }) + + it('should return rotated operator metadata', async () => { + const response = await $subject.rotateOperatorEndPoint() + expect(response).to.eql({ + name: operator.name, + publicKey: operator.publicKey, + jwt: operator.jwt + }) + }) + }) + + describe('.getHubEndPoint()', () => { + const hub = { + host: 'hub-host', + serverPort: 4222, + clusterPort: 6222, + leafPort: 7422, + mqttPort: 8883, + httpPort: 8222 + } + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'getHub').returns(Promise.resolve(hub)) + }) + + it('should return hub metadata', async () => { + const response = await $subject.getHubEndPoint() + expect(response).to.eql(hub) + }) + }) + + describe('.upsertHubEndPoint()', () => { + const hub = { + host: 'hub-host', + serverPort: 4222, + clusterPort: 6222, + leafPort: 7422, + mqttPort: 8883, + httpPort: 8222 + } + + def('req', () => ({ + body: { + host: hub.host + } + })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'upsertHub').returns(Promise.resolve(hub)) + }) + + it('should return upserted hub metadata', async () => { + const response = await $subject.upsertHubEndPoint($req) + expect(response).to.eql(hub) + }) + }) + + describe('.listAccountsEndPoint()', () => { + const payload = { accounts: [{ id: 1, name: 'app1' }] } + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'listAccounts').returns(Promise.resolve(payload)) + }) + + it('should map accounts list', async () => { + const response = await $subject.listAccountsEndPoint() + expect(response).to.eql(payload) + }) + }) + + describe('.getAccountEndPoint()', () => { + const account = { id: 4, name: 'app2' } + + def('req', () => ({ + params: { appName: 'app2' } + })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'getAccount').returns(Promise.resolve(account)) + }) + + it('should return account metadata', async () => { + const response = await $subject.getAccountEndPoint($req) + expect(response).to.eql(account) + }) + }) + + describe('.ensureAccountEndPoint()', () => { + const account = { id: 5, name: 'app-ensure' } + + def('req', () => ({ + params: { appName: 'app-ensure' }, + body: { natsRule: 'default-account' } + })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'ensureAccount').returns(Promise.resolve(account)) + }) + + it('should pass appName and body to ensureAccount', async () => { + const response = await $subject.ensureAccountEndPoint($req) + expect(response).to.eql(account) + expect(NatsApiService.ensureAccount).to.have.been.calledWith('app-ensure', { natsRule: 'default-account' }) + }) + }) + + describe('.listAllUsersEndPoint()', () => { + const payload = { + users: [ + { id: 1, name: 'u1', accountId: 10, accountName: 'acc1', applicationId: 100, applicationName: 'app1', isBearer: false, microserviceUuid: null } + ] + } + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'listAllUsers').returns(Promise.resolve(payload)) + }) + + it('should return all users with account/application context', async () => { + const response = await $subject.listAllUsersEndPoint() + expect(response).to.eql(payload) + expect(NatsApiService.listAllUsers).to.have.been.calledOnce() + }) + }) + + describe('.listUsersEndPoint()', () => { + def('req', () => ({ params: { appName: 'app4' } })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'listUsers').returns(Promise.resolve({ users: [] })) + }) + + it('should return users for account', async () => { + const response = await $subject.listUsersEndPoint($req) + expect(response.users).to.eql([]) + expect(NatsApiService.listUsers).to.have.been.calledWith('app4') + }) + }) + + describe('.createUserEndPoint()', () => { + const user = { + id: 12, + name: 'user1', + publicKey: 'UPUB', + jwt: 'UJWT', + isBearer: false + } + + def('req', () => ({ + params: { appName: 'app3' }, + body: { name: user.name, expiresIn: '7d' } + })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'createUser').returns(Promise.resolve(user)) + }) + + it('should create and return user metadata', async () => { + const response = await $subject.createUserEndPoint($req) + expect(response).to.eql({ + id: user.id, + name: user.name, + publicKey: user.publicKey, + jwt: user.jwt, + isBearer: user.isBearer + }) + expect(NatsApiService.createUser).to.have.been.calledWith('app3', { name: user.name, expiresIn: '7d' }) + }) + + it('should pass only name, expiresIn, natsRule to createUser (external user, no microserviceUuid)', async () => { + const reqWithRule = { + params: { appName: 'app3' }, + body: { name: 'ext-user', expiresIn: '1d', natsRule: 'default-user' } + } + await $subject.createUserEndPoint(reqWithRule) + expect(NatsApiService.createUser).to.have.been.calledWith('app3', { name: 'ext-user', expiresIn: '1d', natsRule: 'default-user' }) + }) + }) + + describe('.getUserCredsEndPoint()', () => { + const secret = { credsBase64: 'Q1JFRFM=' } + + def('req', () => ({ + params: { appName: 'app5', userName: 'user-creds' } + })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'getUserCreds').returns(Promise.resolve(secret)) + }) + + it('should return creds as base64 payload', async () => { + const response = await $subject.getUserCredsEndPoint($req) + expect(response).to.eql(secret) + expect(response).to.have.property('credsBase64') + expect(response).to.not.have.property('creds') + }) + }) + + describe('.deleteUserEndPoint()', () => { + def('req', () => ({ + params: { appName: 'app7', userName: 'user-del' } + })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'deleteUser').returns(Promise.resolve()) + }) + + it('should call deleteUser with appName and userName', async () => { + await $subject.deleteUserEndPoint($req) + expect(NatsApiService.deleteUser).to.have.been.calledWith('app7', 'user-del') + }) + }) + + describe('.deleteMqttBearerEndPoint()', () => { + def('req', () => ({ + params: { appName: 'app8', userName: 'mqtt-del' } + })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'deleteMqttBearer').returns(Promise.resolve()) + }) + + it('should call deleteMqttBearer with appName and userName', async () => { + await $subject.deleteMqttBearerEndPoint($req) + expect(NatsApiService.deleteMqttBearer).to.have.been.calledWith('app8', 'mqtt-del') + }) + }) + + describe('.createMqttBearerEndPoint()', () => { + const user = { id: 11, name: 'mqtt-user', publicKey: 'MPUB' } + const bearerJwt = 'MJW' + + def('req', () => ({ + params: { appName: 'app6' }, + body: { name: user.name, expiresIn: '7d' } + })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'createMqttBearer').returns(Promise.resolve({ + id: user.id, + name: user.name, + publicKey: user.publicKey, + jwt: bearerJwt + })) + }) + + it('should return bearer JWT', async () => { + const response = await $subject.createMqttBearerEndPoint($req) + expect(response).to.eql({ + id: user.id, + name: user.name, + publicKey: user.publicKey, + jwt: bearerJwt + }) + expect(NatsApiService.createMqttBearer).to.have.been.calledWith('app6', { name: user.name, expiresIn: '7d' }) + }) + }) + + describe('.listAccountRulesEndPoint()', () => { + beforeEach(() => { + $sandbox.stub(NatsApiService, 'listAccountRules').returns(Promise.resolve({ + rules: [{ name: 'default-system-account-rule' }, { name: 'default-application-account-rule' }, { name: 'acc-rule' }] + })) + }) + + it('should return account rule list', async () => { + const response = await $subject.listAccountRulesEndPoint() + expect(response.rules.some((rule) => rule.name === 'default-system-account-rule')).to.eql(true) + expect(response.rules.some((rule) => rule.name === 'default-application-account-rule')).to.eql(true) + expect(response.rules.some((rule) => rule.name === 'acc-rule')).to.eql(true) + }) + }) + + describe('.createAccountRuleEndPoint()', () => { + def('req', () => ({ + body: { name: 'default-system-account-rule' } + })) + + it('rejects reserved rule names', async () => { + $sandbox.stub(NatsApiService, 'createAccountRule').throws(new Errors.ValidationError('Rule default-system-account-rule is reserved and immutable')) + try { + await $subject.createAccountRuleEndPoint($req) + } catch (error) { + expect(error).to.be.instanceof(Errors.ValidationError) + expect(error.message).to.contain('reserved and immutable') + } + }) + }) + + describe('.updateUserRuleEndPoint()', () => { + def('req', () => ({ + params: { ruleName: 'user-rule' }, + body: { maxSubscriptions: 100 } + })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'updateUserRule').returns(Promise.resolve({ id: 11, name: 'user-rule', maxSubscriptions: 100 })) + }) + + it('reissues user JWTs after rule update', async () => { + const response = await $subject.updateUserRuleEndPoint($req) + expect(response.maxSubscriptions).to.eql(100) + expect(NatsApiService.updateUserRule).to.have.been.calledWith('user-rule', { maxSubscriptions: 100 }) + }) + }) + + describe('.deleteAccountRuleEndPoint()', () => { + def('req', () => ({ + params: { ruleName: 'custom-acc-rule' } + })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'deleteAccountRule').returns(Promise.resolve()) + }) + + it('falls back bound applications and schedules reissue', async () => { + await $subject.deleteAccountRuleEndPoint($req) + expect(NatsApiService.deleteAccountRule).to.have.been.calledWith('custom-acc-rule') + }) + }) + + describe('.deleteUserRuleEndPoint()', () => { + def('req', () => ({ + params: { ruleName: 'custom-user-rule' } + })) + + beforeEach(() => { + $sandbox.stub(NatsApiService, 'deleteUserRule').returns(Promise.resolve()) + }) + + it('falls back bound microservices and schedules reissue', async () => { + await $subject.deleteUserRuleEndPoint($req) + expect(NatsApiService.deleteUserRule).to.have.been.calledWith('custom-user-rule') + }) + }) +}) diff --git a/test/src/helpers/system-naming.test.js b/test/src/helpers/system-naming.test.js new file mode 100644 index 000000000..da800c3df --- /dev/null +++ b/test/src/helpers/system-naming.test.js @@ -0,0 +1,15 @@ +const { expect } = require('chai') + +const { slugifyName } = require('../../../src/helpers/system-naming') + +describe('System Naming Helper', () => { + describe('.slugifyName()', () => { + it('normalizes readable names', () => { + expect(slugifyName('My App_Name 01')).to.eql('my-app-name-01') + }) + + it('returns default on empty values', () => { + expect(slugifyName(' ')).to.eql('default') + }) + }) +}) diff --git a/test/src/services/agent-service.test.js b/test/src/services/agent-service.test.js index 8c73493df..95b80bf27 100644 --- a/test/src/services/agent-service.test.js +++ b/test/src/services/agent-service.test.js @@ -967,10 +967,6 @@ describe('Agent Service', () => { const transaction = {} const error = 'Error!' - const routes = [] - - const isConsumer = false - const extraHost = { name: 'testExtraHost', value: '1.2.3.4' @@ -998,7 +994,6 @@ describe('Agent Service', () => { id: 10, }, }, - routes: routes, env: [ { key: 'ENV_VAR1', @@ -1040,7 +1035,6 @@ describe('Agent Service', () => { id: 10, }, }, - routes: routes, } @@ -1058,7 +1052,6 @@ describe('Agent Service', () => { imageSnapshot: 'testImageSnapshot', delete: false, deleteWithCleanup: false, - routes: routes, registryId: 10, env: [ { @@ -1070,7 +1063,6 @@ describe('Agent Service', () => { 'ls', '-l', ], - isConsumer, extraHosts: [`${extraHost.name}:${extraHost.value}`] }], } @@ -1088,14 +1080,10 @@ describe('Agent Service', () => { def('subject', () => $subject.getAgentMicroservices($fog, transaction)) def('findAllMicroservicesResponse', () => Promise.resolve([microserviceWithValidImage, microserviceWithInvalidImage])) - def('getPhysicalConnectionsResponse', () => Promise.resolve(routes)) def('updateResponse', () => Promise.resolve([])) - def('isConsumerResponse', () => Promise.resolve(isConsumer)) beforeEach(() => { $sandbox.stub(MicroserviceManager, 'findAllActiveApplicationMicroservices').returns($findAllMicroservicesResponse) - $sandbox.stub(MicroserviceService, 'getReceiverMicroservices').returns($getPhysicalConnectionsResponse) - $sandbox.stub(MicroserviceService, 'isMicroserviceConsumer').returns($isConsumerResponse) $sandbox.stub(MicroserviceManager, 'update').returns($updateResponse) }) @@ -1113,22 +1101,7 @@ describe('Agent Service', () => { }) context('when MicroserviceManager#findAllActiveApplicationMicroservices() succeeds', () => { - it('calls MicroserviceService.getReceiverMicroservices with correct args', async () => { - await $subject - expect(MicroserviceService.getReceiverMicroservices).to.have.been.calledWith(microserviceWithValidImage, transaction) - }) - - context('when MicroserviceService#getReceiverMicroservices fails', () => { - const error = 'Error!' - - def('getReceiverMicroservices', () => error) - - it(`fails with "${error}"`, () => { - return expect($subject).to.be.rejectedWith = (error) - }) - }) - - context('when MicroserviceService#getPhysicalConnections succeeds', () => { + context('when MicroserviceManager#update succeeds', () => { it('calls MicroserviceManager.update with correct args', async () => { await $subject expect(MicroserviceManager.update).to.have.been.calledWith({ @@ -1161,8 +1134,6 @@ describe('Agent Service', () => { const transaction = {} const error = 'Error!' - const routes = [] - const microservice = { uuid: 'testMicroserviceUuid', imageId: 'testContainerImage', @@ -1175,7 +1146,6 @@ describe('Agent Service', () => { imageSnapshot: 'testImageSnapshot', delete: false, deleteWithCleanup: false, - routes: routes, registryId: 10, } diff --git a/test/src/services/application-service.test.js b/test/src/services/application-service.test.js index a5e696576..f1904d1f9 100644 --- a/test/src/services/application-service.test.js +++ b/test/src/services/application-service.test.js @@ -7,7 +7,6 @@ const AppHelper = require('../../../src/helpers/app-helper') const Validator = require('../../../src/schemas') const ChangeTrackingService = require('../../../src/services/change-tracking-service') const MicroserviceService = require('../../../src/services/microservices-service') -const RoutingService = require('../../../src/services/routing-service') const Sequelize = require('sequelize') const Op = Sequelize.Op const ErrorMessages = require('../../../src/helpers/error-messages') @@ -158,28 +157,6 @@ describe('Application Service', () => { }) }) - context('when there are routes to deploy', () => { - const routes = [{ - name: 'test-msvc', - },{ - name: 'test-msvc-2', - }] - const data = { - ...applicationData, - routes - } - def('subject', () => ApplicationService.createApplicationEndPoint(data, user, isCLI, transaction)) - beforeEach(() => { - $sandbox.stub(RoutingService, 'createRouting') - }) - - it('Should create the routes', async () => { - await $subject - for (const routeData of routes) { - expect(RoutingService.createRouting).to.have.been.calledWith({ ...routeData, application: response.name }, user, isCLI, transaction) - } - }) - }) }) describe('.deleteApplicationEndPoint()', () => { @@ -476,34 +453,6 @@ describe('Application Service', () => { }) }) - context('when there are routes to update', () => { - const newRoute = { name: 'new-route' } - const oldRoute = { name: 'old-route' } - const routes = [{ - name: 'test-msvc', - },{ - name: 'test-msvc-2', - }] - const data = { - ...applicationData, - routes: [...routes, newRoute] - } - def('subject', () => ApplicationService.updateApplicationEndPoint(data, name, user, isCLI, transaction)) - beforeEach(() => { - $sandbox.stub(RoutingService, 'createRouting') - $sandbox.stub(RoutingService, 'updateRouting') - $sandbox.stub(RoutingService, 'deleteRouting') - $sandbox.stub(ApplicationManager, 'findApplicationRoutes').returns(Promise.resolve([...routes, oldRoute])) - }) - it('Should update the routes', async () => { - await $subject - for (const routeData of routes) { - expect(RoutingService.updateRouting).to.have.been.calledWith(applicationData.name, routeData.name, {...routeData, application: applicationData.name}, user, isCLI, transaction) - } - expect(RoutingService.createRouting).to.have.been.calledWith({ ...newRoute, application: applicationData.name }, user, isCLI, transaction) - expect(RoutingService.deleteRouting).to.have.been.calledWith(oldRoute.name, user, isCLI, transaction) - }) - }) context('when there are microservices to update', () => { const newMsvc = { name: 'new-msvc' } diff --git a/test/src/services/iofog-service.test.js b/test/src/services/iofog-service.test.js index aa89af5c1..348051b9b 100644 --- a/test/src/services/iofog-service.test.js +++ b/test/src/services/iofog-service.test.js @@ -6,6 +6,7 @@ const ioFogService = require('../../../src/services/iofog-service') const RouterManager = require('../../../src/data/managers/router-manager') const RouterConnectionManager = require('../../../src/data/managers/router-connection-manager') const RouterService = require('../../../src/services/router-service') +const NatsService = require('../../../src/services/nats-service') const AppHelper = require('../../../src/helpers/app-helper') const Validator = require('../../../src/schemas') const ChangeTrackingService = require('../../../src/services/change-tracking-service') @@ -196,6 +197,7 @@ describe('ioFog Service', () => { $sandbox.stub(RouterManager, 'findOne').returns($findOneRouterResponse) $sandbox.stub(RouterService, 'validateAndReturnUpstreamRouters').returns($emptyUpstreamRouters) $sandbox.stub(RouterService, 'createRouterForFog').returns($findOneRouterResponse) + $sandbox.stub(NatsService, 'ensureNatsForFog').returns(Promise.resolve()) $sandbox.stub(ioFogManager, 'update').returns($createIoFogResponse) $sandbox.stub(ioFogManager, 'findOne').returns(Promise.resolve()) $sandbox.stub(ioFogManager, 'findOneWithTags').returns(Promise.resolve()) @@ -654,6 +656,7 @@ describe('ioFog Service', () => { $sandbox.stub(RouterService, 'validateAndReturnUpstreamRouters').returns($emptyUpstreamRouters) $sandbox.stub(RouterService, 'createRouterForFog').returns($createRouterResponse) $sandbox.stub(RouterService, 'updateRouter').returns($updateRouterResponse) + $sandbox.stub(NatsService, 'ensureNatsForFog').returns(Promise.resolve()) $sandbox.stub(RouterConnectionManager, 'findAllWithRouters').returns($emptyUpstreamRouters) $sandbox.stub(CatalogService, 'getRouterCatalogItem').returns($getRouterCatalogItemResponse) $sandbox.stub(MicroserviceManager, 'delete') @@ -1069,6 +1072,7 @@ describe('ioFog Service', () => { $sandbox.stub(CatalogService, 'getRouterCatalogItem').returns($routerCatalogItem) $sandbox.stub(MicroserviceManager, 'delete') $sandbox.stub(MicroserviceManager, 'findAll').returns(Promise.resolve([])) + $sandbox.stub(NatsService, 'cleanupNatsForFog').returns(Promise.resolve()) $sandbox.stub(ioFogManager, 'findAll').returns(Promise.resolve([])) $sandbox.stub(ioFogManager, 'findAllWithTags').returns(Promise.resolve([])) }) @@ -1102,6 +1106,11 @@ describe('ioFog Service', () => { }) context('when ioFogManager#findOne() succeeds', () => { + it('calls NatsService#cleanupNatsForFog() with correct args', async () => { + await $subject + expect(NatsService.cleanupNatsForFog).to.have.been.calledWith(fog, transaction) + }) + it('calls ChangeTrackingService#update() with correct args', async () => { await $subject diff --git a/test/src/services/microservices-service.test.js b/test/src/services/microservices-service.test.js index a6744122a..a9c767b31 100644 --- a/test/src/services/microservices-service.test.js +++ b/test/src/services/microservices-service.test.js @@ -14,7 +14,6 @@ const CatalogItemImageManager = require('../../../src/data/managers/catalog-item const RouterManager = require('../../../src/data/managers/router-manager') const VolumeMappingManager = require('../../../src/data/managers/volume-mapping-manager') const MicroserviceStatusManager = require('../../../src/data/managers/microservice-status-manager') -const RoutingManager = require('../../../src/data/managers/routing-manager') const MicroserviceExtraHostManager = require('../../../src/data/managers/microservice-extra-host-manager') const MicroserviceEnvManager = require('../../../src/data/managers/microservice-env-manager') const MicroserviceArgManager = require('../../../src/data/managers/microservice-arg-manager') @@ -83,7 +82,6 @@ describe('Microservices Service', () => { images: [], logSize: NaN, ports: [], - routes: [], volumeMappings: [], flowId: application.id, applicationId: application.id, @@ -100,7 +98,6 @@ describe('Microservices Service', () => { def('findMicroservicesResponse', () => Promise.resolve(response)) def('findPortMappingsResponse', () => Promise.resolve([])) def('findVolumeMappingsResponse', () => Promise.resolve([])) - def('findRoutesResponse', () => Promise.resolve([])) def('findExtraHostsResponse', () => Promise.resolve([])) def('publicModeResponse', () => Promise.resolve([])) def('envResponse', () => Promise.resolve([])) @@ -112,8 +109,6 @@ describe('Microservices Service', () => { $sandbox.stub(MicroserviceManager, 'findAllExcludeFields').returns($findMicroservicesResponse) $sandbox.stub(MicroservicePortManager, 'findAll').returns($findPortMappingsResponse) $sandbox.stub(VolumeMappingManager, 'findAll').returns($findVolumeMappingsResponse) - $sandbox.stub(RoutingManager, 'findAllPopulated').returns($findRoutesResponse) - $sandbox.stub(RoutingManager, 'findAll').returns($findRoutesResponse) $sandbox.stub(MicroserviceExtraHostManager, 'findAll').returns($findExtraHostsResponse) $sandbox.stub(MicroserviceEnvManager, 'findAllExcludeFields').returns($envResponse) $sandbox.stub(MicroserviceArgManager, 'findAllExcludeFields').returns($cmdResponse) @@ -179,7 +174,6 @@ describe('Microservices Service', () => { def('findMicroserviceResponse', () => Promise.resolve(response)) def('findPortMappingsResponse', () => Promise.resolve([])) def('findVolumeMappingsResponse', () => Promise.resolve([])) - def('findRoutesResponse', () => Promise.resolve([])) def('findExtraHostsResponse', () => Promise.resolve([])) def('publicModeResponse', () => Promise.resolve([])) def('envResponse', () => Promise.resolve([])) @@ -191,8 +185,6 @@ describe('Microservices Service', () => { $sandbox.stub(MicroserviceManager, 'findOneExcludeFields').returns($findMicroserviceResponse) $sandbox.stub(MicroservicePortManager, 'findAll').returns($findPortMappingsResponse) $sandbox.stub(VolumeMappingManager, 'findAll').returns($findVolumeMappingsResponse) - $sandbox.stub(RoutingManager, 'findAllPopulated').returns($findRoutesResponse) - $sandbox.stub(RoutingManager, 'findAll').returns($findRoutesResponse) $sandbox.stub(MicroserviceExtraHostManager, 'findAll').returns($findExtraHostsResponse) $sandbox.stub(MicroserviceEnvManager, 'findAllExcludeFields').returns($envResponse) $sandbox.stub(MicroserviceArgManager, 'findAllExcludeFields').returns($cmdResponse) @@ -309,7 +301,6 @@ describe('Microservices Service', () => { 'external': 1, }, ], - 'routes': [], 'logLimit': 1 } @@ -1241,7 +1232,6 @@ describe('Microservices Service', () => { def('deleteUndefinedFieldsResponse', () => newMicroservice) def('getNewAgentMicroserviceReponse', () => Promise.resolve([])) def('newAgentPublicPortsResponse', () => Promise.resolve([])) - def('findRoutesResponse', () => Promise.resolve([])) def('getPortsResponse', () => Promise.resolve([])) def('findFogResponse', () => Promise.resolve({ ...newFog, getMicroservice: () => $getNewAgentMicroserviceReponse })) @@ -1604,12 +1594,10 @@ describe('Microservices Service', () => { def('subject', () => $subject.deleteMicroserviceEndPoint(microserviceUuid, microserviceData, user, isCLI, transaction)) def('findMicroserviceResponse', () => Promise.resolve(microserviceData)) - def('findRoutesResponse', () => Promise.resolve([])) def('findPortMappings', () => Promise.resolve([])) beforeEach(() => { $sandbox.stub(MicroserviceManager, 'findOneWithStatusAndCategory').returns($findMicroserviceResponse) - $sandbox.stub(RoutingManager, 'findAllPopulated').returns($findRoutesResponse) $sandbox.stub(MicroservicePortManager, 'findAll').returns($findPortMappings) $sandbox.stub(MicroserviceManager, 'delete') $sandbox.stub(ChangeTrackingService, 'update') @@ -1649,54 +1637,6 @@ describe('Microservices Service', () => { }) }) - context('when there are routes', () => { - const app = { - id: 1, - name: 'my-app' - } - const routes = [{ - name: 'one', - id: 1, - sourceMicroserviceUuid: 'srcMsvcUUID1', - destMicroserviceUuid: 'destMsvcUUID1', - application: app - }, { - name: 'two', - id: 2, - sourceMicroserviceUuid: 'srcMsvcUUID2', - destMicroserviceUuid: 'destMsvcUUID2', - application: app - }] - def('findRoutesResponse', () => Promise.resolve(routes)) - - const routeAgentUuid = 'routeAgentUUID' - - beforeEach(() => { - $sandbox.stub(RoutingManager, 'delete') - $sandbox.stub(ApplicationManager, 'findOne').returns(Promise.resolve(app)) - const findOneStub = $sandbox.stub(RoutingManager, 'findOne') - for (const route of routes){ - findOneStub.withArgs({applicationId: app.id, name: route.name}, transaction).returns(route) - } - const stub = $sandbox.stub(MicroserviceManager, 'findOne') - for(const route of routes) { - stub.withArgs({uuid: route.sourceMicroserviceUuid}).returns(Promise.resolve({iofogUuid: routeAgentUuid + route.sourceMicroserviceUuid})) - stub.withArgs({uuid: route.destMicroserviceUuid}).returns(Promise.resolve({iofogUuid: routeAgentUuid + route.destMicroserviceUuid})) - } - }) - - it('should delete routes', async () => { - await $subject - - for(const route of routes) { - expect(RoutingManager.findOne).to.have.been.calledWith({applicationId: app.id, name: route.name}, transaction) - expect(RoutingManager.delete).to.have.been.calledWith({id: route.id}, transaction) - expect(ChangeTrackingService.update).to.have.been.calledWith(routeAgentUuid + route.sourceMicroserviceUuid, ChangeTrackingService.events.microserviceFull, transaction) - expect(ChangeTrackingService.update).to.have.been.calledWith(routeAgentUuid + route.destMicroserviceUuid, ChangeTrackingService.events.microserviceFull, transaction) - } - }) - }) - context('when there are ports', () => { const publicPort = { id: 1, @@ -1782,7 +1722,6 @@ describe('Microservices Service', () => { 'publicMode': false, }, ], - 'routes': [], } const newMicroservice = { uuid: microserviceUuid, diff --git a/test/src/services/nats-auth-service.test.js b/test/src/services/nats-auth-service.test.js new file mode 100644 index 000000000..a648acb92 --- /dev/null +++ b/test/src/services/nats-auth-service.test.js @@ -0,0 +1,123 @@ +const { expect } = require('chai') +const sinon = require('sinon') + +const MicroserviceManager = require('../../../src/data/managers/microservice-manager') +const NatsAccountManager = require('../../../src/data/managers/nats-account-manager') +const NatsUserManager = require('../../../src/data/managers/nats-user-manager') +const NatsUserRuleManager = require('../../../src/data/managers/nats-user-rule-manager') +const NatsAccountRuleManager = require('../../../src/data/managers/nats-account-rule-manager') +const ApplicationManager = require('../../../src/data/managers/application-manager') +const SecretService = require('../../../src/services/secret-service') +const NatsService = require('../../../src/services/nats-service') +const NatsAuthService = require('../../../src/services/nats-auth-service') + +describe('NATS Auth Service', () => { + def('sandbox', () => sinon.createSandbox()) + const transaction = {} + + afterEach(() => $sandbox.restore()) + + describe('reissueUserForMicroservice', () => { + const microserviceUuid = 'ms-uuid-1' + const applicationId = 1 + const accountId = 10 + const userRuleId = 2 + const microservice = { + uuid: microserviceUuid, + applicationId, + natsRuleId: userRuleId, + natsAccess: true, + name: 'box-1' + } + const account = { id: accountId, applicationId, seedSecretName: 'acc-seed' } + const app = { id: applicationId, name: 'app1' } + const defaultUserRule = { id: userRuleId, name: 'default-user' } + const existingUserSameAccountSameRule = { + id: 1, + accountId, + natsUserRuleId: userRuleId, + microserviceUuid, + publicKey: 'existing-pk', + credsSecretName: 'nats-creds-app1-box-1', + name: 'box-1' + } + const existingUserSameAccountDifferentRule = { + id: 1, + accountId, + natsUserRuleId: 99, + microserviceUuid, + publicKey: 'existing-pk', + credsSecretName: 'nats-creds-app1-box-1', + name: 'box-1' + } + + beforeEach(() => { + $sandbox.stub(NatsAccountRuleManager, 'updateOrCreate').resolves() + $sandbox.stub(NatsUserRuleManager, 'updateOrCreate').resolves() + $sandbox.stub(MicroserviceManager, 'findOne').callsFake(({ uuid }) => { + if (uuid === microserviceUuid) return Promise.resolve(microservice) + return Promise.resolve(null) + }) + $sandbox.stub(ApplicationManager, 'findOne').resolves(app) + $sandbox.stub(NatsAccountManager, 'findOne').callsFake((query) => { + if (query.applicationId === applicationId) return Promise.resolve(account) + if (query.id === accountId) return Promise.resolve(account) + return Promise.resolve(null) + }) + $sandbox.stub(NatsUserRuleManager, 'findOne').resolves(defaultUserRule) + $sandbox.stub(NatsService, 'enqueueReconcileTask').callsFake(() => Promise.resolve()) + }) + + context('when existing user has same account and same rule (ensure-only)', () => { + beforeEach(() => { + $sandbox.stub(NatsUserManager, 'findOne').resolves(existingUserSameAccountSameRule) + $sandbox.stub(NatsUserManager, 'update').resolves() + $sandbox.stub(NatsUserManager, 'create').resolves() + $sandbox.stub(SecretService, 'createSecretEndpoint').resolves() + $sandbox.stub(SecretService, 'updateSecretEndpointIfChanged').resolves() + }) + + it('does not call NatsUserManager.update or create (no key rotation)', async () => { + await NatsAuthService.reissueUserForMicroservice(microserviceUuid, transaction, { triggerReconcile: false }) + + expect(NatsUserManager.update).to.not.have.been.called + expect(NatsUserManager.create).to.not.have.been.called + }) + + it('does not call SecretService create or update (no secret overwrite)', async () => { + await NatsAuthService.reissueUserForMicroservice(microserviceUuid, transaction, { triggerReconcile: false }) + + expect(SecretService.createSecretEndpoint).to.not.have.been.called + expect(SecretService.updateSecretEndpointIfChanged).to.not.have.been.called + }) + + it('returns the existing user', async () => { + const result = await NatsAuthService.reissueUserForMicroservice(microserviceUuid, transaction, { triggerReconcile: false }) + + expect(result).to.not.be.null + expect(result.accountId).to.equal(accountId) + expect(result.natsUserRuleId).to.equal(userRuleId) + }) + }) + + context('when existing user has same account but different rule (revoke and reissue)', () => { + beforeEach(() => { + $sandbox.stub(NatsUserManager, 'findOne').resolves(existingUserSameAccountDifferentRule) + $sandbox.stub(NatsUserManager, 'update').resolves() + $sandbox.stub(NatsAccountManager, 'update').resolves() + $sandbox.stub(SecretService, 'getSecretEndpoint').resolves({ data: { seed: 'operator-seed-base64' } }) + $sandbox.stub(SecretService, 'createSecretEndpoint').resolves() + $sandbox.stub(SecretService, 'updateSecretEndpointIfChanged').resolves() + const NatsOperatorManager = require('../../../src/data/managers/nats-operator-manager') + $sandbox.stub(NatsOperatorManager, 'findOne').resolves({ seedSecretName: 'op-seed' }) + }) + + it('updates account JWT (revocation) and user (new key)', async () => { + await NatsAuthService.reissueUserForMicroservice(microserviceUuid, transaction) + + expect(NatsAccountManager.update).to.have.been.called + expect(NatsUserManager.update).to.have.been.called + }) + }) + }) +}) diff --git a/test/src/services/nats-service.test.js b/test/src/services/nats-service.test.js new file mode 100644 index 000000000..9e42f5db5 --- /dev/null +++ b/test/src/services/nats-service.test.js @@ -0,0 +1,144 @@ +const { expect } = require('chai') +const sinon = require('sinon') + +const NatsService = require('../../../src/services/nats-service') +const NatsInstanceManager = require('../../../src/data/managers/nats-instance-manager') +const NatsConnectionManager = require('../../../src/data/managers/nats-connection-manager') +const NatsAccountManager = require('../../../src/data/managers/nats-account-manager') +const NatsUserManager = require('../../../src/data/managers/nats-user-manager') +const MicroserviceManager = require('../../../src/data/managers/microservice-manager') +const VolumeMappingManager = require('../../../src/data/managers/volume-mapping-manager') +const VolumeMountService = require('../../../src/services/volume-mount-service') +const ConfigMapManager = require('../../../src/data/managers/config-map-manager') +const SecretService = require('../../../src/services/secret-service') + +describe('NATS Service', () => { + def('sandbox', () => sinon.createSandbox()) + + afterEach(() => $sandbox.restore()) + + describe('.cleanupNatsForFog()', () => { + const transaction = {} + const fog = { uuid: 'fog-1', name: 'local-agent' } + const natsInstance = { id: 77 } + const microservices = [{ uuid: 'ms-1' }] + + def('subject', () => NatsService.cleanupNatsForFog(fog, transaction)) + + beforeEach(() => { + $sandbox.stub(NatsInstanceManager, 'findByFog').returns(Promise.resolve(natsInstance)) + $sandbox.stub(NatsAccountManager, 'findOne').returns(Promise.resolve({ id: 1 })) + $sandbox.stub(NatsUserManager, 'findOne').returns(Promise.resolve({ credsSecretName: 'nats-creds-sys-admin-hub' })) + $sandbox.stub(NatsConnectionManager, 'delete').returns(Promise.resolve()) + $sandbox.stub(NatsInstanceManager, 'delete').returns(Promise.resolve()) + $sandbox.stub(MicroserviceManager, 'findAll').returns(Promise.resolve(microservices)) + $sandbox.stub(VolumeMappingManager, 'delete').returns(Promise.resolve()) + $sandbox.stub(VolumeMountService, 'unlinkVolumeMountEndpoint').returns(Promise.resolve()) + $sandbox.stub(VolumeMountService, 'findVolumeMountedFogNodes').returns(Promise.resolve([])) + $sandbox.stub(VolumeMountService, 'deleteVolumeMountEndpoint').returns(Promise.resolve()) + $sandbox.stub(ConfigMapManager, 'getConfigMap').returns(Promise.resolve({ name: 'cm' })) + $sandbox.stub(ConfigMapManager, 'deleteConfigMap').returns(Promise.resolve()) + $sandbox.stub(SecretService, 'deleteSecretEndpoint').returns(Promise.resolve()) + }) + + it('cleans up instance, mounts, configmaps, and secrets', async () => { + await $subject + + expect(NatsInstanceManager.findByFog).to.have.been.calledWith(fog.uuid, transaction) + expect(NatsConnectionManager.delete).to.have.been.calledWith({ sourceNats: natsInstance.id }, transaction) + expect(NatsConnectionManager.delete).to.have.been.calledWith({ destNats: natsInstance.id }, transaction) + expect(NatsInstanceManager.delete).to.have.been.calledWith({ id: natsInstance.id }, transaction) + expect(ConfigMapManager.deleteConfigMap).to.have.been.called + expect(SecretService.deleteSecretEndpoint).to.have.been.called + }) + }) + + describe('single hub server config (no cluster block)', () => { + it('server-no-cluster.conf template exists and has no cluster block', () => { + const fs = require('fs') + const path = require('path') + const noClusterPath = path.join(__dirname, '../../../src/templates/nats/server-no-cluster.conf') + const content = fs.readFileSync(noClusterPath, 'utf8') + expect(content).to.not.include('cluster {') + expect(content).to.include('port:') + expect(content).to.include('jetstream') + }) + }) + + describe('K8s NATS ConfigMaps', () => { + it('uses constants iofog-nats-config and iofog-nats-jwt-bundle for K8s ConfigMap names', () => { + const K8S_NATS_SERVER_CONFIG_MAP = 'iofog-nats-config' + const K8S_NATS_JWT_BUNDLE_CONFIG_MAP = 'iofog-nats-jwt-bundle' + expect(K8S_NATS_SERVER_CONFIG_MAP).to.equal('iofog-nats-config') + expect(K8S_NATS_JWT_BUNDLE_CONFIG_MAP).to.equal('iofog-nats-jwt-bundle') + }) + }) + + describe('mergeK8sHubClusterRoutes', () => { + it('preserves operator routes (nats-headless) and appends controller-managed routes', () => { + const currentRoutes = [ + 'nats://nats-0.nats-headless:6222', + 'nats://nats-1.nats-headless:6222' + ] + const desiredControllerRoutes = ['nats://40.120.10.10:6222'] + const result = NatsService.mergeK8sHubClusterRoutes(currentRoutes, desiredControllerRoutes) + expect(result).to.eql([ + 'nats://nats-0.nats-headless:6222', + 'nats://nats-1.nats-headless:6222', + 'nats://40.120.10.10:6222' + ]) + }) + + it('keeps only operator routes when desiredControllerRoutes is empty', () => { + const currentRoutes = [ + 'nats://nats-0.nats-headless:6222', + 'nats://nats-1.nats-headless:6222', + 'nats://40.120.10.10:6222' + ] + const result = NatsService.mergeK8sHubClusterRoutes(currentRoutes, []) + expect(result).to.eql([ + 'nats://nats-0.nats-headless:6222', + 'nats://nats-1.nats-headless:6222' + ]) + }) + + it('returns only desiredControllerRoutes when currentRoutes has no operator routes', () => { + const currentRoutes = ['nats://40.120.10.10:6222'] + const desiredControllerRoutes = ['nats://10.0.0.1:6222'] + const result = NatsService.mergeK8sHubClusterRoutes(currentRoutes, desiredControllerRoutes) + expect(result).to.eql(['nats://10.0.0.1:6222']) + }) + + it('handles empty or null currentRoutes', () => { + expect(NatsService.mergeK8sHubClusterRoutes([], ['nats://40.120.10.10:6222'])).to.eql(['nats://40.120.10.10:6222']) + expect(NatsService.mergeK8sHubClusterRoutes(null, ['nats://40.120.10.10:6222'])).to.eql(['nats://40.120.10.10:6222']) + }) + + it('ignores non-string entries in currentRoutes', () => { + const currentRoutes = [ + 'nats://nats-0.nats-headless:6222', + 123, + null, + undefined + ] + const result = NatsService.mergeK8sHubClusterRoutes(currentRoutes, []) + expect(result).to.eql(['nats://nats-0.nats-headless:6222']) + }) + }) + + describe('operator JWT fields', () => { + it('encodeOperator from @nats-io/jwt accepts account_server_url, operator_service_urls, system_account', async () => { + const { createOperator, encodeOperator } = require('@nats-io/jwt') + const kp = createOperator() + const jwt = await encodeOperator('test-op', kp, { + account_server_url: 'https://hub:4222', + operator_service_urls: ['https://hub:4222'], + system_account: 'ACTPUBKEY123' + }) + expect(jwt).to.be.a('string') + const payload = JSON.parse(Buffer.from(jwt.split('.')[1], 'base64url').toString('utf8')) + expect(payload.nats).to.include({ account_server_url: 'https://hub:4222', system_account: 'ACTPUBKEY123' }) + expect(payload.nats.operator_service_urls).to.eql(['https://hub:4222']) + }) + }) +}) diff --git a/test/src/services/yaml-parser-service.test.js b/test/src/services/yaml-parser-service.test.js new file mode 100644 index 000000000..6297841c7 --- /dev/null +++ b/test/src/services/yaml-parser-service.test.js @@ -0,0 +1,116 @@ +const { expect } = require('chai') + +const YamlParserService = require('../../../src/services/yaml-parser-service') + +describe('YAML Parser Service', () => { + describe('.parseAppFile()', () => { + it('parses application natsConfig', async () => { + const yaml = ` +kind: Application +metadata: + name: app-a +spec: + natsConfig: + natsAccess: true + natsRule: app-rule + microservices: [] +` + const result = await YamlParserService.parseAppFile(yaml) + expect(result.natsConfig).to.eql({ + natsAccess: true, + natsRule: 'app-rule' + }) + }) + }) + + describe('.parseMicroserviceFile()', () => { + it('parses microservice natsConfig', async () => { + const yaml = ` +kind: Microservice +metadata: + name: app-a/ms-a +spec: + container: + env: [] + natsConfig: + natsAccess: true + natsRule: user-rule +` + const result = await YamlParserService.parseMicroserviceFile(yaml) + expect(result.natsConfig).to.eql({ + natsAccess: true, + natsRule: 'user-rule' + }) + expect(result.application).to.eql('app-a') + expect(result.name).to.eql('ms-a') + }) + + it('parses microservice natsEnabled', async () => { + const yaml = ` +kind: Microservice +metadata: + name: app-a/ms-b +spec: + container: + env: [] + natsEnabled: true +` + const result = await YamlParserService.parseMicroserviceFile(yaml) + expect(result.natsEnabled).to.eql(true) + expect(result.application).to.eql('app-a') + expect(result.name).to.eql('ms-b') + }) + + it('does not map deprecated top-level natsAccess', async () => { + const yaml = ` +kind: Microservice +metadata: + name: app-a/ms-c +spec: + container: + env: [] + natsAccess: true +` + const result = await YamlParserService.parseMicroserviceFile(yaml) + expect(result.natsAccess).to.eql(undefined) + }) + }) + + describe('NATS rule YAML parsing', () => { + it('parses NatsAccountRule resource', async () => { + const yaml = ` +kind: NatsAccountRule +metadata: + name: app-rule +spec: + maxConnections: 100 + memStorage: -1 + diskStorage: -1 +` + const result = await YamlParserService.parseNatsAccountRuleFile(yaml) + expect(result.name).to.equal('app-rule') + expect(result.maxConnections).to.equal(100) + expect(result.memStorage).to.equal(-1) + expect(result.diskStorage).to.equal(-1) + expect(result).to.not.have.property('jetstreamEnabled') + }) + + it('parses NatsUserRule resource', async () => { + const yaml = ` +kind: NatsUserRule +metadata: + name: user-rule +spec: + maxSubscriptions: 10 + allowedConnectionTypes: + - STANDARD +` + const result = await YamlParserService.parseNatsUserRuleFile(yaml) + expect(result).to.eql({ + name: 'user-rule', + maxSubscriptions: 10, + allowedConnectionTypes: ['STANDARD'] + }) + }) + }) +}) diff --git a/test/src/utils/k8s-client-integration.test.js b/test/src/utils/k8s-client-integration.test.js new file mode 100644 index 000000000..f2a94ac41 --- /dev/null +++ b/test/src/utils/k8s-client-integration.test.js @@ -0,0 +1,177 @@ +/* + * k8s-client integration test. + * Uses namespace "local-test" by default (override with K8S_TEST_NAMESPACE). + * Requires local kubeconfig (KUBECONFIG or ~/.kube/config). + * Run with: nvm use 24 && npm run test:k8s-client + * Skip when no namespace (e.g. K8S_TEST_NAMESPACE="" in CI without a cluster). + */ + +const namespace = process.env.K8S_TEST_NAMESPACE || 'local-test' +if (namespace) { + process.env.CONTROL_PLANE = 'kubernetes' + process.env.CONTROLLER_NAMESPACE = namespace + process.env.K8S_USE_LOCAL_KUBECONFIG = 'true' +} + +const { expect } = require('chai') +const k8sClient = require('../../../src/utils/k8s-client') + +const resourcePrefix = 'k8s-client-test-' +const testSecretName = resourcePrefix + 'secret' +const testConfigMapName = resourcePrefix + 'configmap' +const testServiceName = resourcePrefix + 'service' + +describe('k8s-client integration', function () { + let k8sApi + let k8s + + before(async function () { + if (!namespace) { + this.skip() + return + } + k8s = await import('@kubernetes/client-node') + const kc = new k8s.KubeConfig() + kc.loadFromDefault() + k8sApi = kc.makeApiClient(k8s.CoreV1Api) + }) + + after(async function () { + if (!k8sApi || !namespace) return + try { + await k8sApi.deleteNamespacedSecret({ name: testSecretName, namespace }) + } catch (_) {} + try { + await k8sApi.deleteNamespacedConfigMap({ name: testConfigMapName, namespace }) + } catch (_) {} + try { + await k8sApi.deleteNamespacedService({ name: testServiceName, namespace }) + } catch (_) {} + }) + + it('checkKubernetesEnvironment returns true when env is set', function () { + if (!namespace) this.skip() + expect(k8sClient.checkKubernetesEnvironment()).to.equal(true) + }) + + describe('Secrets', function () { + before(async function () { + if (!k8sApi || !namespace) this.skip() + await k8sApi.createNamespacedSecret({ + namespace, + body: { + metadata: { name: testSecretName }, + type: 'Opaque', + data: { key: Buffer.from('value').toString('base64') } + } + }) + }) + + it('getSecret retrieves the created secret', async function () { + if (!namespace) this.skip() + const secret = await k8sClient.getSecret(testSecretName) + expect(secret).to.be.an('object') + expect(secret.metadata).to.be.an('object') + expect(secret.metadata.name).to.equal(testSecretName) + expect(secret.data).to.have.property('key') + }) + }) + + describe('ConfigMaps', function () { + before(async function () { + if (!k8sApi || !namespace) this.skip() + await k8sApi.createNamespacedConfigMap({ + namespace, + body: { + metadata: { name: testConfigMapName }, + data: { foo: 'bar' } + } + }) + }) + + it('getConfigMap retrieves the created configmap', async function () { + if (!namespace) this.skip() + const cm = await k8sClient.getConfigMap(testConfigMapName) + expect(cm).to.be.an('object') + expect(cm.metadata.name).to.equal(testConfigMapName) + expect(cm.data).to.have.property('foo', 'bar') + }) + + it('patchConfigMap updates the configmap', async function () { + if (!namespace) this.skip() + const updated = await k8sClient.patchConfigMap(testConfigMapName, { + data: { foo: 'baz', newKey: 'newValue' } + }) + expect(updated.data).to.have.property('foo', 'baz') + expect(updated.data).to.have.property('newKey', 'newValue') + }) + }) + + describe('Services', function () { + it('createService creates a service', async function () { + if (!namespace) this.skip() + const spec = { + metadata: { name: testServiceName }, + spec: { + selector: { app: 'k8s-client-test' }, + ports: [{ port: 80, targetPort: 8080, name: 'http' }], + type: 'ClusterIP' + } + } + const svc = await k8sClient.createService(spec) + expect(svc).to.be.an('object') + expect(svc.metadata.name).to.equal(testServiceName) + expect(svc.spec.type).to.equal('ClusterIP') + }) + + it('getNamespacedServices lists services including the test service', async function () { + if (!namespace) this.skip() + const list = await k8sClient.getNamespacedServices() + expect(list).to.have.property('items').that.is.an('array') + const found = list.items.find(s => s.metadata.name === testServiceName) + expect(found).to.be.an('object') + }) + + it('getService retrieves the service', async function () { + if (!namespace) this.skip() + const svc = await k8sClient.getService(testServiceName) + expect(svc.metadata.name).to.equal(testServiceName) + }) + + it('updateService patches the service', async function () { + if (!namespace) this.skip() + const updated = await k8sClient.updateService(testServiceName, { + metadata: { annotations: { 'test-key': 'test-value' } } + }) + expect(updated.metadata.annotations).to.have.property('test-key', 'test-value') + }) + + it('watchLoadBalancerIP returns null for ClusterIP service', async function () { + if (!namespace) this.skip() + const ip = await k8sClient.watchLoadBalancerIP(testServiceName, 1, 100) + expect(ip).to.equal(null) + }) + + it('deleteService removes the service', async function () { + if (!namespace) this.skip() + const result = await k8sClient.deleteService(testServiceName) + expect(result).to.be.an('object') + }) + }) + + describe('StatefulSet rollout', function () { + const statefulSetName = 'nats' + + it('rolloutStatefulSet patches the nats StatefulSet and returns it', async function () { + if (!namespace) this.skip() + const result = await k8sClient.rolloutStatefulSet(statefulSetName) + expect(result).to.be.an('object') + expect(result.metadata).to.be.an('object') + expect(result.metadata.name).to.equal(statefulSetName) + expect(result.spec).to.have.property('template') + const restartedAt = result.spec.template.metadata?.annotations?.['kubectl.kubernetes.io/restartedAt'] + expect(restartedAt).to.be.a('string') + expect(new Date(restartedAt).getTime()).to.be.closeTo(Date.now(), 5000) + }) + }) +}) diff --git a/test/vault/openbao.md b/test/vault/openbao.md new file mode 100644 index 000000000..6c90e58a0 --- /dev/null +++ b/test/vault/openbao.md @@ -0,0 +1,26 @@ +docker run \ + --name openbao \ + --detach \ + --cap-add=IPC_LOCK \ + -p 8200:8200 \ + -v openbao-data:/home//openbao/data:rw \ + -e BAO_LOCAL_CONFIG=' +ui = true + +listener "tcp" { + address = "0.0.0.0:8200" + tls_disable = 1 +} + +storage "file" { + path = "/openbao/data" +} + +disable_mlock = true +api_addr = "http://127.0.0.1:8200" +' \ + openbao/openbao server + + +