`status`: 'success' | 'failure'
}
+###### Delete Charging Stations
+
+- Request:
+ `ProcedureName`: 'deleteChargingStations'
+ `PDU`: {
+ `hashIds`: charging station unique identifier strings array (optional, default: all charging stations),
+ `deleteConfiguration?`: boolean
+ }
+
+- Response:
+ `PDU`: {
+ `status`: 'success' | 'failure',
+ `hashIdsSucceeded`: charging station unique identifier strings array,
+ `hashIdsFailed`: charging station unique identifier strings array (optional),
+ `responsesFailed`: failed responses payload array (optional)
+ }
+
###### Set Charging Station Supervision Url
- Request:
has-property-descriptors: 1.0.1
has-proto: 1.0.1
has-symbols: 1.0.3
- hasown: 2.0.0
+ hasown: 2.0.1
internal-slot: 1.0.7
is-array-buffer: 3.0.4
is-callable: 1.2.7
dependencies:
get-intrinsic: 1.2.4
has-tostringtag: 1.0.2
- hasown: 2.0.0
+ hasown: 2.0.1
dev: true
/es-shim-unscopables@1.0.2:
resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==}
dependencies:
- hasown: 2.0.0
+ hasown: 2.0.1
dev: true
/es-to-primitive@1.2.1:
eslint: 8.56.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
- hasown: 2.0.0
+ hasown: 2.0.1
is-core-module: 2.13.1
is-glob: 4.0.3
minimatch: 3.1.2
function-bind: 1.1.2
has-proto: 1.0.1
has-symbols: 1.0.3
- hasown: 2.0.0
+ hasown: 2.0.1
dev: true
/get-package-type@0.1.0:
minimalistic-assert: 1.0.1
dev: true
- /hasown@2.0.0:
- resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==}
+ /hasown@2.0.1:
+ resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==}
engines: {node: '>= 0.4'}
dependencies:
function-bind: 1.1.2
engines: {node: '>= 0.4'}
dependencies:
es-errors: 1.3.0
- hasown: 2.0.0
+ hasown: 2.0.1
side-channel: 1.0.5
dev: true
/is-core-module@2.13.1:
resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
dependencies:
- hasown: 2.0.0
+ hasown: 2.0.1
/is-date-object@1.0.5:
resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
{
"_type": "export",
"__export_format": 4,
- "__export_date": "2024-02-09T13:02:45.966Z",
+ "__export_date": "2024-02-11T11:11:14.532Z",
"__export_source": "insomnia.desktop.app:v8.6.1",
"resources": [
{
"settingFollowRedirects": "global",
"_type": "request"
},
+ {
+ "_id": "req_5db3c8b9a7094ec5806bcc804752f968",
+ "parentId": "wrk_509d4a5094fa485ba93e53bc735e8ac3",
+ "modified": 1707649833755,
+ "created": 1707649782517,
+ "url": "{{baseUrl}}/{{protocol}}/{{version}}/deleteChargingStations",
+ "name": "deleteChargingStations",
+ "description": "",
+ "method": "POST",
+ "body": {
+ "mimeType": "application/json",
+ "text": "{\n\t\"hashIds\": [\n\t\t\"0058d8b50e422cce5bbd0c0a4ad13d5d657e8a88670dcf04c1b2b563fea3db5b96a3686278b374ed050e21baef89060e\"\n\t]\n}"
+ },
+ "parameters": [],
+ "headers": [
+ {
+ "name": "Content-Type",
+ "value": "application/json",
+ "id": "pair_af9f914ca52f407488bc6df6c7db3a08"
+ }
+ ],
+ "authentication": {
+ "type": "basic",
+ "useISO88591": false,
+ "disabled": false,
+ "username": "{{username}}",
+ "password": "{{password}}"
+ },
+ "metaSortKey": -999999971.875,
+ "isPrivate": false,
+ "pathParameters": [],
+ "settingStoreCookies": true,
+ "settingSendCookies": true,
+ "settingDisableRenderRequestBody": false,
+ "settingEncodeUrl": true,
+ "settingRebuildPath": true,
+ "settingFollowRedirects": "global",
+ "_type": "request"
+ },
{
"_id": "req_79422f6238204d9b8f832f2cb3ebfde3",
"parentId": "wrk_509d4a5094fa485ba93e53bc735e8ac3",
{
"_type": "export",
"__export_format": 4,
- "__export_date": "2024-02-09T13:03:00.609Z",
+ "__export_date": "2024-02-11T11:07:54.308Z",
"__export_source": "insomnia.desktop.app:v8.6.1",
"resources": [
{
"description": "",
"_type": "websocket_request"
},
+ {
+ "_id": "ws-req_c36eca7e4cdd453dac690a46cba1afdf",
+ "parentId": "wrk_64c9d5670f014930baf668326b95e601",
+ "modified": 1707645101146,
+ "created": 1707645101146,
+ "name": "deleteChargingStations",
+ "url": "{{ _.baseUrl }}",
+ "metaSortKey": -1671191988792.4688,
+ "headers": [
+ {
+ "id": "pair_9a64d3b0bc654ab68710ef138f00d3f5",
+ "name": "Sec-WebSocket-Protocol",
+ "value": "{{ _.protocol }}{{ _.version }}",
+ "description": ""
+ }
+ ],
+ "authentication": {
+ "type": "basic",
+ "useISO88591": false,
+ "disabled": false,
+ "username": "{{ _.username }}",
+ "password": "{{ _.password }}"
+ },
+ "parameters": [],
+ "pathParameters": [],
+ "settingEncodeUrl": true,
+ "settingStoreCookies": true,
+ "settingSendCookies": true,
+ "settingFollowRedirects": "global",
+ "description": "",
+ "_type": "websocket_request"
+ },
{
"_id": "ws-req_afbfa6e6824b427e99e735c0b1eabe3b",
"parentId": "wrk_64c9d5670f014930baf668326b95e601",
{
"_id": "ws-payload_2872e2656c164769acf98cc7ba7ea028",
"parentId": "ws-req_e5902850ac1d40369bd6e942a2755a9d",
- "modified": 1707477801921,
+ "modified": 1707649312368,
"created": 1671297544207,
"name": "New Payload",
"value": "[\n\t\"{% uuid 'v4' %}\",\n\t\"listChargingStations\",\n\t{}\n]",
{
"_id": "ws-payload_edebda0226aa43f88712d7feb60ac645",
"parentId": "ws-req_ebe5a555a6344dfba7e29f857af11d08",
- "modified": 1707475947625,
+ "modified": 1707649325381,
"created": 1671297697172,
"name": "New Payload",
"value": "[\n\t\"{% uuid 'v4' %}\",\n\t\"startChargingStation\",\n\t{\n\t\t\"hashIds\": [\n\t\t\t\"5b82a559d2b453f6277e272e134ae824ae358cfb6ee2415af9f7c2f325ef8b3e930aeeadcd866df4b8aec58786e60ae7\"\n\t\t]\n\t}\n]",
{
"_id": "ws-payload_d8e66e0f933e4d74bb5fbff4d15a44bf",
"parentId": "ws-req_23025e078480491daf01406b2b5e9cc2",
- "modified": 1707157205853,
+ "modified": 1707589443241,
"created": 1671298432039,
"name": "New Payload",
"value": "[\n\t\"{% uuid 'v4' %}\",\n\t\"startAutomaticTransactionGenerator\",\n\t{}\n]",
{
"_id": "ws-payload_95c28d71c8d940bb83ac514f8916a66d",
"parentId": "ws-req_afbfa6e6824b427e99e735c0b1eabe3b",
- "modified": 1707157216642,
+ "modified": 1707649322410,
"created": 1678991663554,
"name": "New Payload",
"value": "[\n\t\"{% uuid 'v4' %}\",\n\t\"setSupervisionUrl\",\n\t{\n\t\t\"hashIds\": [\n\t\t\t\"5b82a559d2b453f6277e272e134ae824ae358cfb6ee2415af9f7c2f325ef8b3e930aeeadcd866df4b8aec58786e60ae7\"\n\t\t],\n\t\t\"url\": \"wss://domain.tld\"\n\t}\n]",
{
"_id": "ws-payload_3e1dffbcefcc481286b44c694b9e6496",
"parentId": "ws-req_3a0ff14878b449f4be3dfbb7432b5f87",
- "modified": 1707481292801,
+ "modified": 1707645536699,
"created": 1706726300041,
"name": "New Payload",
"value": "[\n\t\"{% uuid 'v4' %}\",\n\t\"listTemplates\",\n\t{}\n]",
{
"_id": "ws-payload_5e2dfed34a104c28b887c885ada1b4af",
"parentId": "ws-req_8777c5635dd64fccbc2b0f450be656c0",
- "modified": 1707482458081,
+ "modified": 1707649639026,
"created": 1706778795544,
"name": "New Payload",
"value": "[\n\t\"{% uuid 'v4' %}\",\n\t\"addChargingStations\",\n\t{\n\t\t\"template\": \"evlink.station-template\",\n\t\t\"numberOfStations\": 1,\n\t\t\"options\": {\n\t\t\t\"autoStart\": false\n\t\t}\n\t}\n]",
{
"_id": "ws-payload_494fba679fa644ccb318f092e780834f",
"parentId": "ws-req_0bab7a97ceda4944976a463f616dec5c",
- "modified": 1707475888681,
+ "modified": 1707649324584,
"created": 1707143784130,
"name": "New Payload",
"value": "[\n\t\"{% uuid 'v4' %}\",\n\t\"performanceStatistics\",\n\t{}\n]",
"mode": "application/json",
"_type": "websocket_payload"
+ },
+ {
+ "_id": "ws-payload_c4a0dbcd684e430b9b27298fe2bd088a",
+ "parentId": "ws-req_c36eca7e4cdd453dac690a46cba1afdf",
+ "modified": 1707649358965,
+ "created": 1707645101151,
+ "name": "New Payload",
+ "value": "[\n\t\"{% uuid 'v4' %}\",\n\t\"deleteChargingStations\",\n\t{\n\t\t\"hashIds\": [\n\t\t\t\"5b82a559d2b453f6277e272e134ae824ae358cfb6ee2415af9f7c2f325ef8b3e930aeeadcd866df4b8aec58786e60ae7\"\n\t\t]\n\t}\n]",
+ "mode": "application/json",
+ "_type": "websocket_payload"
}
]
}
return AutomaticTransactionGenerator.instances.get(chargingStation.stationInfo!.hashId)
}
+ public static deleteInstance (chargingStation: ChargingStation): boolean {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return AutomaticTransactionGenerator.instances.delete(chargingStation.stationInfo!.hashId)
+ }
+
public start (stopAbsoluteDuration?: boolean): void {
if (!checkChargingStation(this.chargingStation, this.logPrefix())) {
return
if (!this.starting) {
this.starting = true
this.on(ChargingStationWorkerMessageEvents.added, this.workerEventAdded)
+ this.on(ChargingStationWorkerMessageEvents.deleted, this.workerEventDeleted)
this.on(ChargingStationWorkerMessageEvents.started, this.workerEventStarted)
this.on(ChargingStationWorkerMessageEvents.stopped, this.workerEventStopped)
this.on(ChargingStationWorkerMessageEvents.updated, this.workerEventUpdated)
case ChargingStationWorkerMessageEvents.added:
this.emit(ChargingStationWorkerMessageEvents.added, msg.data)
break
+ case ChargingStationWorkerMessageEvents.deleted:
+ this.emit(ChargingStationWorkerMessageEvents.deleted, msg.data)
+ break
case ChargingStationWorkerMessageEvents.started:
this.emit(ChargingStationWorkerMessageEvents.started, msg.data)
break
)
}
+ private readonly workerEventDeleted = (data: ChargingStationData): void => {
+ this.uiServer?.chargingStations.delete(data.stationInfo.hashId)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ --this.chargingStationsByTemplate.get(data.stationInfo.templateName)!.added
+ logger.info(
+ `${this.logPrefix()} ${moduleName}.workerEventDeleted: Charging station ${
+ data.stationInfo.chargingStationId
+ } (hashId: ${data.stationInfo.hashId}) deleted (${
+ this.numberOfAddedChargingStations
+ } added from ${this.numberOfConfiguredChargingStations} configured charging station(s))`
+ )
+ }
+
private readonly workerEventStarted = (data: ChargingStationData): void => {
this.uiServer?.chargingStations.set(data.stationInfo.hashId, data)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
import { createHash } from 'node:crypto'
import { EventEmitter } from 'node:events'
-import { type FSWatcher, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
+import { type FSWatcher, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { dirname, join, parse } from 'node:path'
import { URL } from 'node:url'
import { parentPort } from 'node:worker_threads'
buildAddedMessage,
buildChargingStationAutomaticTransactionGeneratorConfiguration,
buildConnectorsStatus,
+ buildDeletedMessage,
buildEvsesStatus,
buildStartedMessage,
buildStoppedMessage,
public readonly connectors: Map<number, ConnectorStatus>
public readonly evses: Map<number, EvseStatus>
public readonly requests: Map<string, CachedRequest>
- public performanceStatistics!: PerformanceStatistics | undefined
+ public performanceStatistics: PerformanceStatistics | undefined
public heartbeatSetInterval?: NodeJS.Timeout
public ocppRequestService!: OCPPRequestService
public bootNotificationRequest?: BootNotificationRequest
private configuredSupervisionUrl!: URL
private wsConnectionRetried: boolean
private wsConnectionRetryCount: number
- private templateFileWatcher!: FSWatcher | undefined
+ private templateFileWatcher: FSWatcher | undefined
private templateFileHash!: string
private readonly sharedLRUCache: SharedLRUCache
private wsPingSetInterval?: NodeJS.Timeout
this.on(ChargingStationEvents.added, () => {
parentPort?.postMessage(buildAddedMessage(this))
})
+ this.on(ChargingStationEvents.deleted, () => {
+ parentPort?.postMessage(buildDeletedMessage(this))
+ })
this.on(ChargingStationEvents.started, () => {
parentPort?.postMessage(buildStartedMessage(this))
})
this.emit(ChargingStationEvents.added)
}
+ public async delete (deleteConfiguration = true): Promise<void> {
+ if (this.started) {
+ await this.stop()
+ }
+ AutomaticTransactionGenerator.deleteInstance(this)
+ PerformanceStatistics.deleteInstance(this.stationInfo?.hashId)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.idTagsCache.deleteIdTags(getIdTagsFile(this.stationInfo!)!)
+ this.requests.clear()
+ this.connectors.clear()
+ this.evses.clear()
+ this.templateFileWatcher?.unref()
+ deleteConfiguration && rmSync(this.configurationFile, { force: true })
+ this.chargingStationWorkerBroadcastChannel.unref()
+ this.emit(ChargingStationEvents.deleted)
+ }
+
public start (): void {
if (!this.started) {
if (!this.starting) {
} file have changed, reload`
)
this.sharedLRUCache.deleteChargingStationTemplate(this.templateFileHash)
- // Initialize
- this.initialize()
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.idTagsCache.deleteIdTags(getIdTagsFile(this.stationInfo!)!)
+ // Initialize
+ this.initialize()
// Restart the ATG
const ATGStarted = this.automaticTransactionGenerator?.started
if (ATGStarted === true) {
if (this.stationInfo?.enableStatistics === true) {
this.performanceStatistics?.stop()
}
- this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash)
this.templateFileWatcher?.close()
- this.sharedLRUCache.deleteChargingStationTemplate(this.templateFileHash)
delete this.bootNotificationResponse
this.started = false
this.saveConfiguration()
+ this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash)
this.emit(ChargingStationEvents.stopped)
this.stopping = false
} else {
await this.chargingStation.stop()
}
],
+ [
+ BroadcastChannelProcedureName.DELETE_CHARGING_STATIONS,
+ async (requestPayload?: BroadcastChannelRequestPayload) => {
+ await this.chargingStation.delete(requestPayload?.deleteConfiguration as boolean)
+ }
+ ],
[
BroadcastChannelProcedureName.OPEN_CONNECTION,
() => {
public stop (): void {
this.stopHttpServer()
+ for (const uiService of this.uiServices.values()) {
+ uiService.stop()
+ }
this.chargingStations.clear()
this.chargingStationTemplates.clear()
}
>([
[ProcedureName.START_CHARGING_STATION, BroadcastChannelProcedureName.START_CHARGING_STATION],
[ProcedureName.STOP_CHARGING_STATION, BroadcastChannelProcedureName.STOP_CHARGING_STATION],
+ [
+ ProcedureName.DELETE_CHARGING_STATIONS,
+ BroadcastChannelProcedureName.DELETE_CHARGING_STATIONS
+ ],
[ProcedureName.CLOSE_CONNECTION, BroadcastChannelProcedureName.CLOSE_CONNECTION],
[ProcedureName.OPEN_CONNECTION, BroadcastChannelProcedureName.OPEN_CONNECTION],
[
this.broadcastChannelRequests = new Map<string, number>()
}
+ public stop (): void {
+ this.broadcastChannelRequests.clear()
+ this.uiServiceWorkerBroadcastChannel.close()
+ }
+
public async requestHandler (request: ProtocolRequest): Promise<ProtocolResponse | undefined> {
let messageId: string | undefined
let command: ProcedureName | undefined
objName: string | undefined,
uri: URL | undefined
): PerformanceStatistics | undefined {
- const logPfx = logPrefix(' Performance statistics')
if (objId == null) {
const errMsg = 'Cannot get performance statistics instance without specifying object id'
- logger.error(`${logPfx} ${errMsg}`)
+ logger.error(`${PerformanceStatistics.logPrefix()} ${errMsg}`)
throw new BaseError(errMsg)
}
if (objName == null) {
const errMsg = 'Cannot get performance statistics instance without specifying object name'
- logger.error(`${logPfx} ${errMsg}`)
+ logger.error(`${PerformanceStatistics.logPrefix()} ${errMsg}`)
throw new BaseError(errMsg)
}
if (uri == null) {
const errMsg = 'Cannot get performance statistics instance without specifying object uri'
- logger.error(`${logPfx} ${errMsg}`)
+ logger.error(`${PerformanceStatistics.logPrefix()} ${errMsg}`)
throw new BaseError(errMsg)
}
if (!PerformanceStatistics.instances.has(objId)) {
return PerformanceStatistics.instances.get(objId)
}
+ public static deleteInstance (objId: string | undefined): boolean {
+ if (objId == null) {
+ const errMsg = 'Cannot delete performance statistics instance without specifying object id'
+ logger.error(`${PerformanceStatistics.logPrefix()} ${errMsg}`)
+ throw new BaseError(errMsg)
+ }
+ return PerformanceStatistics.instances.delete(objId)
+ }
+
public static beginMeasure (id: string): string {
const markId = `${id.charAt(0).toUpperCase()}${id.slice(1)}~${generateUUID()}`
performance.mark(markId)
}
}
+ private static readonly logPrefix = (): string => {
+ return logPrefix(' Performance statistics')
+ }
+
private readonly logPrefix = (): string => {
return logPrefix(` ${this.objName} | Performance statistics`)
}
export enum ChargingStationEvents {
added = 'added',
+ deleted = 'deleted',
started = 'started',
stopped = 'stopped',
updated = 'updated',
LIST_TEMPLATES = 'listTemplates',
LIST_CHARGING_STATIONS = 'listChargingStations',
ADD_CHARGING_STATIONS = 'addChargingStations',
+ DELETE_CHARGING_STATIONS = 'deleteChargingStations',
PERFORMANCE_STATISTICS = 'performanceStatistics',
START_CHARGING_STATION = 'startChargingStation',
STOP_CHARGING_STATION = 'stopChargingStation',
export enum BroadcastChannelProcedureName {
START_CHARGING_STATION = 'startChargingStation',
STOP_CHARGING_STATION = 'stopChargingStation',
+ DELETE_CHARGING_STATIONS = 'deleteChargingStations',
OPEN_CONNECTION = 'openConnection',
CLOSE_CONNECTION = 'closeConnection',
START_AUTOMATIC_TRANSACTION_GENERATOR = 'startAutomaticTransactionGenerator',
private static readonly SEMVER_PATTERN =
'^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$'
- private static readonly DEFAULT_CHARGING_STATION_RESET_TIME = 60000 // Ms
+ private static readonly DEFAULT_CHARGING_STATION_RESET_TIME = 30000 // Ms
static readonly DEFAULT_STATION_INFO: Partial<ChargingStationInfo> = Object.freeze({
enableStatistics: false,
}
}
+export const buildDeletedMessage = (
+ chargingStation: ChargingStation
+): ChargingStationWorkerMessage<ChargingStationData> => {
+ return {
+ event: ChargingStationWorkerMessageEvents.deleted,
+ data: buildChargingStationDataPayload(chargingStation)
+ }
+}
+
export const buildStartedMessage = (
chargingStation: ChargingStation
): ChargingStationWorkerMessage<ChargingStationData> => {
export {
buildAddedMessage,
buildChargingStationDataPayload,
+ buildDeletedMessage,
buildPerformanceStatisticsMessage,
buildStartedMessage,
buildStoppedMessage,
has-property-descriptors: 1.0.1
has-proto: 1.0.1
has-symbols: 1.0.3
- hasown: 2.0.0
+ hasown: 2.0.1
internal-slot: 1.0.7
is-array-buffer: 3.0.4
is-callable: 1.2.7
dependencies:
get-intrinsic: 1.2.4
has-tostringtag: 1.0.2
- hasown: 2.0.0
+ hasown: 2.0.1
dev: true
/es-shim-unscopables@1.0.2:
resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==}
dependencies:
- hasown: 2.0.0
+ hasown: 2.0.1
dev: true
/es-to-primitive@1.2.1:
eslint: 8.56.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
- hasown: 2.0.0
+ hasown: 2.0.1
is-core-module: 2.13.1
is-glob: 4.0.3
minimatch: 3.1.2
function-bind: 1.1.2
has-proto: 1.0.1
has-symbols: 1.0.3
- hasown: 2.0.0
+ hasown: 2.0.1
dev: true
/get-stream@8.0.1:
has-symbols: 1.0.3
dev: true
- /hasown@2.0.0:
- resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==}
+ /hasown@2.0.1:
+ resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==}
engines: {node: '>= 0.4'}
dependencies:
function-bind: 1.1.2
engines: {node: '>= 0.4'}
dependencies:
es-errors: 1.3.0
- hasown: 2.0.0
+ hasown: 2.0.1
side-channel: 1.0.5
dev: true
/is-core-module@2.13.1:
resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
dependencies:
- hasown: 2.0.0
+ hasown: 2.0.1
dev: true
/is-date-object@1.0.5: