@uk-open-data-connectors/uk-sources 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/README.md +206 -0
- package/dist/ancientWoodland.d.ts +102 -0
- package/dist/ancientWoodland.d.ts.map +1 -0
- package/dist/ancientWoodland.js +245 -0
- package/dist/ancientWoodland.js.map +1 -0
- package/dist/bankRate.d.ts +107 -0
- package/dist/bankRate.d.ts.map +1 -0
- package/dist/bankRate.js +251 -0
- package/dist/bankRate.js.map +1 -0
- package/dist/carbonIntensity.d.ts +151 -0
- package/dist/carbonIntensity.d.ts.map +1 -0
- package/dist/carbonIntensity.js +257 -0
- package/dist/carbonIntensity.js.map +1 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +26 -0
- package/dist/errors.js.map +1 -0
- package/dist/fixtures.d.ts +5 -0
- package/dist/fixtures.d.ts.map +1 -0
- package/dist/fixtures.js +11 -0
- package/dist/fixtures.js.map +1 -0
- package/dist/floodMonitoring.d.ts +70 -0
- package/dist/floodMonitoring.d.ts.map +1 -0
- package/dist/floodMonitoring.js +164 -0
- package/dist/floodMonitoring.js.map +1 -0
- package/dist/foodHygiene.d.ts +68 -0
- package/dist/foodHygiene.d.ts.map +1 -0
- package/dist/foodHygiene.js +103 -0
- package/dist/foodHygiene.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/onsDatasets.d.ts +67 -0
- package/dist/onsDatasets.d.ts.map +1 -0
- package/dist/onsDatasets.js +111 -0
- package/dist/onsDatasets.js.map +1 -0
- package/dist/parliamentSeats.d.ts +115 -0
- package/dist/parliamentSeats.d.ts.map +1 -0
- package/dist/parliamentSeats.js +202 -0
- package/dist/parliamentSeats.js.map +1 -0
- package/dist/planningDatasets.d.ts +65 -0
- package/dist/planningDatasets.d.ts.map +1 -0
- package/dist/planningDatasets.js +100 -0
- package/dist/planningDatasets.js.map +1 -0
- package/dist/policeCrimes.d.ts +152 -0
- package/dist/policeCrimes.d.ts.map +1 -0
- package/dist/policeCrimes.js +262 -0
- package/dist/policeCrimes.js.map +1 -0
- package/dist/registry.d.ts +17 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +67 -0
- package/dist/registry.js.map +1 -0
- package/dist/tflBikePoints.d.ts +65 -0
- package/dist/tflBikePoints.d.ts.map +1 -0
- package/dist/tflBikePoints.js +149 -0
- package/dist/tflBikePoints.js.map +1 -0
- package/dist/types.d.ts +30 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { UkDataAdapter } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The Bank of England's official Bank Rate, published in the Bank's
|
|
4
|
+
* Interactive Statistical Database (IADB). Keyless: the database answers
|
|
5
|
+
* without a key, and the series is the one the Bank's own statistics pages
|
|
6
|
+
* read: <https://www.bankofengland.co.uk/statistics>.
|
|
7
|
+
*/
|
|
8
|
+
export declare const BANK_RATE_SOURCE_ID = "bank-rate";
|
|
9
|
+
/** The IADB series code for the daily official Bank Rate. */
|
|
10
|
+
export declare const BANK_RATE_SERIES_CODE = "IUDBEDR";
|
|
11
|
+
/** The IADB CSV endpoint, before the query string is added. */
|
|
12
|
+
export declare const BANK_RATE_CSV_URL = "https://www.bankofengland.co.uk/boeapps/database/_iadb-fromshowcolumns.asp";
|
|
13
|
+
/**
|
|
14
|
+
* First date the database holds for the daily series, in the database's own
|
|
15
|
+
* query format. Asking for an earlier start returns the database's error
|
|
16
|
+
* page rather than a CSV, so the adapter never asks for one.
|
|
17
|
+
*/
|
|
18
|
+
export declare const BANK_RATE_FIRST_QUERY_DATE = "02/Jan/1975";
|
|
19
|
+
/** One date reading: the rate that stood on that day. */
|
|
20
|
+
export interface BankRateObservation {
|
|
21
|
+
/** ISO date, e.g. "1975-01-02". */
|
|
22
|
+
date: string;
|
|
23
|
+
/** The rate on that day, in per cent per year. */
|
|
24
|
+
ratePercent: number;
|
|
25
|
+
}
|
|
26
|
+
/** One unbroken run at a single level. */
|
|
27
|
+
export interface BankRateSpell {
|
|
28
|
+
startDate: string;
|
|
29
|
+
endDate: string;
|
|
30
|
+
ratePercent: number;
|
|
31
|
+
/** Calendar days from the first reading to the last, both counted. */
|
|
32
|
+
dayCount: number;
|
|
33
|
+
}
|
|
34
|
+
/** Rolled-up shape of the whole series. */
|
|
35
|
+
export interface BankRateSummary {
|
|
36
|
+
/** Daily readings the series carried. */
|
|
37
|
+
observationCount: number;
|
|
38
|
+
/** Times the rate moved to a new level. */
|
|
39
|
+
changeCount: number;
|
|
40
|
+
/** How many levels the series has stood at. */
|
|
41
|
+
levelCount: number;
|
|
42
|
+
firstObservation: BankRateObservation;
|
|
43
|
+
latestObservation: BankRateObservation;
|
|
44
|
+
/** Highest level the series reached, and when it lasted. */
|
|
45
|
+
highestSpell: BankRateSpell;
|
|
46
|
+
/** Lowest level the series reached, and when it lasted. */
|
|
47
|
+
lowestSpell: BankRateSpell;
|
|
48
|
+
/** The longest run at one level. */
|
|
49
|
+
longestSpell: BankRateSpell;
|
|
50
|
+
/** Every run at one level, oldest first. */
|
|
51
|
+
spells: BankRateSpell[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Formats a day the way an IADB query string wants it, e.g. "28/Sep/2026".
|
|
55
|
+
*
|
|
56
|
+
* @param day - the day to format
|
|
57
|
+
* @returns the day as DD/Mon/YYYY, read in UTC
|
|
58
|
+
*/
|
|
59
|
+
export declare function formatBankRateQueryDate(day: Date): string;
|
|
60
|
+
/**
|
|
61
|
+
* Builds the CSV URL for the Bank Rate series, from the series start to a day.
|
|
62
|
+
*
|
|
63
|
+
* @param toQueryDate - the last day to ask for, in the database's DD/Mon/YYYY format
|
|
64
|
+
* @returns the full CSV URL
|
|
65
|
+
*/
|
|
66
|
+
export declare function buildBankRateCsvUrl(toQueryDate: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* Parses an IADB CSV body into daily Bank Rate readings.
|
|
69
|
+
*
|
|
70
|
+
* The CSV carries one row per business day, oldest first, with the date in
|
|
71
|
+
* the first column and the rate in the second. Dates must run forwards: a
|
|
72
|
+
* body that repeats or reorders a day would quietly break the spell counts.
|
|
73
|
+
*
|
|
74
|
+
* @param csvText - the raw CSV body from the IADB endpoint
|
|
75
|
+
* @returns one observation per day the database returned
|
|
76
|
+
*/
|
|
77
|
+
export declare function parseBankRateCsv(csvText: string): BankRateObservation[];
|
|
78
|
+
/**
|
|
79
|
+
* Collapses the daily readings into the runs the rate held one level for.
|
|
80
|
+
*
|
|
81
|
+
* @param observations - daily readings, oldest first
|
|
82
|
+
* @returns one spell per unbroken level, oldest first
|
|
83
|
+
*/
|
|
84
|
+
export declare function buildBankRateSpells(observations: BankRateObservation[]): BankRateSpell[];
|
|
85
|
+
/**
|
|
86
|
+
* Totals the series and finds its highest, lowest, and longest spells.
|
|
87
|
+
*
|
|
88
|
+
* @param observations - daily readings, oldest first
|
|
89
|
+
* @returns counts, the first and last readings, and the spells
|
|
90
|
+
*/
|
|
91
|
+
export declare function summarizeBankRateSeries(observations: BankRateObservation[]): BankRateSummary;
|
|
92
|
+
/**
|
|
93
|
+
* Reads the Bank Rate series from the Bank of England's database.
|
|
94
|
+
*
|
|
95
|
+
* The database answers with the whole series up to the day asked for, so the
|
|
96
|
+
* call runs to today rather than to a fixed end date.
|
|
97
|
+
*
|
|
98
|
+
* @param options - an optional fetch implementation and an optional "today"
|
|
99
|
+
* @returns one observation per day the database returned
|
|
100
|
+
*/
|
|
101
|
+
export declare function fetchBankRateObservations(options?: {
|
|
102
|
+
fetchImpl?: typeof globalThis.fetch;
|
|
103
|
+
now?: Date;
|
|
104
|
+
}): Promise<BankRateObservation[]>;
|
|
105
|
+
/** Bank of England Bank Rate readings, keyless, one row per business day. */
|
|
106
|
+
export declare const bankRateAdapter: UkDataAdapter<BankRateObservation[]>;
|
|
107
|
+
//# sourceMappingURL=bankRate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bankRate.d.ts","sourceRoot":"","sources":["../src/bankRate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAE/C,6DAA6D;AAC7D,eAAO,MAAM,qBAAqB,YAAY,CAAC;AAE/C,+DAA+D;AAC/D,eAAO,MAAM,iBAAiB,+EACgD,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,gBAAgB,CAAC;AAExD,yDAAyD;AACzD,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,0CAA0C;AAC1C,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,2CAA2C;AAC3C,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,gBAAgB,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,mBAAmB,CAAC;IACtC,iBAAiB,EAAE,mBAAmB,CAAC;IACvC,4DAA4D;IAC5D,YAAY,EAAE,aAAa,CAAC;IAC5B,2DAA2D;IAC3D,WAAW,EAAE,aAAa,CAAC;IAC3B,oCAAoC;IACpC,YAAY,EAAE,aAAa,CAAC;IAC5B,4CAA4C;IAC5C,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAuCD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,IAAI,GAAG,MAAM,CAOzD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAW/D;AA2BD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAiCvE;AAeD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,mBAAmB,EAAE,GAAG,aAAa,EAAE,CAiBxF;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,mBAAmB,EAAE,GAAG,eAAe,CAyC5F;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAAC,GAAG,CAAC,EAAE,IAAI,CAAA;CAAO,GAChE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAQhC;AAED,6EAA6E;AAC7E,eAAO,MAAM,eAAe,EAAE,aAAa,CAAC,mBAAmB,EAAE,CAWhE,CAAC"}
|
package/dist/bankRate.js
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { UkSourceApiError, UkSourceParseError } from './errors.js';
|
|
2
|
+
import { readFixtureText } from './fixtures.js';
|
|
3
|
+
/**
|
|
4
|
+
* The Bank of England's official Bank Rate, published in the Bank's
|
|
5
|
+
* Interactive Statistical Database (IADB). Keyless: the database answers
|
|
6
|
+
* without a key, and the series is the one the Bank's own statistics pages
|
|
7
|
+
* read: <https://www.bankofengland.co.uk/statistics>.
|
|
8
|
+
*/
|
|
9
|
+
export const BANK_RATE_SOURCE_ID = 'bank-rate';
|
|
10
|
+
/** The IADB series code for the daily official Bank Rate. */
|
|
11
|
+
export const BANK_RATE_SERIES_CODE = 'IUDBEDR';
|
|
12
|
+
/** The IADB CSV endpoint, before the query string is added. */
|
|
13
|
+
export const BANK_RATE_CSV_URL = 'https://www.bankofengland.co.uk/boeapps/database/_iadb-fromshowcolumns.asp';
|
|
14
|
+
/**
|
|
15
|
+
* First date the database holds for the daily series, in the database's own
|
|
16
|
+
* query format. Asking for an earlier start returns the database's error
|
|
17
|
+
* page rather than a CSV, so the adapter never asks for one.
|
|
18
|
+
*/
|
|
19
|
+
export const BANK_RATE_FIRST_QUERY_DATE = '02/Jan/1975';
|
|
20
|
+
/** The two CSV columns the database writes: date then series code. */
|
|
21
|
+
const BANK_RATE_CSV_COLUMNS = 2;
|
|
22
|
+
const CSV_DATE_COLUMN = 0;
|
|
23
|
+
const CSV_RATE_COLUMN = 1;
|
|
24
|
+
/** Milliseconds in a day, for turning a date span into a day count. */
|
|
25
|
+
const MILLISECONDS_PER_DAY = 86_400_000;
|
|
26
|
+
/** The three-letter month names the database writes, January first. */
|
|
27
|
+
const BANK_RATE_MONTH_NAMES = [
|
|
28
|
+
'Jan',
|
|
29
|
+
'Feb',
|
|
30
|
+
'Mar',
|
|
31
|
+
'Apr',
|
|
32
|
+
'May',
|
|
33
|
+
'Jun',
|
|
34
|
+
'Jul',
|
|
35
|
+
'Aug',
|
|
36
|
+
'Sep',
|
|
37
|
+
'Oct',
|
|
38
|
+
'Nov',
|
|
39
|
+
'Dec',
|
|
40
|
+
];
|
|
41
|
+
/** Month numbers by the name the database writes, e.g. "Jan" to "01". */
|
|
42
|
+
const BANK_RATE_MONTHS = Object.fromEntries(BANK_RATE_MONTH_NAMES.map((name, index) => [name, String(index + 1).padStart(2, '0')]));
|
|
43
|
+
/** Splits a CSV body into rows, tolerating CRLF line endings and a blank tail. */
|
|
44
|
+
function splitCsvRows(csvText) {
|
|
45
|
+
return csvText
|
|
46
|
+
.split(/\r?\n/)
|
|
47
|
+
.map((row) => row.trim())
|
|
48
|
+
.filter((row) => row !== '');
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Formats a day the way an IADB query string wants it, e.g. "28/Sep/2026".
|
|
52
|
+
*
|
|
53
|
+
* @param day - the day to format
|
|
54
|
+
* @returns the day as DD/Mon/YYYY, read in UTC
|
|
55
|
+
*/
|
|
56
|
+
export function formatBankRateQueryDate(day) {
|
|
57
|
+
const month = BANK_RATE_MONTH_NAMES[day.getUTCMonth()];
|
|
58
|
+
const dayOfMonth = String(day.getUTCDate()).padStart(2, '0');
|
|
59
|
+
if (month === undefined) {
|
|
60
|
+
throw new UkSourceParseError(BANK_RATE_SOURCE_ID, 'the query date fell outside a year');
|
|
61
|
+
}
|
|
62
|
+
return `${dayOfMonth}/${month}/${String(day.getUTCFullYear())}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Builds the CSV URL for the Bank Rate series, from the series start to a day.
|
|
66
|
+
*
|
|
67
|
+
* @param toQueryDate - the last day to ask for, in the database's DD/Mon/YYYY format
|
|
68
|
+
* @returns the full CSV URL
|
|
69
|
+
*/
|
|
70
|
+
export function buildBankRateCsvUrl(toQueryDate) {
|
|
71
|
+
const url = new URL(BANK_RATE_CSV_URL);
|
|
72
|
+
url.searchParams.set('csv.x', 'yes');
|
|
73
|
+
url.searchParams.set('Datefrom', BANK_RATE_FIRST_QUERY_DATE);
|
|
74
|
+
url.searchParams.set('Dateto', toQueryDate);
|
|
75
|
+
url.searchParams.set('SeriesCodes', BANK_RATE_SERIES_CODE);
|
|
76
|
+
url.searchParams.set('CSVF', 'TN');
|
|
77
|
+
url.searchParams.set('UsingCodes', 'Y');
|
|
78
|
+
url.searchParams.set('VPD', 'Y');
|
|
79
|
+
url.searchParams.set('VFD', 'N');
|
|
80
|
+
return url.href;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Converts one database date, e.g. "02 Jan 1975", to an ISO date.
|
|
84
|
+
*
|
|
85
|
+
* @param value - the date as the database writes it
|
|
86
|
+
* @returns the same day as YYYY-MM-DD
|
|
87
|
+
*/
|
|
88
|
+
function parseObservationDate(value) {
|
|
89
|
+
const parts = value.split(' ');
|
|
90
|
+
const [dayPart, monthPart, yearPart] = parts;
|
|
91
|
+
const month = monthPart === undefined ? undefined : BANK_RATE_MONTHS[monthPart];
|
|
92
|
+
if (parts.length !== 3 ||
|
|
93
|
+
dayPart === undefined ||
|
|
94
|
+
month === undefined ||
|
|
95
|
+
yearPart === undefined) {
|
|
96
|
+
throw new UkSourceParseError(BANK_RATE_SOURCE_ID, `"${value}" is not a database date`);
|
|
97
|
+
}
|
|
98
|
+
const day = dayPart.padStart(2, '0');
|
|
99
|
+
if (!/^\d{2}$/.test(day) || !/^\d{4}$/.test(yearPart)) {
|
|
100
|
+
throw new UkSourceParseError(BANK_RATE_SOURCE_ID, `"${value}" is not a database date`);
|
|
101
|
+
}
|
|
102
|
+
return `${yearPart}-${month}-${day}`;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Parses an IADB CSV body into daily Bank Rate readings.
|
|
106
|
+
*
|
|
107
|
+
* The CSV carries one row per business day, oldest first, with the date in
|
|
108
|
+
* the first column and the rate in the second. Dates must run forwards: a
|
|
109
|
+
* body that repeats or reorders a day would quietly break the spell counts.
|
|
110
|
+
*
|
|
111
|
+
* @param csvText - the raw CSV body from the IADB endpoint
|
|
112
|
+
* @returns one observation per day the database returned
|
|
113
|
+
*/
|
|
114
|
+
export function parseBankRateCsv(csvText) {
|
|
115
|
+
const rows = splitCsvRows(csvText);
|
|
116
|
+
const header = rows[0]?.split(',') ?? [];
|
|
117
|
+
if (header[CSV_RATE_COLUMN] !== BANK_RATE_SERIES_CODE) {
|
|
118
|
+
throw new UkSourceParseError(BANK_RATE_SOURCE_ID, `the CSV header does not name the ${BANK_RATE_SERIES_CODE} series`);
|
|
119
|
+
}
|
|
120
|
+
const observations = [];
|
|
121
|
+
for (const row of rows.slice(1)) {
|
|
122
|
+
const columns = row.split(',');
|
|
123
|
+
if (columns.length !== BANK_RATE_CSV_COLUMNS) {
|
|
124
|
+
throw new UkSourceParseError(BANK_RATE_SOURCE_ID, `"${row}" is not a date and a rate`);
|
|
125
|
+
}
|
|
126
|
+
const date = parseObservationDate(columns[CSV_DATE_COLUMN] ?? '');
|
|
127
|
+
const rawRate = (columns[CSV_RATE_COLUMN] ?? '').trim();
|
|
128
|
+
const rate = Number(rawRate);
|
|
129
|
+
if (rawRate === '' || !Number.isFinite(rate)) {
|
|
130
|
+
throw new UkSourceParseError(BANK_RATE_SOURCE_ID, `"${row}" carries no rate`);
|
|
131
|
+
}
|
|
132
|
+
const previous = observations.at(-1);
|
|
133
|
+
if (previous !== undefined && previous.date >= date) {
|
|
134
|
+
throw new UkSourceParseError(BANK_RATE_SOURCE_ID, `${date} does not follow ${previous.date}`);
|
|
135
|
+
}
|
|
136
|
+
observations.push({ date, ratePercent: rate });
|
|
137
|
+
}
|
|
138
|
+
if (observations.length === 0) {
|
|
139
|
+
throw new UkSourceParseError(BANK_RATE_SOURCE_ID, 'the CSV carried no readings');
|
|
140
|
+
}
|
|
141
|
+
return observations;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Days between two ISO dates, counting both ends.
|
|
145
|
+
*
|
|
146
|
+
* @param startDate - the first day of the run
|
|
147
|
+
* @param endDate - the last day of the run
|
|
148
|
+
* @returns how many calendar days the run covers
|
|
149
|
+
*/
|
|
150
|
+
function countDaysBetween(startDate, endDate) {
|
|
151
|
+
const start = Date.parse(`${startDate}T00:00:00Z`);
|
|
152
|
+
const end = Date.parse(`${endDate}T00:00:00Z`);
|
|
153
|
+
return Math.round((end - start) / MILLISECONDS_PER_DAY) + 1;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Collapses the daily readings into the runs the rate held one level for.
|
|
157
|
+
*
|
|
158
|
+
* @param observations - daily readings, oldest first
|
|
159
|
+
* @returns one spell per unbroken level, oldest first
|
|
160
|
+
*/
|
|
161
|
+
export function buildBankRateSpells(observations) {
|
|
162
|
+
const spells = [];
|
|
163
|
+
for (const observation of observations) {
|
|
164
|
+
const open = spells.at(-1);
|
|
165
|
+
if (open?.ratePercent === observation.ratePercent) {
|
|
166
|
+
open.endDate = observation.date;
|
|
167
|
+
open.dayCount = countDaysBetween(open.startDate, observation.date);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
spells.push({
|
|
171
|
+
startDate: observation.date,
|
|
172
|
+
endDate: observation.date,
|
|
173
|
+
ratePercent: observation.ratePercent,
|
|
174
|
+
dayCount: 1,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
return spells;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Totals the series and finds its highest, lowest, and longest spells.
|
|
181
|
+
*
|
|
182
|
+
* @param observations - daily readings, oldest first
|
|
183
|
+
* @returns counts, the first and last readings, and the spells
|
|
184
|
+
*/
|
|
185
|
+
export function summarizeBankRateSeries(observations) {
|
|
186
|
+
const spells = buildBankRateSpells(observations);
|
|
187
|
+
const firstObservation = observations[0];
|
|
188
|
+
const latestObservation = observations.at(-1);
|
|
189
|
+
const firstSpell = spells[0];
|
|
190
|
+
const lastSpell = spells.at(-1);
|
|
191
|
+
if (firstObservation === undefined ||
|
|
192
|
+
latestObservation === undefined ||
|
|
193
|
+
firstSpell === undefined ||
|
|
194
|
+
lastSpell === undefined) {
|
|
195
|
+
throw new UkSourceParseError(BANK_RATE_SOURCE_ID, 'the series carried no readings');
|
|
196
|
+
}
|
|
197
|
+
let highestSpell = firstSpell;
|
|
198
|
+
let lowestSpell = firstSpell;
|
|
199
|
+
let longestSpell = firstSpell;
|
|
200
|
+
for (const spell of spells) {
|
|
201
|
+
if (spell.ratePercent > highestSpell.ratePercent) {
|
|
202
|
+
highestSpell = spell;
|
|
203
|
+
}
|
|
204
|
+
if (spell.ratePercent < lowestSpell.ratePercent) {
|
|
205
|
+
lowestSpell = spell;
|
|
206
|
+
}
|
|
207
|
+
if (spell.dayCount > longestSpell.dayCount) {
|
|
208
|
+
longestSpell = spell;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
observationCount: observations.length,
|
|
213
|
+
changeCount: spells.length - 1,
|
|
214
|
+
levelCount: new Set(spells.map((spell) => spell.ratePercent)).size,
|
|
215
|
+
firstObservation,
|
|
216
|
+
latestObservation,
|
|
217
|
+
highestSpell,
|
|
218
|
+
lowestSpell,
|
|
219
|
+
longestSpell,
|
|
220
|
+
spells,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Reads the Bank Rate series from the Bank of England's database.
|
|
225
|
+
*
|
|
226
|
+
* The database answers with the whole series up to the day asked for, so the
|
|
227
|
+
* call runs to today rather than to a fixed end date.
|
|
228
|
+
*
|
|
229
|
+
* @param options - an optional fetch implementation and an optional "today"
|
|
230
|
+
* @returns one observation per day the database returned
|
|
231
|
+
*/
|
|
232
|
+
export async function fetchBankRateObservations(options = {}) {
|
|
233
|
+
const { fetchImpl = globalThis.fetch, now = new Date() } = options;
|
|
234
|
+
const url = buildBankRateCsvUrl(formatBankRateQueryDate(now));
|
|
235
|
+
const response = await fetchImpl(url);
|
|
236
|
+
if (!response.ok) {
|
|
237
|
+
throw new UkSourceApiError(BANK_RATE_SOURCE_ID, `HTTP ${response.status} reading Bank Rate`);
|
|
238
|
+
}
|
|
239
|
+
return parseBankRateCsv(await response.text());
|
|
240
|
+
}
|
|
241
|
+
/** Bank of England Bank Rate readings, keyless, one row per business day. */
|
|
242
|
+
export const bankRateAdapter = {
|
|
243
|
+
id: BANK_RATE_SOURCE_ID,
|
|
244
|
+
name: 'Bank of England Bank Rate',
|
|
245
|
+
auth: 'none',
|
|
246
|
+
description: 'The daily official Bank Rate, from 2 January 1975 to the latest published day.',
|
|
247
|
+
fetchLive: (options) => fetchBankRateObservations(options?.fetchImpl === undefined ? {} : { fetchImpl: options.fetchImpl }),
|
|
248
|
+
parse: parseBankRateCsv,
|
|
249
|
+
loadFixture: () => parseBankRateCsv(readFixtureText('bank-rate.csv')),
|
|
250
|
+
};
|
|
251
|
+
//# sourceMappingURL=bankRate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bankRate.js","sourceRoot":"","sources":["../src/bankRate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import type { UkDataAdapter } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Half-hourly carbon intensity for Great Britain's electricity grid, from the
|
|
4
|
+
* National Energy System Operator's Carbon Intensity API. Every call answers
|
|
5
|
+
* without a key, and the API's own terms place the data under the Creative
|
|
6
|
+
* Commons Attribution 4.0 licence: <https://carbonintensity.org.uk/>
|
|
7
|
+
*/
|
|
8
|
+
export declare const CARBON_INTENSITY_SOURCE_ID = "carbon-intensity";
|
|
9
|
+
/** Root every call here is built from. */
|
|
10
|
+
export declare const CARBON_INTENSITY_API_BASE_URL = "https://api.carbonintensity.org.uk";
|
|
11
|
+
/** Half-hourly readings between two instants. */
|
|
12
|
+
export declare const CARBON_INTENSITY_RANGE_URL = "https://api.carbonintensity.org.uk/intensity";
|
|
13
|
+
/**
|
|
14
|
+
* The API refuses a range longer than 31 days ("The date range you have
|
|
15
|
+
* specified is greater than 31 days"). The window stays a day inside that.
|
|
16
|
+
*/
|
|
17
|
+
export declare const CARBON_INTENSITY_MAX_WINDOW_DAYS = 30;
|
|
18
|
+
/** How many complete days the default window covers. */
|
|
19
|
+
export declare const DEFAULT_CARBON_INTENSITY_WINDOW_DAYS = 30;
|
|
20
|
+
/** How long one reading covers. */
|
|
21
|
+
export declare const CARBON_INTENSITY_PERIOD_MINUTES = 30;
|
|
22
|
+
/**
|
|
23
|
+
* The grades the API puts each half hour in, lowest intensity first. They are
|
|
24
|
+
* the operator's own words: "The index is a measure of the Carbon Intensity
|
|
25
|
+
* represented on a scale between 'very low', 'low', 'moderate', 'high', 'very
|
|
26
|
+
* high'."
|
|
27
|
+
*/
|
|
28
|
+
export declare const CARBON_INTENSITY_INDEX_BANDS: readonly ["very low", "low", "moderate", "high", "very high"];
|
|
29
|
+
/** One of the grades the API labels a half hour with. */
|
|
30
|
+
export type CarbonIntensityIndex = (typeof CARBON_INTENSITY_INDEX_BANDS)[number];
|
|
31
|
+
/** One half hour of the series, with the reading the API holds for it. */
|
|
32
|
+
export interface CarbonIntensityPeriod {
|
|
33
|
+
/** Start of the half hour, as an ISO instant in UTC. */
|
|
34
|
+
from: string;
|
|
35
|
+
/** End of the half hour, as an ISO instant in UTC. */
|
|
36
|
+
to: string;
|
|
37
|
+
/** The estimated actual intensity over the half hour, in gCO2/kWh. */
|
|
38
|
+
intensity: number;
|
|
39
|
+
/** The grade the API puts that reading in. */
|
|
40
|
+
index: CarbonIntensityIndex;
|
|
41
|
+
}
|
|
42
|
+
/** How many half hours the window holds at one grade. */
|
|
43
|
+
export interface CarbonIntensityBandCount {
|
|
44
|
+
index: CarbonIntensityIndex;
|
|
45
|
+
periodCount: number;
|
|
46
|
+
}
|
|
47
|
+
/** A window of half-hourly readings, rolled up into the numbers a page prints. */
|
|
48
|
+
export interface CarbonIntensityWindow {
|
|
49
|
+
/** Half hours the window holds. */
|
|
50
|
+
periodCount: number;
|
|
51
|
+
/** Complete days the window covers. */
|
|
52
|
+
dayCount: number;
|
|
53
|
+
/** Start of the oldest half hour in the window. */
|
|
54
|
+
firstPeriodFrom: string;
|
|
55
|
+
/** End of the newest half hour in the window. */
|
|
56
|
+
lastPeriodTo: string;
|
|
57
|
+
/** Mean intensity across the window, rounded to a whole number. */
|
|
58
|
+
averageIntensity: number;
|
|
59
|
+
/** The cleanest half hour in the window. */
|
|
60
|
+
lowestPeriod: CarbonIntensityPeriod;
|
|
61
|
+
/** The dirtiest half hour in the window. */
|
|
62
|
+
highestPeriod: CarbonIntensityPeriod;
|
|
63
|
+
/** Half hours per grade, lowest grade first. */
|
|
64
|
+
bandCounts: CarbonIntensityBandCount[];
|
|
65
|
+
/** Every reading, oldest first. */
|
|
66
|
+
periods: CarbonIntensityPeriod[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Writes a Date as the ISO instant the API takes in its path, e.g.
|
|
70
|
+
* `2026-08-30T00:00Z`.
|
|
71
|
+
*
|
|
72
|
+
* @param date - the instant to write
|
|
73
|
+
* @returns the instant as `YYYY-MM-DDThh:mmZ`
|
|
74
|
+
*/
|
|
75
|
+
export declare function formatCarbonIntensityInstant(date: Date): string;
|
|
76
|
+
/**
|
|
77
|
+
* Works out the window a build reads: whole UTC days, ending at the start of
|
|
78
|
+
* today, so every reading in it is settled rather than a forecast.
|
|
79
|
+
*
|
|
80
|
+
* @param options - how many days, and the clock to measure back from
|
|
81
|
+
* @returns the window's start and end as ISO instants
|
|
82
|
+
*/
|
|
83
|
+
export declare function resolveCarbonIntensityWindow(options?: {
|
|
84
|
+
windowDays?: number;
|
|
85
|
+
now?: Date;
|
|
86
|
+
}): {
|
|
87
|
+
from: string;
|
|
88
|
+
to: string;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Checks a window a caller passed in rather than one the adapter worked out.
|
|
92
|
+
*
|
|
93
|
+
* The API refuses a range longer than 31 days and answers in half hours, so a
|
|
94
|
+
* window that is not a whole number of half hours, or that runs past the
|
|
95
|
+
* limit, throws here rather than at the API.
|
|
96
|
+
*
|
|
97
|
+
* @param window - the start and end a caller asked for
|
|
98
|
+
* @returns the same window, once it has been checked
|
|
99
|
+
*/
|
|
100
|
+
export declare function validateCarbonIntensityWindow(window: {
|
|
101
|
+
from?: string | undefined;
|
|
102
|
+
to?: string | undefined;
|
|
103
|
+
}): {
|
|
104
|
+
from: string;
|
|
105
|
+
to: string;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Builds the URL for one window of half-hourly readings.
|
|
109
|
+
*
|
|
110
|
+
* @param window - the start and end of the window, as ISO instants
|
|
111
|
+
* @returns the full range URL
|
|
112
|
+
*/
|
|
113
|
+
export declare function buildCarbonIntensityWindowUrl(window: {
|
|
114
|
+
from: string;
|
|
115
|
+
to: string;
|
|
116
|
+
}): string;
|
|
117
|
+
/**
|
|
118
|
+
* Parses a range response into the readings the page draws.
|
|
119
|
+
*
|
|
120
|
+
* Every check here is one the page would otherwise show as a wrong number: a
|
|
121
|
+
* half hour with no settled reading, a period that does not run for half an
|
|
122
|
+
* hour, an instant that does not move forwards, or a grade the API's own band
|
|
123
|
+
* list does not carry all throw rather than quietly changing the counts.
|
|
124
|
+
*
|
|
125
|
+
* @param payload - the range response, or the committed fixture of one
|
|
126
|
+
* @returns every reading in the window, oldest first, with its totals
|
|
127
|
+
*/
|
|
128
|
+
export declare function parseCarbonIntensityWindow(payload: unknown): CarbonIntensityWindow;
|
|
129
|
+
/**
|
|
130
|
+
* Reads a window of half-hourly carbon intensity.
|
|
131
|
+
*
|
|
132
|
+
* The range endpoint also returns the half hour that ends at the window's
|
|
133
|
+
* start, so the first response is dropped: without that, the window is a half
|
|
134
|
+
* hour longer than the whole days it claims to cover.
|
|
135
|
+
*
|
|
136
|
+
* A caller can also pass the window's own start and end, which is how a page
|
|
137
|
+
* aligns the window to whole days in its own time zone rather than to UTC.
|
|
138
|
+
*
|
|
139
|
+
* @param options - how many days, or an explicit window, and an optional fetch implementation
|
|
140
|
+
* @returns every reading in the window, oldest first, with its totals
|
|
141
|
+
*/
|
|
142
|
+
export declare function fetchCarbonIntensityWindow(options?: {
|
|
143
|
+
windowDays?: number;
|
|
144
|
+
now?: Date;
|
|
145
|
+
from?: string | undefined;
|
|
146
|
+
to?: string | undefined;
|
|
147
|
+
fetchImpl?: typeof globalThis.fetch;
|
|
148
|
+
}): Promise<CarbonIntensityWindow>;
|
|
149
|
+
/** National Energy System Operator half-hourly carbon intensity, keyless. */
|
|
150
|
+
export declare const carbonIntensityAdapter: UkDataAdapter<CarbonIntensityWindow>;
|
|
151
|
+
//# sourceMappingURL=carbonIntensity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"carbonIntensity.d.ts","sourceRoot":"","sources":["../src/carbonIntensity.ts"],"names":[],"mappings":"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"}
|