emissions-api-sdk 1.0.8 → 1.0.10

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.
Files changed (49) hide show
  1. package/dist/Client.js +69 -9
  2. package/dist/Constants.js +2 -1
  3. package/dist/coverage/clover.xml +72 -57
  4. package/dist/coverage/coverage-final.json +4 -4
  5. package/dist/coverage/lcov-report/index.html +18 -18
  6. package/dist/coverage/lcov-report/src/Client.ts.html +242 -50
  7. package/dist/coverage/lcov-report/src/Constants.ts.html +7 -4
  8. package/dist/coverage/lcov-report/src/api/Calculation.ts.html +1 -1
  9. package/dist/coverage/lcov-report/src/api/EconomicActivity.ts.html +1 -1
  10. package/dist/coverage/lcov-report/src/api/Factor.ts.html +1 -1
  11. package/dist/coverage/lcov-report/src/api/FactorSets.ts.html +1 -1
  12. package/dist/coverage/lcov-report/src/api/Fugitive.ts.html +1 -1
  13. package/dist/coverage/lcov-report/src/api/Location.ts.html +1 -1
  14. package/dist/coverage/lcov-report/src/api/Metadata.ts.html +1 -1
  15. package/dist/coverage/lcov-report/src/api/Mobile.ts.html +1 -1
  16. package/dist/coverage/lcov-report/src/api/RealEstate.ts.html +1 -1
  17. package/dist/coverage/lcov-report/src/api/Stationary.ts.html +1 -1
  18. package/dist/coverage/lcov-report/src/api/TransportationAndDistribution.ts.html +1 -1
  19. package/dist/coverage/lcov-report/src/api/TypeRecommender.ts.html +1 -1
  20. package/dist/coverage/lcov-report/src/api/Usage.ts.html +1 -1
  21. package/dist/coverage/lcov-report/src/api/index.html +1 -1
  22. package/dist/coverage/lcov-report/src/index.html +21 -21
  23. package/dist/coverage/lcov-report/src/request.ts.html +1 -1
  24. package/dist/coverage/lcov-report/src/utils.ts.html +5 -5
  25. package/dist/coverage/lcov-report/test/index.html +1 -1
  26. package/dist/coverage/lcov-report/test/mocks/CommonRequest.ts.html +1 -1
  27. package/dist/coverage/lcov-report/test/mocks/FactorRequest.ts.html +1 -1
  28. package/dist/coverage/lcov-report/test/mocks/GenericCalculationRequest.ts.html +1 -1
  29. package/dist/coverage/lcov-report/test/mocks/LocationRequest.ts.html +1 -1
  30. package/dist/coverage/lcov-report/test/mocks/SearchRequest.ts.html +1 -1
  31. package/dist/coverage/lcov-report/test/mocks/index.html +1 -1
  32. package/dist/coverage/lcov-report/test/testUtils.ts.html +4 -4
  33. package/dist/coverage/lcov.info +161 -121
  34. package/dist/types/Client.d.ts +26 -0
  35. package/dist/types/Constants.d.ts +1 -0
  36. package/dist/types/index.d.ts +1 -1
  37. package/dist/types/interfaces/Config.d.ts +6 -0
  38. package/dist/types/interfaces/response/EmissionResponseWithDetails.d.ts +62 -124
  39. package/docs/reference.html +8 -2
  40. package/docs/searchindex.js +1 -1
  41. package/package.json +3 -2
  42. package/src/Client.ts +79 -15
  43. package/src/Constants.ts +1 -0
  44. package/src/index.ts +3 -12
  45. package/src/interfaces/Config.ts +7 -0
  46. package/src/interfaces/response/EmissionResponseWithDetails.ts +79 -146
  47. package/test/client.test.ts +93 -1
  48. package/test/tokenRefresh.test.ts +91 -1
  49. package/.secrets.baseline +0 -314
@@ -1,51 +1,11 @@
1
1
  import { EmissionResponse } from './EmissionResponse';
2
2
 
3
3
  /**
4
- * Interface for unit information in emission details
4
+ * Interface for factor set details
5
5
  */
6
- export interface UnitInfo {
7
- /** Unit name */
8
- name: string;
9
-
10
- /** Unit description (optional) */
11
- description?: string;
12
- }
13
-
14
- /**
15
- * Interface for area information
16
- */
17
- export interface AreaInfo {
18
- /** Internal name of the area */
19
- internalName: string;
20
-
21
- /** Standard name of the area */
22
- standardName: string;
23
-
24
- alpha3?: string;
25
- }
26
-
27
- /**
28
- * Interface for area type information
29
- */
30
- export interface AreaType {
31
- /** Type name (e.g., "Planet", "State") */
32
- name: string;
33
- }
34
-
35
- /**
36
- * Interface for factor data type categories
37
- */
38
- export interface FactorDataTypeCategory {
39
- /** Category name */
40
- name: string;
41
- }
42
-
43
- /**
44
- * Interface for factor set information
45
- */
46
- export interface FactorSetInfo {
47
- /** Factor set type */
48
- type: string;
6
+ export interface FactorSetDetails {
7
+ /** Name of the factor set */
8
+ name?: string;
49
9
 
50
10
  /** Description of the factor set */
51
11
  description?: string;
@@ -55,135 +15,108 @@ export interface FactorSetInfo {
55
15
 
56
16
  /** Source URL for the factor set */
57
17
  sourceUrl?: string;
58
-
59
- factorSource?: string;
60
- }
61
- export interface FactorSelectionDefault {
62
- actorDataType?: string;
63
- areaName?: string;
64
- factorSetName?: string;
18
+
19
+ /** Citation information for the factor set */
20
+ citation?: string;
65
21
  }
22
+
66
23
  /**
67
- * Interface for factor data type code
24
+ * Interface for factor details
68
25
  */
69
- export interface FactorDataTypeCode {
70
- /** Unit of measure */
71
- unitOfMeasure: string;
26
+ export interface FactorDetails {
27
+ /** Name of the factor */
28
+ name?: string;
72
29
 
73
- /** Activity type */
74
- type: string;
30
+ /** Description of the factor */
31
+ description?: string;
75
32
 
76
- /** Activity subtype */
77
- subtype: string;
33
+ /** Total CO2 equivalent emissions */
34
+ totalCO2e?: number;
78
35
 
79
- /** Unique factor identifier */
80
- factorId: number;
36
+ /** CO2 emissions value */
37
+ CO2?: number;
81
38
 
82
- /** activity based or spend based */
83
- methodology: string;
84
-
85
- /** scopes data belongs to */
86
- scope : string[];
87
- }
88
-
89
- /**
90
- * Interface for factor set version information
91
- */
92
- export interface FactorSetVersion {
93
- /** Publication start date */
94
- publishedFrom?: string;
39
+ /** CH4 (Methane) emissions value */
40
+ CH4?: number;
95
41
 
96
- /** Publication end date (optional) */
97
- publishedTo?: string;
42
+ /** N2O (Nitrous Oxide) emissions value */
43
+ N2O?: number;
98
44
 
99
- /** Source of the factor */
100
- factorSource: string;
101
- }
102
-
103
- /**
104
- * Interface for factor value
105
- */
106
- export interface FactorValue {
107
- /** Unit information */
108
- unit: {
109
- /** Unit name */
110
- name: string;
111
- };
112
-
113
- /** Factor value */
114
- value: number;
115
- }
116
-
117
- /**
118
- * Interface for factor metadata
119
- */
120
- export interface FactorMetaData {
121
- /** Metadata key */
122
- key: string;
45
+ /** Biogenic CO2 emissions value */
46
+ bioCO2?: number;
123
47
 
124
- /** Metadata value */
125
- value: string;
126
- }
127
-
128
- /**
129
- * Interface for unit conversion information
130
- */
131
- export interface UnitConversion {
132
- /** Input unit */
133
- inputUnit: string;
48
+ /** Indirect CO2 equivalent emissions value */
49
+ indirectCO2e?: number;
50
+
51
+ /** Hydrofluorocarbon emissions value */
52
+ HFC?: number;
53
+
54
+ /** Perfluorocarbon emissions value */
55
+ PFC?: number;
56
+
57
+ /** Sulfur hexafluoride emissions value */
58
+ SF6?: number;
59
+
60
+ /** Nitrogen trifluoride emissions value */
61
+ NF3?: number;
134
62
 
135
- /** Unit from database */
136
- unitFromDb: string;
63
+ /** Energy consumption in megawatt-hours */
64
+ 'energy(MWh)'?: number;
65
+
66
+ /** Input unit of measurement */
67
+ inputUnit?: string;
68
+
69
+ /** Unit of measurement for emissions */
70
+ unit?: string;
137
71
 
138
72
  /** Conversion ratio */
139
- conversionRatio: string;
140
- }
141
-
142
- /**
143
- * Interface for detailed emission data
144
- */
145
- export interface EmissionData {
146
- /** Array of unit information */
147
- unit: UnitInfo[];
73
+ conversionRatio?: string;
148
74
 
149
- /** Array of area information */
150
- area: AreaInfo[];
75
+ /** Type of activity */
76
+ activityType?: string;
151
77
 
152
- /** Array of area types */
153
- areaType: AreaType[];
78
+ /** Activity subtype */
79
+ activitySubtype?: string;
154
80
 
155
- /** Array of factor data type categories */
156
- factorDataTypeCategories: FactorDataTypeCategory[];
157
-
158
- factorSelectionDefault? :FactorSelectionDefault[];
81
+ /** Unique factor identifier */
82
+ factorId?: number;
159
83
 
160
- /** Array of factor set information */
161
- factorSet: FactorSetInfo[];
84
+ /** Methodology (activity based or spend based) */
85
+ methodology?: string;
162
86
 
163
- /** Array of factor data type codes */
164
- factorDataTypeCode: FactorDataTypeCode[];
87
+ /** Scopes data belongs to */
88
+ scopes?: string[];
165
89
 
166
- /** Array of factor set versions */
167
- factorSetVersion: FactorSetVersion[];
90
+ /** Area name */
91
+ areaName?: string;
168
92
 
169
- /** Array of factor values */
170
- factorValue: FactorValue[];
93
+ /** Area type */
94
+ areaType?: string;
171
95
 
172
- /** Array of factor metadata */
173
- factorMetaData: FactorMetaData[];
96
+ /** Publication start date */
97
+ publishedFrom?: string;
98
+
99
+ /** Publication end date */
100
+ publishedTo?: string;
174
101
 
175
- /** Array of unit conversions */
176
- unitConversion: UnitConversion[];
102
+ /** Source of the factor */
103
+ source?: string;
177
104
  }
178
105
 
179
106
  /**
180
- * Interface representing the emission calculation response with detailed information
107
+ * Interface for include details
181
108
  */
182
- export interface EmissionResponseWithDetails {
183
- /** Emission calculation result */
184
- result: EmissionResponse;
109
+ export interface IncludeDetails {
110
+ /** Factor set details */
111
+ factorSet?: FactorSetDetails;
185
112
 
113
+ /** Factor details */
114
+ factor?: FactorDetails;
115
+ }
116
+
117
+
118
+ export interface EmissionResponseWithDetails extends EmissionResponse {
186
119
  /** Detailed emission data */
187
- data: EmissionData;
120
+ details?: IncludeDetails;
188
121
  }
189
122
 
@@ -1,7 +1,7 @@
1
1
  import { Client } from "../src/Client";
2
2
  import axios from "axios";
3
3
  import MockAdapter from "axios-mock-adapter";
4
- import { TOKEN_GENERATION_API } from "../src/Constants";
4
+ import { TOKEN_GENERATION_API, PAT_TOKEN_EXCHANGE_API } from "../src/Constants";
5
5
  import { ClientConfig } from "../src/interfaces/Config";
6
6
 
7
7
  const mock = new MockAdapter(axios);
@@ -57,6 +57,27 @@ describe("Client initialization and Header Authorization", () => {
57
57
  'If apiKey is provided , "clientId" and "OrgId" must also be provided.'
58
58
  );
59
59
  });
60
+
61
+ it("Should throw validation error for missing clientId with patToken", async () => {
62
+ await expect(
63
+ Client.getClient({ patToken: "pat-token" } as unknown as ClientConfig)
64
+ ).rejects.toThrow(
65
+ 'If patToken is provided, "clientId" must also be provided.'
66
+ );
67
+ });
68
+
69
+ it("Should throw validation error when orgId is provided with patToken", async () => {
70
+ await expect(
71
+ Client.getClient({
72
+ patToken: "pat-token",
73
+ clientId: "client123",
74
+ orgId: "org456"
75
+ } as ClientConfig)
76
+ ).rejects.toThrow(
77
+ 'orgId should not be provided when using patToken.'
78
+ );
79
+ });
80
+
60
81
  it("should not call refresh token if userProvidedToken is set and set token to userProvided", async () => {
61
82
  const base64Header = Buffer.from(
62
83
  JSON.stringify({ alg: "HS256", typ: "JWT" })
@@ -79,4 +100,75 @@ describe("Client initialization and Header Authorization", () => {
79
100
  });
80
101
  expect(spy).not.toHaveBeenCalled();
81
102
  });
103
+
104
+ it("should initialize client with PAT token and return auth header", async () => {
105
+ const base64Header = Buffer.from(
106
+ JSON.stringify({ alg: "HS256", typ: "JWT" })
107
+ ).toString("base64url");
108
+ const base64Payload = Buffer.from(
109
+ JSON.stringify({ exp: Math.floor(Date.now() / 1000) + 600 })
110
+ ).toString("base64url");
111
+ const mockToken = `${base64Header}.${base64Payload}.Signature`;
112
+
113
+ mock.onPost(PAT_TOKEN_EXCHANGE_API).reply(200, mockToken);
114
+
115
+ await Client.getClient({
116
+ patToken: "test-pat-token",
117
+ clientId: "test-client-id",
118
+ });
119
+
120
+ const instance = Client.getInstance();
121
+ expect(instance.getAuthHeader()).toEqual({
122
+ Authorization: `Bearer ${mockToken}`,
123
+ });
124
+ });
125
+
126
+ it("should initialize client with PAT token and custom authUrl", async () => {
127
+ const base64Header = Buffer.from(
128
+ JSON.stringify({ alg: "HS256", typ: "JWT" })
129
+ ).toString("base64url");
130
+ const base64Payload = Buffer.from(
131
+ JSON.stringify({ exp: Math.floor(Date.now() / 1000) + 600 })
132
+ ).toString("base64url");
133
+ const mockToken = `${base64Header}.${base64Payload}.Signature`;
134
+
135
+ const customAuthUrl = "https://custom-auth.example.com/exchange";
136
+ mock.onPost(customAuthUrl).reply(200, mockToken);
137
+
138
+ await Client.getClient({
139
+ patToken: "test-pat-token",
140
+ clientId: "test-client-id",
141
+ authUrl: customAuthUrl,
142
+ });
143
+
144
+ const instance = Client.getInstance();
145
+ expect(instance.getAuthHeader()).toEqual({
146
+ Authorization: `Bearer ${mockToken}`,
147
+ });
148
+ });
149
+
150
+ it("should call requestTokenFromPAT with correct headers", async () => {
151
+ const base64Header = Buffer.from(
152
+ JSON.stringify({ alg: "HS256", typ: "JWT" })
153
+ ).toString("base64url");
154
+ const base64Payload = Buffer.from(
155
+ JSON.stringify({ exp: Math.floor(Date.now() / 1000) + 600 })
156
+ ).toString("base64url");
157
+ const mockToken = `${base64Header}.${base64Payload}.Signature`;
158
+
159
+ mock.onPost(PAT_TOKEN_EXCHANGE_API).reply((config) => {
160
+ expect(config.headers?.["X-IBM-Client-Id"]).toBe("saascore-test-client-id");
161
+ expect(config.headers?.["X-IBM-Envizi-Pat"]).toBe("test-pat-token");
162
+ expect(config.headers?.["Accept"]).toBe("application/json");
163
+ return [200, mockToken];
164
+ });
165
+
166
+ await Client.getClient({
167
+ patToken: "test-pat-token",
168
+ clientId: "test-client-id",
169
+ });
170
+
171
+ const instance = Client.getInstance();
172
+ expect(instance).toBeDefined();
173
+ });
82
174
  });
@@ -3,7 +3,7 @@ import * as utils from "../src/utils";
3
3
  import mockAxios from "axios";
4
4
  import MockAdapter from "axios-mock-adapter";
5
5
  import { generateMockjwt } from "./testUtils";
6
- import { TOKEN_GENERATION_API } from "../src/Constants";
6
+ import { TOKEN_GENERATION_API, PAT_TOKEN_EXCHANGE_API } from "../src/Constants";
7
7
 
8
8
  const mock = new MockAdapter(mockAxios);
9
9
  describe("Token refreshing", () => {
@@ -49,4 +49,94 @@ describe("Token refreshing", () => {
49
49
  await instance.refreshToken();
50
50
  expect(spy).not.toHaveBeenCalledTimes(1);
51
51
  });
52
+
53
+ it("should refresh PAT token when it is about to expire", async () => {
54
+ const shortLiveToken = generateMockjwt(1);
55
+ const refreshedToken = generateMockjwt(600);
56
+
57
+ mock
58
+ .onPost(PAT_TOKEN_EXCHANGE_API)
59
+ .replyOnce(200, shortLiveToken)
60
+ .onPost(PAT_TOKEN_EXCHANGE_API)
61
+ .replyOnce(200, refreshedToken);
62
+
63
+ jest
64
+ .spyOn(utils, "findExpiryTime")
65
+ .mockReturnValueOnce(Math.floor(Date.now() / 1000) + 1)
66
+ .mockReturnValueOnce(Math.floor(Date.now() / 1000) + 600);
67
+
68
+ await Client.getClient({
69
+ patToken: "test-pat-token",
70
+ clientId: "test-client-id",
71
+ });
72
+ const instance = Client.getInstance();
73
+
74
+ const spy = jest.spyOn(Client as any, "requestTokenFromPAT");
75
+
76
+ await instance.refreshToken();
77
+ expect(spy).toHaveBeenCalledTimes(1);
78
+ expect(spy).toHaveBeenCalledWith({
79
+ patToken: "test-pat-token",
80
+ clientId: "test-client-id",
81
+ authUrl: PAT_TOKEN_EXCHANGE_API,
82
+ });
83
+ });
84
+
85
+ it("should not refresh PAT token if it is still valid", async () => {
86
+ const freshToken = generateMockjwt(600);
87
+ mock.onPost(PAT_TOKEN_EXCHANGE_API).reply(200, freshToken);
88
+
89
+ const spy = jest.spyOn(Client as any, "requestTokenFromPAT");
90
+
91
+ jest
92
+ .spyOn(utils, "findExpiryTime")
93
+ .mockReturnValue(Math.floor(Date.now() / 1000) + 600);
94
+
95
+ await Client.getClient({
96
+ patToken: "test-pat-token",
97
+ clientId: "test-client-id",
98
+ });
99
+ const instance = Client.getInstance();
100
+
101
+ spy.mockClear(); // Clear the initial call from getClient
102
+
103
+ await instance.refreshToken();
104
+ expect(spy).not.toHaveBeenCalled();
105
+ });
106
+
107
+ it("should refresh PAT token with custom authUrl", async () => {
108
+ const shortLiveToken = generateMockjwt(1);
109
+ const refreshedToken = generateMockjwt(600);
110
+ const customAuthUrl = "https://custom-auth.example.com/exchange";
111
+
112
+ mock
113
+ .onPost(customAuthUrl)
114
+ .replyOnce(200, shortLiveToken)
115
+ .onPost(customAuthUrl)
116
+ .replyOnce(200, refreshedToken);
117
+
118
+ const spy = jest.spyOn(Client as any, "requestTokenFromPAT");
119
+
120
+ jest
121
+ .spyOn(utils, "findExpiryTime")
122
+ .mockReturnValueOnce(Math.floor(Date.now() / 1000) + 1)
123
+ .mockReturnValueOnce(Math.floor(Date.now() / 1000) + 600);
124
+
125
+ await Client.getClient({
126
+ patToken: "test-pat-token",
127
+ clientId: "test-client-id",
128
+ authUrl: customAuthUrl,
129
+ });
130
+ const instance = Client.getInstance();
131
+
132
+ spy.mockClear(); // Clear the initial call from getClient
133
+
134
+ await instance.refreshToken();
135
+ expect(spy).toHaveBeenCalledTimes(1);
136
+ expect(spy).toHaveBeenCalledWith({
137
+ patToken: "test-pat-token",
138
+ clientId: "test-client-id",
139
+ authUrl: customAuthUrl,
140
+ });
141
+ });
52
142
  });