@cardog/ocm-client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/LICENSE +21 -0
- package/README.md +300 -0
- package/dist/index.cjs +328 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +866 -0
- package/dist/index.d.ts +866 -0
- package/dist/index.js +293 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2024-12-30
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Initial release
|
|
15
|
+
- `OCMClient` class with full API support
|
|
16
|
+
- `searchPOI()` - Search charging stations with filters (location, distance, connector types, power, etc.)
|
|
17
|
+
- `getPOI()` - Get a specific charging station by ID
|
|
18
|
+
- `searchPOIGeoJSON()` - Get search results in GeoJSON format
|
|
19
|
+
- `getPOIUpdates()` - Get stations modified since a specific date
|
|
20
|
+
- `getReferenceData()` - Fetch all lookup tables (connection types, status types, etc.)
|
|
21
|
+
- `authenticate()` - User authentication
|
|
22
|
+
- `submitPOI()` - Submit new charging stations (requires auth)
|
|
23
|
+
- `submitComment()` - Submit comments/check-ins (requires auth)
|
|
24
|
+
- Full TypeScript types for all OCM API entities
|
|
25
|
+
- Standard enums for connection types, status types, usage types
|
|
26
|
+
- `OCMAPIError` class for structured error handling
|
|
27
|
+
- ESM and CommonJS builds
|
|
28
|
+
- Full TypeScript declarations
|
|
29
|
+
|
|
30
|
+
[Unreleased]: https://github.com/cardog-ai/ocm-client/compare/v0.1.0...HEAD
|
|
31
|
+
[0.1.0]: https://github.com/cardog-ai/ocm-client/releases/tag/v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Cardog
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# @cardog/ocm-client
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@cardog/ocm-client)
|
|
4
|
+
[](https://www.npmjs.com/package/@cardog/ocm-client)
|
|
5
|
+
[](https://github.com/cardog-ai/ocm-client/actions/workflows/ci.yml)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
A TypeScript client for the [Open Charge Map](https://openchargemap.org) API — the world's largest open database of EV charging stations.
|
|
10
|
+
|
|
11
|
+
## About Open Charge Map
|
|
12
|
+
|
|
13
|
+
[Open Charge Map (OCM)](https://openchargemap.org) is a non-commercial, community-driven project that provides free access to EV charging location data worldwide. Since 2011, OCM has been the go-to open data source for EV charging infrastructure.
|
|
14
|
+
|
|
15
|
+
**This is an unofficial client library.** Please consider [supporting OCM](https://opencollective.com/openchargemap) if you find it useful.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# npm
|
|
21
|
+
npm install @cardog/ocm-client
|
|
22
|
+
|
|
23
|
+
# pnpm
|
|
24
|
+
pnpm add @cardog/ocm-client
|
|
25
|
+
|
|
26
|
+
# yarn
|
|
27
|
+
yarn add @cardog/ocm-client
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { createOCMClient } from "@cardog/ocm-client";
|
|
34
|
+
|
|
35
|
+
// Get your API key at https://openchargemap.org/site/profile
|
|
36
|
+
const client = createOCMClient({
|
|
37
|
+
apiKey: "your-api-key",
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Search for nearby charging stations
|
|
41
|
+
const stations = await client.searchPOI({
|
|
42
|
+
latitude: 37.7749,
|
|
43
|
+
longitude: -122.4194,
|
|
44
|
+
distance: 10,
|
|
45
|
+
distanceunit: "km",
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
console.log(`Found ${stations.length} charging stations`);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Features
|
|
52
|
+
|
|
53
|
+
- Full TypeScript support with comprehensive type definitions
|
|
54
|
+
- ESM and CommonJS builds
|
|
55
|
+
- All OCM API v4 endpoints covered
|
|
56
|
+
- Standard enums for connection types, status types, etc.
|
|
57
|
+
- Structured error handling
|
|
58
|
+
- Zero dependencies (uses native `fetch`)
|
|
59
|
+
|
|
60
|
+
## API Reference
|
|
61
|
+
|
|
62
|
+
### Creating a Client
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { createOCMClient, OCMClient } from "@cardog/ocm-client";
|
|
66
|
+
|
|
67
|
+
const client = createOCMClient({
|
|
68
|
+
apiKey: "your-api-key", // Required - get one at openchargemap.org
|
|
69
|
+
baseUrl: "https://api.openchargemap.io", // Optional
|
|
70
|
+
timeout: 30000, // Optional, in milliseconds
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Searching Charging Stations
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// Basic location search
|
|
78
|
+
const stations = await client.searchPOI({
|
|
79
|
+
latitude: 37.7749,
|
|
80
|
+
longitude: -122.4194,
|
|
81
|
+
distance: 25,
|
|
82
|
+
distanceunit: "miles",
|
|
83
|
+
maxresults: 100,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Filter by connector type
|
|
87
|
+
import { StandardConnectionTypes } from "@cardog/ocm-client";
|
|
88
|
+
|
|
89
|
+
const ccsStations = await client.searchPOI({
|
|
90
|
+
latitude: 37.7749,
|
|
91
|
+
longitude: -122.4194,
|
|
92
|
+
distance: 50,
|
|
93
|
+
connectiontypeid: [
|
|
94
|
+
StandardConnectionTypes.CCSCombo1,
|
|
95
|
+
StandardConnectionTypes.CCSCombo2,
|
|
96
|
+
],
|
|
97
|
+
minpowerkw: 50, // DC fast chargers only
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Filter by country
|
|
101
|
+
const ukStations = await client.searchPOI({
|
|
102
|
+
countrycode: "GB",
|
|
103
|
+
maxresults: 500,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Get as GeoJSON (great for mapping)
|
|
107
|
+
const geojson = await client.searchPOIGeoJSON({
|
|
108
|
+
latitude: 37.7749,
|
|
109
|
+
longitude: -122.4194,
|
|
110
|
+
distance: 10,
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Get a Single Station
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
const station = await client.getPOI(123456);
|
|
118
|
+
|
|
119
|
+
if (station) {
|
|
120
|
+
console.log(station.AddressInfo.Title);
|
|
121
|
+
console.log(station.Connections);
|
|
122
|
+
console.log(station.OperatorInfo?.Title);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Reference Data
|
|
127
|
+
|
|
128
|
+
OCM uses lookup tables for connection types, operators, status types, etc. Fetch and cache this data locally:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
const refData = await client.getReferenceData();
|
|
132
|
+
|
|
133
|
+
// Connection types (J1772, CCS, CHAdeMO, Tesla, etc.)
|
|
134
|
+
console.log(refData.ConnectionTypes);
|
|
135
|
+
|
|
136
|
+
// Status types (Operational, Not Operational, etc.)
|
|
137
|
+
console.log(refData.StatusTypes);
|
|
138
|
+
|
|
139
|
+
// Usage types (Public, Private, Membership Required, etc.)
|
|
140
|
+
console.log(refData.UsageTypes);
|
|
141
|
+
|
|
142
|
+
// Network operators (ChargePoint, Electrify America, etc.)
|
|
143
|
+
console.log(refData.Operators);
|
|
144
|
+
|
|
145
|
+
// Countries
|
|
146
|
+
console.log(refData.Countries);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Syncing Updates
|
|
150
|
+
|
|
151
|
+
Efficiently sync changes since your last update:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const lastSync = new Date("2024-01-01");
|
|
155
|
+
const updates = await client.getPOIUpdates(lastSync, {
|
|
156
|
+
countrycode: "US",
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Authentication & Submissions
|
|
161
|
+
|
|
162
|
+
For submitting new stations or comments, you'll need to authenticate:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// Authenticate (stores session token automatically)
|
|
166
|
+
await client.authenticate({
|
|
167
|
+
EmailAddress: "user@example.com",
|
|
168
|
+
Password: "password",
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Submit a new charging station
|
|
172
|
+
const result = await client.submitPOI({
|
|
173
|
+
AddressInfo: {
|
|
174
|
+
Title: "New Charging Station",
|
|
175
|
+
AddressLine1: "123 Main St",
|
|
176
|
+
Town: "San Francisco",
|
|
177
|
+
StateOrProvince: "CA",
|
|
178
|
+
CountryID: 2, // USA
|
|
179
|
+
Latitude: 37.7749,
|
|
180
|
+
Longitude: -122.4194,
|
|
181
|
+
},
|
|
182
|
+
Connections: [
|
|
183
|
+
{
|
|
184
|
+
ConnectionTypeID: 32, // CCS Combo 1
|
|
185
|
+
PowerKW: 150,
|
|
186
|
+
Quantity: 2,
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
UsageTypeID: 1, // Public
|
|
190
|
+
StatusTypeID: 50, // Operational
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Submit a comment/check-in
|
|
194
|
+
await client.submitComment({
|
|
195
|
+
ChargePointID: 123456,
|
|
196
|
+
Comment: "All chargers working!",
|
|
197
|
+
Rating: 5,
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Types
|
|
202
|
+
|
|
203
|
+
All types are exported for your convenience:
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
import type {
|
|
207
|
+
// Core entities
|
|
208
|
+
ChargePoint,
|
|
209
|
+
POI, // Alias for ChargePoint
|
|
210
|
+
ConnectionInfo,
|
|
211
|
+
AddressInfo,
|
|
212
|
+
UserComment,
|
|
213
|
+
|
|
214
|
+
// Reference data
|
|
215
|
+
CoreReferenceData,
|
|
216
|
+
ConnectionType,
|
|
217
|
+
StatusType,
|
|
218
|
+
UsageType,
|
|
219
|
+
OperatorInfo,
|
|
220
|
+
Country,
|
|
221
|
+
|
|
222
|
+
// Enums
|
|
223
|
+
StandardConnectionTypes,
|
|
224
|
+
StandardStatusTypes,
|
|
225
|
+
StandardUsageTypes,
|
|
226
|
+
StandardCurrentTypes,
|
|
227
|
+
|
|
228
|
+
// Requests
|
|
229
|
+
POISearchParams,
|
|
230
|
+
AuthenticateResponse,
|
|
231
|
+
} from "@cardog/ocm-client";
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Common Connection Types
|
|
235
|
+
|
|
236
|
+
| ID | Type | Description |
|
|
237
|
+
| --- | --------------------- | -------------------- |
|
|
238
|
+
| 1 | J1772 | Type 1 (North America) |
|
|
239
|
+
| 2 | CHAdeMO | DC Fast (Japanese) |
|
|
240
|
+
| 25 | Type 2 (Mennekes) | AC (Europe) |
|
|
241
|
+
| 27 | Tesla (Roadster) | Legacy Tesla |
|
|
242
|
+
| 30 | Tesla Supercharger | Tesla DC |
|
|
243
|
+
| 32 | CCS Combo 1 | DC Fast (N. America) |
|
|
244
|
+
| 33 | CCS Combo 2 | DC Fast (Europe) |
|
|
245
|
+
| 36 | NACS | Tesla connector |
|
|
246
|
+
|
|
247
|
+
## Error Handling
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { OCMAPIError } from "@cardog/ocm-client";
|
|
251
|
+
|
|
252
|
+
try {
|
|
253
|
+
const stations = await client.searchPOI({
|
|
254
|
+
latitude: 0,
|
|
255
|
+
longitude: 0,
|
|
256
|
+
});
|
|
257
|
+
} catch (error) {
|
|
258
|
+
if (error instanceof OCMAPIError) {
|
|
259
|
+
console.error(`API Error ${error.status}: ${error.message}`);
|
|
260
|
+
|
|
261
|
+
switch (error.code) {
|
|
262
|
+
case "APIKEY_MISSING":
|
|
263
|
+
console.error("API key is required");
|
|
264
|
+
break;
|
|
265
|
+
case "APIKEY_INVALID":
|
|
266
|
+
console.error("Invalid API key");
|
|
267
|
+
break;
|
|
268
|
+
case "RATE_LIMITED":
|
|
269
|
+
console.error("Rate limit exceeded");
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Rate Limits
|
|
277
|
+
|
|
278
|
+
OCM has soft rate limits (~10,000 requests/day for registered users). The API tracks usage per key per month. Be respectful of the service — it's run by volunteers.
|
|
279
|
+
|
|
280
|
+
Tips:
|
|
281
|
+
- Cache `getReferenceData()` results (they rarely change)
|
|
282
|
+
- Use `getPOIUpdates()` for incremental syncing
|
|
283
|
+
- Batch requests where possible
|
|
284
|
+
|
|
285
|
+
## Requirements
|
|
286
|
+
|
|
287
|
+
- Node.js 18+
|
|
288
|
+
- An OCM API key ([get one here](https://openchargemap.org/site/profile))
|
|
289
|
+
|
|
290
|
+
## Contributing
|
|
291
|
+
|
|
292
|
+
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
293
|
+
|
|
294
|
+
## License
|
|
295
|
+
|
|
296
|
+
MIT © [Cardog](https://cardog.io)
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
**Disclaimer:** This is an unofficial client library and is not affiliated with or endorsed by Open Charge Map. OCM data is provided under the [Open Database License (ODbL)](https://opendatacommons.org/licenses/odbl/).
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ChargingLevels: () => ChargingLevels,
|
|
24
|
+
OCMAPIError: () => OCMAPIError,
|
|
25
|
+
OCMClient: () => OCMClient,
|
|
26
|
+
StandardConnectionTypes: () => StandardConnectionTypes,
|
|
27
|
+
StandardCurrentTypes: () => StandardCurrentTypes,
|
|
28
|
+
StandardStatusTypes: () => StandardStatusTypes,
|
|
29
|
+
StandardSubmissionStatusTypes: () => StandardSubmissionStatusTypes,
|
|
30
|
+
StandardUsageTypes: () => StandardUsageTypes,
|
|
31
|
+
createOCMClient: () => createOCMClient
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(index_exports);
|
|
34
|
+
|
|
35
|
+
// src/client.ts
|
|
36
|
+
var DEFAULT_BASE_URL = "https://api.openchargemap.io";
|
|
37
|
+
var DEFAULT_VERSION = "v4";
|
|
38
|
+
var OCMClient = class {
|
|
39
|
+
apiKey;
|
|
40
|
+
baseUrl;
|
|
41
|
+
version;
|
|
42
|
+
fetchFn;
|
|
43
|
+
timeout;
|
|
44
|
+
sessionToken;
|
|
45
|
+
constructor(options) {
|
|
46
|
+
if (!options.apiKey) {
|
|
47
|
+
throw new Error("API key is required");
|
|
48
|
+
}
|
|
49
|
+
this.apiKey = options.apiKey;
|
|
50
|
+
this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
|
|
51
|
+
this.version = options.version ?? DEFAULT_VERSION;
|
|
52
|
+
this.fetchFn = options.fetch ?? globalThis.fetch;
|
|
53
|
+
this.timeout = options.timeout ?? 3e4;
|
|
54
|
+
this.sessionToken = options.sessionToken;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Build URL with query parameters
|
|
58
|
+
*/
|
|
59
|
+
buildUrl(endpoint, params) {
|
|
60
|
+
const url = new URL(`/${this.version}${endpoint}`, this.baseUrl);
|
|
61
|
+
if (params) {
|
|
62
|
+
for (const [key, value] of Object.entries(params)) {
|
|
63
|
+
if (value === void 0 || value === null) continue;
|
|
64
|
+
if (Array.isArray(value)) {
|
|
65
|
+
url.searchParams.set(key, value.join(","));
|
|
66
|
+
} else if (value instanceof Date) {
|
|
67
|
+
url.searchParams.set(key, value.toISOString());
|
|
68
|
+
} else {
|
|
69
|
+
url.searchParams.set(key, String(value));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return url.toString();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Make a request with proper headers and error handling
|
|
77
|
+
*/
|
|
78
|
+
async request(endpoint, options = {}) {
|
|
79
|
+
const { method = "GET", params, body } = options;
|
|
80
|
+
const url = this.buildUrl(endpoint, params);
|
|
81
|
+
const headers = {
|
|
82
|
+
"X-API-Key": this.apiKey,
|
|
83
|
+
"Content-Type": "application/json"
|
|
84
|
+
};
|
|
85
|
+
if (this.sessionToken) {
|
|
86
|
+
headers["Authorization"] = `Bearer ${this.sessionToken}`;
|
|
87
|
+
}
|
|
88
|
+
const controller = new AbortController();
|
|
89
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
90
|
+
try {
|
|
91
|
+
const response = await this.fetchFn(url, {
|
|
92
|
+
method,
|
|
93
|
+
headers,
|
|
94
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
95
|
+
signal: controller.signal
|
|
96
|
+
});
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
const errorText = await response.text();
|
|
99
|
+
throw new OCMAPIError(response.status, errorText);
|
|
100
|
+
}
|
|
101
|
+
return response.json();
|
|
102
|
+
} finally {
|
|
103
|
+
clearTimeout(timeoutId);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// ============================================
|
|
107
|
+
// POI (Point of Interest) Methods
|
|
108
|
+
// ============================================
|
|
109
|
+
/**
|
|
110
|
+
* Search for charging stations
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```ts
|
|
114
|
+
* // Nearby search
|
|
115
|
+
* const stations = await client.searchPOI({
|
|
116
|
+
* latitude: 37.7749,
|
|
117
|
+
* longitude: -122.4194,
|
|
118
|
+
* distance: 10,
|
|
119
|
+
* distanceunit: "km"
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* // Fast chargers only
|
|
123
|
+
* const fastChargers = await client.searchPOI({
|
|
124
|
+
* latitude: 37.7749,
|
|
125
|
+
* longitude: -122.4194,
|
|
126
|
+
* connectiontypeid: [32, 33], // CCS Combo
|
|
127
|
+
* minpowerkw: 50
|
|
128
|
+
* });
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
async searchPOI(params = {}) {
|
|
132
|
+
return this.request("/poi", {
|
|
133
|
+
params
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get a specific POI by ID
|
|
138
|
+
*/
|
|
139
|
+
async getPOI(id, verbose = true) {
|
|
140
|
+
const results = await this.request("/poi", {
|
|
141
|
+
params: { chargepointid: id, verbose }
|
|
142
|
+
});
|
|
143
|
+
return results[0] ?? null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Search POIs and return GeoJSON format
|
|
147
|
+
*/
|
|
148
|
+
async searchPOIGeoJSON(params) {
|
|
149
|
+
return this.request("/poi", {
|
|
150
|
+
params: { ...params, output: "geojson" }
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get POIs modified since a specific date
|
|
155
|
+
* Useful for syncing/caching
|
|
156
|
+
*/
|
|
157
|
+
async getPOIUpdates(since, params = {}) {
|
|
158
|
+
return this.searchPOI({ ...params, modifiedsince: since });
|
|
159
|
+
}
|
|
160
|
+
// ============================================
|
|
161
|
+
// Reference Data Methods
|
|
162
|
+
// ============================================
|
|
163
|
+
/**
|
|
164
|
+
* Get all reference data (lookup tables)
|
|
165
|
+
* Results should be cached locally
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```ts
|
|
169
|
+
* const refData = await client.getReferenceData();
|
|
170
|
+
* console.log(refData.ConnectionTypes);
|
|
171
|
+
* console.log(refData.StatusTypes);
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
async getReferenceData() {
|
|
175
|
+
return this.request("/referencedata");
|
|
176
|
+
}
|
|
177
|
+
// ============================================
|
|
178
|
+
// Authentication Methods
|
|
179
|
+
// ============================================
|
|
180
|
+
/**
|
|
181
|
+
* Authenticate user and get session token
|
|
182
|
+
* Store the sessionToken for subsequent authenticated requests
|
|
183
|
+
*/
|
|
184
|
+
async authenticate(credentials) {
|
|
185
|
+
const response = await this.request(
|
|
186
|
+
"/profile/authenticate",
|
|
187
|
+
{
|
|
188
|
+
method: "POST",
|
|
189
|
+
body: credentials
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
if (response.CurrentSessionToken) {
|
|
193
|
+
this.sessionToken = response.CurrentSessionToken;
|
|
194
|
+
}
|
|
195
|
+
return response;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Set session token for authenticated requests
|
|
199
|
+
*/
|
|
200
|
+
setSessionToken(token) {
|
|
201
|
+
this.sessionToken = token;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Clear session token
|
|
205
|
+
*/
|
|
206
|
+
clearSession() {
|
|
207
|
+
this.sessionToken = void 0;
|
|
208
|
+
}
|
|
209
|
+
// ============================================
|
|
210
|
+
// Submission Methods (Require Authentication)
|
|
211
|
+
// ============================================
|
|
212
|
+
/**
|
|
213
|
+
* Submit a new POI
|
|
214
|
+
* Requires authentication
|
|
215
|
+
*/
|
|
216
|
+
async submitPOI(poi) {
|
|
217
|
+
if (!this.sessionToken) {
|
|
218
|
+
throw new Error("Authentication required. Call authenticate() first.");
|
|
219
|
+
}
|
|
220
|
+
return this.request("/system/poi", {
|
|
221
|
+
method: "POST",
|
|
222
|
+
body: poi
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Submit a comment/check-in on a POI
|
|
227
|
+
* Requires authentication
|
|
228
|
+
*/
|
|
229
|
+
async submitComment(comment) {
|
|
230
|
+
if (!this.sessionToken) {
|
|
231
|
+
throw new Error("Authentication required. Call authenticate() first.");
|
|
232
|
+
}
|
|
233
|
+
return this.request("/system/comment", {
|
|
234
|
+
method: "POST",
|
|
235
|
+
body: comment
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
var OCMAPIError = class extends Error {
|
|
240
|
+
status;
|
|
241
|
+
code;
|
|
242
|
+
constructor(status, message) {
|
|
243
|
+
super(message);
|
|
244
|
+
this.name = "OCMAPIError";
|
|
245
|
+
this.status = status;
|
|
246
|
+
if (message.includes("REJECTED_APIKEY_MISSING")) {
|
|
247
|
+
this.code = "APIKEY_MISSING";
|
|
248
|
+
} else if (message.includes("REJECTED_APIKEY_INVALID")) {
|
|
249
|
+
this.code = "APIKEY_INVALID";
|
|
250
|
+
} else if (message.includes("Blocked for API Abuse")) {
|
|
251
|
+
this.code = "RATE_LIMITED";
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
function createOCMClient(options) {
|
|
256
|
+
return new OCMClient(options);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// src/types/enums.ts
|
|
260
|
+
var StandardConnectionTypes = /* @__PURE__ */ ((StandardConnectionTypes2) => {
|
|
261
|
+
StandardConnectionTypes2[StandardConnectionTypes2["Unknown"] = 0] = "Unknown";
|
|
262
|
+
StandardConnectionTypes2[StandardConnectionTypes2["J1772"] = 1] = "J1772";
|
|
263
|
+
StandardConnectionTypes2[StandardConnectionTypes2["CHAdeMO"] = 2] = "CHAdeMO";
|
|
264
|
+
StandardConnectionTypes2[StandardConnectionTypes2["Type2Mennekes"] = 25] = "Type2Mennekes";
|
|
265
|
+
StandardConnectionTypes2[StandardConnectionTypes2["Type2Outlet"] = 28] = "Type2Outlet";
|
|
266
|
+
StandardConnectionTypes2[StandardConnectionTypes2["CCSCombo1"] = 32] = "CCSCombo1";
|
|
267
|
+
StandardConnectionTypes2[StandardConnectionTypes2["CCSCombo2"] = 33] = "CCSCombo2";
|
|
268
|
+
StandardConnectionTypes2[StandardConnectionTypes2["Tesla"] = 27] = "Tesla";
|
|
269
|
+
StandardConnectionTypes2[StandardConnectionTypes2["TeslaSupercharger"] = 30] = "TeslaSupercharger";
|
|
270
|
+
StandardConnectionTypes2[StandardConnectionTypes2["NACS"] = 36] = "NACS";
|
|
271
|
+
StandardConnectionTypes2[StandardConnectionTypes2["Type1CCS"] = 32] = "Type1CCS";
|
|
272
|
+
StandardConnectionTypes2[StandardConnectionTypes2["Type2CCS"] = 33] = "Type2CCS";
|
|
273
|
+
return StandardConnectionTypes2;
|
|
274
|
+
})(StandardConnectionTypes || {});
|
|
275
|
+
var StandardStatusTypes = /* @__PURE__ */ ((StandardStatusTypes2) => {
|
|
276
|
+
StandardStatusTypes2[StandardStatusTypes2["Unknown"] = 0] = "Unknown";
|
|
277
|
+
StandardStatusTypes2[StandardStatusTypes2["CurrentlyAvailable"] = 50] = "CurrentlyAvailable";
|
|
278
|
+
StandardStatusTypes2[StandardStatusTypes2["Operational"] = 50] = "Operational";
|
|
279
|
+
StandardStatusTypes2[StandardStatusTypes2["NotOperational"] = 100] = "NotOperational";
|
|
280
|
+
StandardStatusTypes2[StandardStatusTypes2["PlannedForFuture"] = 150] = "PlannedForFuture";
|
|
281
|
+
StandardStatusTypes2[StandardStatusTypes2["TemporarilyUnavailable"] = 75] = "TemporarilyUnavailable";
|
|
282
|
+
StandardStatusTypes2[StandardStatusTypes2["Removed"] = 200] = "Removed";
|
|
283
|
+
return StandardStatusTypes2;
|
|
284
|
+
})(StandardStatusTypes || {});
|
|
285
|
+
var StandardUsageTypes = /* @__PURE__ */ ((StandardUsageTypes2) => {
|
|
286
|
+
StandardUsageTypes2[StandardUsageTypes2["Unknown"] = 0] = "Unknown";
|
|
287
|
+
StandardUsageTypes2[StandardUsageTypes2["Public"] = 1] = "Public";
|
|
288
|
+
StandardUsageTypes2[StandardUsageTypes2["PublicMembershipRequired"] = 4] = "PublicMembershipRequired";
|
|
289
|
+
StandardUsageTypes2[StandardUsageTypes2["PublicPayAtLocation"] = 5] = "PublicPayAtLocation";
|
|
290
|
+
StandardUsageTypes2[StandardUsageTypes2["PublicNoticeRequired"] = 7] = "PublicNoticeRequired";
|
|
291
|
+
StandardUsageTypes2[StandardUsageTypes2["Private"] = 2] = "Private";
|
|
292
|
+
StandardUsageTypes2[StandardUsageTypes2["PrivateForStaffAndVisitors"] = 6] = "PrivateForStaffAndVisitors";
|
|
293
|
+
StandardUsageTypes2[StandardUsageTypes2["PrivateResidential"] = 3] = "PrivateResidential";
|
|
294
|
+
return StandardUsageTypes2;
|
|
295
|
+
})(StandardUsageTypes || {});
|
|
296
|
+
var StandardCurrentTypes = /* @__PURE__ */ ((StandardCurrentTypes2) => {
|
|
297
|
+
StandardCurrentTypes2[StandardCurrentTypes2["Unknown"] = 0] = "Unknown";
|
|
298
|
+
StandardCurrentTypes2[StandardCurrentTypes2["AC_SinglePhase"] = 10] = "AC_SinglePhase";
|
|
299
|
+
StandardCurrentTypes2[StandardCurrentTypes2["AC_ThreePhase"] = 20] = "AC_ThreePhase";
|
|
300
|
+
StandardCurrentTypes2[StandardCurrentTypes2["DC"] = 30] = "DC";
|
|
301
|
+
return StandardCurrentTypes2;
|
|
302
|
+
})(StandardCurrentTypes || {});
|
|
303
|
+
var ChargingLevels = /* @__PURE__ */ ((ChargingLevels2) => {
|
|
304
|
+
ChargingLevels2[ChargingLevels2["Level1"] = 1] = "Level1";
|
|
305
|
+
ChargingLevels2[ChargingLevels2["Level2"] = 2] = "Level2";
|
|
306
|
+
ChargingLevels2[ChargingLevels2["Level3_DCFastCharging"] = 3] = "Level3_DCFastCharging";
|
|
307
|
+
return ChargingLevels2;
|
|
308
|
+
})(ChargingLevels || {});
|
|
309
|
+
var StandardSubmissionStatusTypes = /* @__PURE__ */ ((StandardSubmissionStatusTypes2) => {
|
|
310
|
+
StandardSubmissionStatusTypes2[StandardSubmissionStatusTypes2["Submitted_UnderReview"] = 1] = "Submitted_UnderReview";
|
|
311
|
+
StandardSubmissionStatusTypes2[StandardSubmissionStatusTypes2["Imported_UnverifiedOrLowQuality"] = 100] = "Imported_UnverifiedOrLowQuality";
|
|
312
|
+
StandardSubmissionStatusTypes2[StandardSubmissionStatusTypes2["Imported_Published"] = 200] = "Imported_Published";
|
|
313
|
+
StandardSubmissionStatusTypes2[StandardSubmissionStatusTypes2["Submitted_Published"] = 1e3] = "Submitted_Published";
|
|
314
|
+
return StandardSubmissionStatusTypes2;
|
|
315
|
+
})(StandardSubmissionStatusTypes || {});
|
|
316
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
317
|
+
0 && (module.exports = {
|
|
318
|
+
ChargingLevels,
|
|
319
|
+
OCMAPIError,
|
|
320
|
+
OCMClient,
|
|
321
|
+
StandardConnectionTypes,
|
|
322
|
+
StandardCurrentTypes,
|
|
323
|
+
StandardStatusTypes,
|
|
324
|
+
StandardSubmissionStatusTypes,
|
|
325
|
+
StandardUsageTypes,
|
|
326
|
+
createOCMClient
|
|
327
|
+
});
|
|
328
|
+
//# sourceMappingURL=index.cjs.map
|