matterbridge-example-dynamic-platform 3.0.2-dev-20260802-681c9d9 → 3.0.2-dev-20260808-db970b3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -3
- package/README.md +23 -14
- package/dist/module.js +116 -14
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -35,15 +35,19 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
35
35
|
|
|
36
36
|
### Added
|
|
37
37
|
|
|
38
|
+
- [chip]: Add chip-test toolchain agents instruction and chip-test runner.
|
|
39
|
+
- [frontend]: Add plugin-frontend agents instructions.
|
|
38
40
|
- [platform]: Add `closureGarageDoor` device.
|
|
41
|
+
- [platform]: Add `closureVenetianBlind` device with Lift and Tilt panels.
|
|
39
42
|
|
|
40
43
|
### Changed
|
|
41
44
|
|
|
42
45
|
- [package]: Upgrade package.
|
|
43
46
|
- [package]: Update dependencies.
|
|
44
|
-
- [package]: Bump
|
|
45
|
-
- [package]: Bump `
|
|
46
|
-
- [package]: Bump `
|
|
47
|
+
- [package]: Bump `typescript` to v.7.0.2.
|
|
48
|
+
- [package]: Bump `@types/node` to v.26.2.0.
|
|
49
|
+
- [package]: Bump `oxfmt` to v.0.62.0.
|
|
50
|
+
- [package]: Bump `oxlint` to v.1.77.0.
|
|
47
51
|
- [package]: Bump `oxlint-tsgolint` to v.7.0.2001.
|
|
48
52
|
- [package]: Update agents configs.
|
|
49
53
|
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
Matterbridge dynamic platform example plugin is a template to develop your own plugin using the dynamic platform.
|
|
25
25
|
|
|
26
|
-
It exposes
|
|
26
|
+
It exposes 72 virtual devices:
|
|
27
27
|
|
|
28
28
|
- a door contact sensor
|
|
29
29
|
- a motion sensor
|
|
@@ -96,6 +96,7 @@ It exposes 71 virtual devices:
|
|
|
96
96
|
- an irrigation system (Matter 1.5.0)
|
|
97
97
|
- an irrigation system with four zones (Matter 1.5.0)
|
|
98
98
|
- a closure device (Matter 1.5.0, supported by SmartThings)
|
|
99
|
+
- a closure device with Lift and Tilt panels (Matter 1.5.0, supported by SmartThings)
|
|
99
100
|
|
|
100
101
|
All these devices continuously change their state and position. The plugin also shows how to use all the command handlers (so you can control all the devices), how to subscribe to attributes, and how to trigger events.
|
|
101
102
|
|
|
@@ -111,11 +112,11 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
111
112
|
|
|
112
113
|
See the guidelines on [Matterbridge](https://github.com/Luligu/matterbridge/blob/main/README.md) for more information.
|
|
113
114
|
|
|
114
|
-
## Repository
|
|
115
|
+
## Repository toolchain
|
|
115
116
|
|
|
116
|
-
> **Note:** This repository uses a new toolchain. It replaces the traditional TypeScript / ESLint / Prettier / Jest stack with a faster
|
|
117
|
+
> **Note:** This repository uses a new toolchain. It replaces the traditional TypeScript / ESLint / Prettier / Jest stack with a faster and lighter setup.
|
|
117
118
|
|
|
118
|
-
- **No `typescript` package** — replaced by [TypeScript Native](https://github.com/microsoft/typescript-go).
|
|
119
|
+
- **No `typescript 6.x` package** — replaced by [TypeScript Native 7.x](https://github.com/microsoft/typescript-go).
|
|
119
120
|
- **No ESLint, no Prettier** — replaced by the [oxc](https://oxc.rs) stack: [oxlint](https://oxc.rs/docs/guide/usage/linter.html) for linting and [oxfmt](https://oxc.rs/docs/guide/usage/formatter.html) for formatting.
|
|
120
121
|
- **No Jest** — replaced by [Vitest](https://vitest.dev), which is much faster and natively supports ESM without extra configuration.
|
|
121
122
|
- **Far fewer development dependencies** — the number of installed packages drops from **~600** to **~75**. A clean install is much faster.
|
|
@@ -129,25 +130,33 @@ See also the [Style Guide](./STYLEGUIDE.md) for JSDoc, naming, and logging conve
|
|
|
129
130
|
|
|
130
131
|
## Copilot instructions
|
|
131
132
|
|
|
132
|
-
| File
|
|
133
|
-
|
|
|
134
|
-
| `.github/copilot-instructions.md`
|
|
135
|
-
| `.github/instructions/
|
|
136
|
-
| `.github/instructions/
|
|
133
|
+
| File | Notes |
|
|
134
|
+
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
135
|
+
| `.github/copilot-instructions.md` | Main project instructions — always loaded |
|
|
136
|
+
| `.github/instructions/chip-tests/chip-tests.instructions.md` | CHIP conformance test harness — scoped to CHIP test files |
|
|
137
|
+
| `.github/instructions/matterbridge/matterbridge.instructions.md` | Matterbridge endpoint guide — dedicated Copilot instruction file |
|
|
138
|
+
| `.github/instructions/plugin-frontend/plugin-frontend.instructions.md` | Plugin frontend SPA and custom REST API guide — scoped to frontend and plugin code |
|
|
139
|
+
| `.github/instructions/testing/unit-tests.instructions.md` | Testing standards — scoped to `**/*.test.ts` |
|
|
137
140
|
|
|
138
141
|
## Claude instructions
|
|
139
142
|
|
|
140
|
-
| File
|
|
141
|
-
|
|
|
142
|
-
| `CLAUDE.md`
|
|
143
|
-
| `.claude/rules/
|
|
144
|
-
| `.claude/rules/
|
|
143
|
+
| File | Notes |
|
|
144
|
+
| --------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
145
|
+
| `CLAUDE.md` | Main project instructions — always loaded |
|
|
146
|
+
| `.claude/rules/chip-tests/chip-tests.instructions.md` | CHIP conformance test harness — scoped to CHIP test files |
|
|
147
|
+
| `.claude/rules/matterbridge/matterbridge.instructions.md` | Matterbridge endpoint guide — loaded for all contexts |
|
|
148
|
+
| `.claude/rules/plugin-frontend/plugin-frontend.instructions.md` | Plugin frontend SPA and custom REST API guide — scoped to frontend and plugin code |
|
|
149
|
+
| `.claude/rules/testing/unit-tests.instructions.md` | Testing standards — scoped to `**/*.test.ts` |
|
|
145
150
|
|
|
146
151
|
## Codex/Agents instructions
|
|
147
152
|
|
|
148
153
|
| File | Notes |
|
|
149
154
|
| ---------------------------- | ------------------------------------------------- |
|
|
150
155
|
| `AGENTS.md` | Main project instructions |
|
|
156
|
+
| `.agents/chip-tests.md` | CHIP conformance test harness |
|
|
157
|
+
| `.agents/matterbridge.md` | Matterbridge endpoint guide |
|
|
158
|
+
| `.agents/plugin-frontend.md` | Plugin frontend SPA and custom REST API guide |
|
|
159
|
+
| `.agents/testing.md` | Testing and validation expectations |
|
|
151
160
|
| `.codex/config.toml` | Codex project permissions, approvals, and profile |
|
|
152
161
|
| `.codex/rules/default.rules` | Codex command allow, prompt, and deny rules |
|
|
153
162
|
|
package/dist/module.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { aggregator, airPurifier, airQualitySensor, bridgedNode, colorTemperatureLight, contactSensor, windowCovering, dimmableLight, mountedDimmableLoadControl, dimmablePlugInUnit, doorLock, electricalSensor, extendedColorLight, fan, flowSensor, genericSwitch, getSemtag, humiditySensor, lightSensor, MatterbridgeDynamicPlatform, MatterbridgeEndpoint, modeSelect, occupancySensor, onOffLight, mountedOnOffControl, onOffPlugInUnit, onOffLightSwitch, powerSource, pressureSensor, pump, rainSensor, smokeCoAlarm, temperatureSensor, thermostat, waterFreezeDetector, waterLeakDetector, waterValve, } from 'matterbridge';
|
|
2
2
|
import { AirConditioner, BasicVideoPlayer, BatteryStorage, Closure, Cooktop, Dishwasher, Evse, ExtractorHood, HeatPump, IrrigationSystem, LaundryDryer, LaundryWasher, MicrowaveOven, Oven, Refrigerator, RoboticVacuumCleaner, SoilSensor, SolarPower, Speaker, WaterHeater, } from 'matterbridge/devices';
|
|
3
3
|
import { debugStringify } from 'matterbridge/logger';
|
|
4
|
-
import { ClosureTag, CommonAreaNamespaceTag, CommonLocationTag, CommonNumberTag, CommonPositionTag, RefrigeratorTag, SwitchesTag, UINT16_MAX, UINT32_MAX, } from 'matterbridge/matter';
|
|
5
|
-
import { AirQuality, BooleanState, BridgedDeviceBasicInformation, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, ClosureControl, ColorControl, Descriptor, DeviceEnergyManagement, DoorLock, ElectricalEnergyMeasurement, ElectricalPowerMeasurement, EnergyEvse, EnergyEvseMode, FanControl, FlowMeasurement, FormaldehydeConcentrationMeasurement, Identify, IlluminanceMeasurement, LevelControl, NitrogenDioxideConcentrationMeasurement, OccupancySensing, OnOff, OperationalState, OvenMode, OzoneConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm10ConcentrationMeasurement, Pm25ConcentrationMeasurement, PowerSource, PressureMeasurement, RadonConcentrationMeasurement, RelativeHumidityMeasurement, RvcCleanMode, RvcOperationalState, RvcRunMode, SmokeCoAlarm, TemperatureMeasurement, Thermostat, TotalVolatileOrganicCompoundsConcentrationMeasurement, WindowCovering, } from 'matterbridge/matter/clusters';
|
|
4
|
+
import { ClosureCoveringTag, ClosurePanelTag, ClosureTag, CommonAreaNamespaceTag, CommonLocationTag, CommonNumberTag, CommonPositionTag, RefrigeratorTag, SwitchesTag, UINT16_MAX, UINT32_MAX, } from 'matterbridge/matter';
|
|
5
|
+
import { AirQuality, BooleanState, BridgedDeviceBasicInformation, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, ClosureControl, ClosureDimension, ColorControl, Descriptor, DeviceEnergyManagement, DoorLock, ElectricalEnergyMeasurement, ElectricalPowerMeasurement, EnergyEvse, EnergyEvseMode, FanControl, FlowMeasurement, FormaldehydeConcentrationMeasurement, Identify, IlluminanceMeasurement, LevelControl, NitrogenDioxideConcentrationMeasurement, OccupancySensing, OnOff, OperationalState, OvenMode, OzoneConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm10ConcentrationMeasurement, Pm25ConcentrationMeasurement, PowerSource, PressureMeasurement, RadonConcentrationMeasurement, RelativeHumidityMeasurement, RvcCleanMode, RvcOperationalState, RvcRunMode, SmokeCoAlarm, TemperatureMeasurement, Thermostat, TotalVolatileOrganicCompoundsConcentrationMeasurement, WindowCovering, } from 'matterbridge/matter/clusters';
|
|
6
6
|
import { fireAndForget, getEnumDescription, isValidBoolean, isValidNumber, isValidObject, isValidString } from 'matterbridge/utils';
|
|
7
7
|
function luxToMatter(lux) {
|
|
8
8
|
if (!Number.isFinite(lux) || lux <= 0)
|
|
@@ -35,6 +35,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
|
35
35
|
irrigation;
|
|
36
36
|
irrigationSystem;
|
|
37
37
|
closureGarageDoor;
|
|
38
|
+
closureVenetianBlind;
|
|
38
39
|
select;
|
|
39
40
|
climate;
|
|
40
41
|
switch;
|
|
@@ -179,26 +180,127 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
|
179
180
|
tagList: [getSemtag(ClosureTag.GarageDoor)],
|
|
180
181
|
});
|
|
181
182
|
this.closureGarageDoor = (await this.addDevice(this.closureGarageDoor));
|
|
182
|
-
|
|
183
|
+
let closureGarageDoorMoveTimeout;
|
|
184
|
+
function closureTargetToCurrentPosition(position) {
|
|
185
|
+
if (position === ClosureControl.TargetPosition.MoveToFullyClosed)
|
|
186
|
+
return ClosureControl.CurrentPosition.FullyClosed;
|
|
187
|
+
if (position === ClosureControl.TargetPosition.MoveToFullyOpen)
|
|
188
|
+
return ClosureControl.CurrentPosition.FullyOpened;
|
|
189
|
+
if (position === ClosureControl.TargetPosition.MoveToPedestrianPosition)
|
|
190
|
+
return ClosureControl.CurrentPosition.OpenedForPedestrian;
|
|
191
|
+
if (position === ClosureControl.TargetPosition.MoveToVentilationPosition)
|
|
192
|
+
return ClosureControl.CurrentPosition.OpenedForVentilation;
|
|
193
|
+
return ClosureControl.CurrentPosition.OpenedAtSignature;
|
|
194
|
+
}
|
|
195
|
+
this.closureGarageDoor?.addCommandHandler('ClosureControl.moveTo', ({ request: { position, latch, speed }, attributes }) => {
|
|
183
196
|
this.closureGarageDoor?.log.info(`Command moveTo called position:${position} latch:${latch} speed:${speed}`);
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
if (targetState === undefined || targetState === null)
|
|
197
|
+
attributes.countdownTime = 1;
|
|
198
|
+
closureGarageDoorMoveTimeout = setTimeout(() => {
|
|
199
|
+
const targetState = this.closureGarageDoor?.getAttribute(ClosureControl, 'overallTargetState');
|
|
200
|
+
if (targetState === undefined || targetState === null || targetState.position === undefined || targetState.position === null)
|
|
188
201
|
return;
|
|
189
|
-
void this.closureGarageDoor?.setAttribute(ClosureControl
|
|
190
|
-
void this.closureGarageDoor?.setAttribute(ClosureControl
|
|
191
|
-
|
|
202
|
+
void this.closureGarageDoor?.setAttribute(ClosureControl, 'mainState', ClosureControl.MainState.Stopped, this.closureGarageDoor.log);
|
|
203
|
+
void this.closureGarageDoor?.setAttribute(ClosureControl, 'countdownTime', 0, this.closureGarageDoor.log);
|
|
204
|
+
void this.closureGarageDoor?.setAttribute(ClosureControl, 'overallCurrentState', {
|
|
205
|
+
position: closureTargetToCurrentPosition(targetState.position),
|
|
192
206
|
latch: targetState.latch,
|
|
193
207
|
speed: targetState.speed,
|
|
194
|
-
secureState: targetState.position === ClosureControl.TargetPosition.MoveToFullyClosed
|
|
208
|
+
secureState: targetState.position === ClosureControl.TargetPosition.MoveToFullyClosed && targetState.latch === true,
|
|
195
209
|
}, this.closureGarageDoor.log);
|
|
196
|
-
}, 1000);
|
|
197
|
-
currentStateTimeout.unref();
|
|
210
|
+
}, 1000).unref();
|
|
198
211
|
});
|
|
199
212
|
this.closureGarageDoor?.addCommandHandler('ClosureControl.stop', () => {
|
|
200
213
|
this.closureGarageDoor?.log.info('Command stop called');
|
|
201
|
-
|
|
214
|
+
clearTimeout(closureGarageDoorMoveTimeout);
|
|
215
|
+
closureGarageDoorMoveTimeout = undefined;
|
|
216
|
+
});
|
|
217
|
+
this.closureVenetianBlind = new Closure('Venetian Blind', 'VEN000072', {
|
|
218
|
+
tagList: [getSemtag(ClosureTag.Covering), getSemtag(ClosureCoveringTag.Venetian)],
|
|
219
|
+
});
|
|
220
|
+
const closureVenetianBlindLift = this.closureVenetianBlind.addPanel('Lift', [getSemtag(ClosurePanelTag.Lift)]);
|
|
221
|
+
const closureVenetianBlindTilt = this.closureVenetianBlind.addPanel('Tilt', [getSemtag(ClosurePanelTag.Tilt)]);
|
|
222
|
+
this.closureVenetianBlind = (await this.addDevice(this.closureVenetianBlind));
|
|
223
|
+
const closurePanelTargetPercent = (position) => {
|
|
224
|
+
if (position === ClosureControl.TargetPosition.MoveToFullyOpen)
|
|
225
|
+
return 0;
|
|
226
|
+
if (position === ClosureControl.TargetPosition.MoveToFullyClosed)
|
|
227
|
+
return 10000;
|
|
228
|
+
return 5000;
|
|
229
|
+
};
|
|
230
|
+
const closurePanelReachTimeouts = new Map();
|
|
231
|
+
let closureVenetianBlindMoveTimeout;
|
|
232
|
+
const clearClosureVenetianBlindTimeouts = () => {
|
|
233
|
+
clearTimeout(closureVenetianBlindMoveTimeout);
|
|
234
|
+
closureVenetianBlindMoveTimeout = undefined;
|
|
235
|
+
for (const pending of closurePanelReachTimeouts.values())
|
|
236
|
+
clearTimeout(pending);
|
|
237
|
+
closurePanelReachTimeouts.clear();
|
|
238
|
+
};
|
|
239
|
+
const syncClosureVenetianBlindFromPanels = () => {
|
|
240
|
+
const liftTarget = closureVenetianBlindLift.getAttribute(ClosureDimension, 'targetState');
|
|
241
|
+
const liftCurrent = closureVenetianBlindLift.getAttribute(ClosureDimension, 'currentState');
|
|
242
|
+
const tiltTarget = closureVenetianBlindTilt.getAttribute(ClosureDimension, 'targetState');
|
|
243
|
+
const tiltCurrent = closureVenetianBlindTilt.getAttribute(ClosureDimension, 'currentState');
|
|
244
|
+
if (!liftTarget || !liftCurrent || !tiltTarget || !tiltCurrent)
|
|
245
|
+
return;
|
|
246
|
+
if (liftCurrent.position !== liftTarget.position || tiltCurrent.position !== tiltTarget.position)
|
|
247
|
+
return;
|
|
248
|
+
const overallPosition = liftCurrent.position === 0
|
|
249
|
+
? ClosureControl.CurrentPosition.FullyOpened
|
|
250
|
+
: liftCurrent.position === 10000
|
|
251
|
+
? ClosureControl.CurrentPosition.FullyClosed
|
|
252
|
+
: ClosureControl.CurrentPosition.PartiallyOpened;
|
|
253
|
+
void this.closureVenetianBlind?.setAttribute(ClosureControl, 'mainState', ClosureControl.MainState.Stopped, this.closureVenetianBlind.log);
|
|
254
|
+
void this.closureVenetianBlind?.setAttribute(ClosureControl, 'overallCurrentState', { position: overallPosition, latch: liftCurrent.latch ?? true, speed: liftCurrent.speed, secureState: liftCurrent.position === 10000 && liftCurrent.latch === true }, this.closureVenetianBlind?.log);
|
|
255
|
+
};
|
|
256
|
+
const simulateClosurePanelReachingTarget = (panel) => {
|
|
257
|
+
const pending = closurePanelReachTimeouts.get(panel);
|
|
258
|
+
if (pending)
|
|
259
|
+
clearTimeout(pending);
|
|
260
|
+
const currentStateTimeout = setTimeout(() => {
|
|
261
|
+
void (async () => {
|
|
262
|
+
closurePanelReachTimeouts.delete(panel);
|
|
263
|
+
const targetState = panel.getAttribute(ClosureDimension, 'targetState');
|
|
264
|
+
if (targetState === undefined || targetState === null)
|
|
265
|
+
return;
|
|
266
|
+
await panel.setAttribute(ClosureDimension, 'currentState', targetState, panel.log);
|
|
267
|
+
syncClosureVenetianBlindFromPanels();
|
|
268
|
+
})();
|
|
269
|
+
}, 1000);
|
|
270
|
+
currentStateTimeout.unref();
|
|
271
|
+
closurePanelReachTimeouts.set(panel, currentStateTimeout);
|
|
272
|
+
};
|
|
273
|
+
const moveClosurePanelTo = (panel, position, latch, speed) => {
|
|
274
|
+
void panel.setAttribute(ClosureDimension, 'targetState', { position, latch: latch ?? true, speed }, panel.log);
|
|
275
|
+
simulateClosurePanelReachingTarget(panel);
|
|
276
|
+
};
|
|
277
|
+
this.closureVenetianBlind?.addCommandHandler('ClosureControl.moveTo', ({ request: { position, latch, speed }, attributes }) => {
|
|
278
|
+
this.closureVenetianBlind?.log.info(`Command moveTo called position:${position} latch:${latch} speed:${speed}`);
|
|
279
|
+
attributes.countdownTime = 1;
|
|
280
|
+
clearClosureVenetianBlindTimeouts();
|
|
281
|
+
closureVenetianBlindMoveTimeout = setTimeout(() => {
|
|
282
|
+
void this.closureVenetianBlind?.setAttribute(ClosureControl, 'countdownTime', 0, this.closureVenetianBlind.log);
|
|
283
|
+
closureVenetianBlindMoveTimeout = undefined;
|
|
284
|
+
const targetState = this.closureVenetianBlind?.getAttribute(ClosureControl, 'overallTargetState');
|
|
285
|
+
if (targetState === undefined || targetState === null || targetState.position === undefined || targetState.position === null)
|
|
286
|
+
return;
|
|
287
|
+
const panelPercent = closurePanelTargetPercent(targetState.position);
|
|
288
|
+
moveClosurePanelTo(closureVenetianBlindLift, panelPercent, targetState.latch, targetState.speed);
|
|
289
|
+
moveClosurePanelTo(closureVenetianBlindTilt, panelPercent, targetState.latch, targetState.speed);
|
|
290
|
+
}, 1000).unref();
|
|
291
|
+
});
|
|
292
|
+
this.closureVenetianBlind?.addCommandHandler('ClosureControl.stop', () => {
|
|
293
|
+
this.closureVenetianBlind?.log.info('Command stop called');
|
|
294
|
+
clearClosureVenetianBlindTimeouts();
|
|
295
|
+
});
|
|
296
|
+
const addClosurePanelSetTargetSimulation = (panel) => {
|
|
297
|
+
panel.addCommandHandler('ClosureDimension.setTarget', ({ request: { position, latch, speed } }) => {
|
|
298
|
+
panel.log.info(`Command setTarget called position:${position} latch:${latch} speed:${speed}`);
|
|
299
|
+
simulateClosurePanelReachingTarget(panel);
|
|
300
|
+
});
|
|
301
|
+
};
|
|
302
|
+
addClosurePanelSetTargetSimulation(closureVenetianBlindLift);
|
|
303
|
+
addClosurePanelSetTargetSimulation(closureVenetianBlindTilt);
|
|
202
304
|
this.climate = new MatterbridgeEndpoint([bridgedNode, powerSource], { id: 'Climate' }, this.config.debug)
|
|
203
305
|
.createDefaultBridgedDeviceBasicInformationClusterServer('Climate', 'CLI00008', 0xfff1, 'Matterbridge', 'Matterbridge Climate')
|
|
204
306
|
.createDefaultPowerSourceReplaceableBatteryClusterServer(90, PowerSource.BatChargeLevel.Ok, 2990, '2 x AA', 2, PowerSource.BatReplaceability.UserReplaceable)
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge-example-dynamic-platform",
|
|
3
|
-
"version": "3.0.2-dev-
|
|
3
|
+
"version": "3.0.2-dev-20260808-db970b3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "matterbridge-example-dynamic-platform",
|
|
9
|
-
"version": "3.0.2-dev-
|
|
9
|
+
"version": "3.0.2-dev-20260808-db970b3",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"node-ansi-logger": "3.3.0",
|
package/package.json
CHANGED