@greensecurity/javascript-sdk 0.48.0-beta.10 → 0.48.0-beta.11

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 (62) hide show
  1. package/dist/commonjs/__tests__/subscriptionPlanSelection.test.d.ts +2 -0
  2. package/dist/commonjs/__tests__/subscriptionPlanSelection.test.d.ts.map +1 -0
  3. package/dist/commonjs/__tests__/subscriptionPlanSelection.test.js +36 -0
  4. package/dist/commonjs/__tests__/subscriptionPlanSelection.test.js.map +1 -0
  5. package/dist/commonjs/__tests__/vendors.test.js +1 -1
  6. package/dist/commonjs/__tests__/vendors.test.js.map +1 -1
  7. package/dist/commonjs/__tests__/zones.test.js +13 -10
  8. package/dist/commonjs/__tests__/zones.test.js.map +1 -1
  9. package/dist/commonjs/admin-funcs/doAdmin.d.ts +5 -4
  10. package/dist/commonjs/admin-funcs/doAdmin.d.ts.map +1 -1
  11. package/dist/commonjs/admin-funcs/doAdmin.js +10 -5
  12. package/dist/commonjs/admin-funcs/doAdmin.js.map +1 -1
  13. package/dist/commonjs/admin-funcs/subscriptionFinishScreeningQuestions.d.ts +3 -2
  14. package/dist/commonjs/admin-funcs/subscriptionFinishScreeningQuestions.d.ts.map +1 -1
  15. package/dist/commonjs/admin-funcs/subscriptionFinishScreeningQuestions.js +2 -1
  16. package/dist/commonjs/admin-funcs/subscriptionFinishScreeningQuestions.js.map +1 -1
  17. package/dist/commonjs/admin-funcs/subscriptionPlanSelection.d.ts +7 -0
  18. package/dist/commonjs/admin-funcs/subscriptionPlanSelection.d.ts.map +1 -0
  19. package/dist/commonjs/admin-funcs/subscriptionPlanSelection.js +45 -0
  20. package/dist/commonjs/admin-funcs/subscriptionPlanSelection.js.map +1 -0
  21. package/dist/commonjs/admin-funcs/subscriptionUpdateVendorType.d.ts +3 -2
  22. package/dist/commonjs/admin-funcs/subscriptionUpdateVendorType.d.ts.map +1 -1
  23. package/dist/commonjs/admin-funcs/subscriptionUpdateVendorType.js +2 -1
  24. package/dist/commonjs/admin-funcs/subscriptionUpdateVendorType.js.map +1 -1
  25. package/dist/commonjs/lib/config.d.ts +2 -2
  26. package/dist/commonjs/lib/config.js +2 -2
  27. package/dist/esm/__tests__/subscriptionPlanSelection.test.d.ts +2 -0
  28. package/dist/esm/__tests__/subscriptionPlanSelection.test.d.ts.map +1 -0
  29. package/dist/esm/__tests__/subscriptionPlanSelection.test.js +34 -0
  30. package/dist/esm/__tests__/subscriptionPlanSelection.test.js.map +1 -0
  31. package/dist/esm/__tests__/vendors.test.js +1 -1
  32. package/dist/esm/__tests__/vendors.test.js.map +1 -1
  33. package/dist/esm/__tests__/zones.test.js +13 -10
  34. package/dist/esm/__tests__/zones.test.js.map +1 -1
  35. package/dist/esm/admin-funcs/doAdmin.d.ts +5 -4
  36. package/dist/esm/admin-funcs/doAdmin.d.ts.map +1 -1
  37. package/dist/esm/admin-funcs/doAdmin.js +10 -5
  38. package/dist/esm/admin-funcs/doAdmin.js.map +1 -1
  39. package/dist/esm/admin-funcs/subscriptionFinishScreeningQuestions.d.ts +3 -2
  40. package/dist/esm/admin-funcs/subscriptionFinishScreeningQuestions.d.ts.map +1 -1
  41. package/dist/esm/admin-funcs/subscriptionFinishScreeningQuestions.js +2 -1
  42. package/dist/esm/admin-funcs/subscriptionFinishScreeningQuestions.js.map +1 -1
  43. package/dist/esm/admin-funcs/subscriptionPlanSelection.d.ts +7 -0
  44. package/dist/esm/admin-funcs/subscriptionPlanSelection.d.ts.map +1 -0
  45. package/dist/esm/admin-funcs/subscriptionPlanSelection.js +9 -0
  46. package/dist/esm/admin-funcs/subscriptionPlanSelection.js.map +1 -0
  47. package/dist/esm/admin-funcs/subscriptionUpdateVendorType.d.ts +3 -2
  48. package/dist/esm/admin-funcs/subscriptionUpdateVendorType.d.ts.map +1 -1
  49. package/dist/esm/admin-funcs/subscriptionUpdateVendorType.js +2 -1
  50. package/dist/esm/admin-funcs/subscriptionUpdateVendorType.js.map +1 -1
  51. package/dist/esm/lib/config.d.ts +2 -2
  52. package/dist/esm/lib/config.js +2 -2
  53. package/jsr.json +1 -1
  54. package/package.json +1 -1
  55. package/src/__tests__/subscriptionPlanSelection.test.ts +53 -0
  56. package/src/__tests__/vendors.test.ts +1 -1
  57. package/src/__tests__/zones.test.ts +13 -10
  58. package/src/admin-funcs/doAdmin.ts +24 -11
  59. package/src/admin-funcs/subscriptionFinishScreeningQuestions.ts +11 -3
  60. package/src/admin-funcs/subscriptionPlanSelection.ts +17 -0
  61. package/src/admin-funcs/subscriptionUpdateVendorType.ts +11 -3
  62. package/src/lib/config.ts +2 -2
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+
3
+ const { doPostMock } = vi.hoisted(() => ({
4
+ doPostMock: vi.fn(() => Promise.resolve([{ ok: true }, { status: "complete" }])),
5
+ }));
6
+
7
+ vi.mock("../admin-funcs/doAdmin.js", () => ({
8
+ $doPost: doPostMock,
9
+ }));
10
+
11
+ import { subscriptionFinishScreeningQuestions } from "../admin-funcs/subscriptionFinishScreeningQuestions.js";
12
+ import { subscriptionPlanSelectionResponse$inboundSchema } from "../admin-funcs/subscriptionPlanSelection.js";
13
+ import { subscriptionUpdateVendorType } from "../admin-funcs/subscriptionUpdateVendorType.js";
14
+
15
+ // GSSD-7289: both steps answer whether the vendor has a plan to choose, and the SDK holds the
16
+ // server to it.
17
+ describe("subscription plan selection responses", () => {
18
+ it("validates finishing the screening questions against the plan selection schema", () => {
19
+ subscriptionFinishScreeningQuestions({ vendor_id: 7 });
20
+
21
+ expect(doPostMock).toHaveBeenCalledWith(
22
+ "/subscription/screening-questions",
23
+ { vendor_id: 7 },
24
+ undefined,
25
+ subscriptionPlanSelectionResponse$inboundSchema,
26
+ );
27
+ });
28
+
29
+ it("validates choosing a vendor type against the plan selection schema", () => {
30
+ subscriptionUpdateVendorType({ vendor_id: 7, vendor_type_id: [10] });
31
+
32
+ expect(doPostMock).toHaveBeenCalledWith(
33
+ "/subscription/vendor-type",
34
+ { vendor_id: 7, vendor_type_id: [10] },
35
+ undefined,
36
+ subscriptionPlanSelectionResponse$inboundSchema,
37
+ );
38
+ });
39
+
40
+ it("accepts a response that says whether a plan must be chosen, keeping other fields", () => {
41
+ const parsed = subscriptionPlanSelectionResponse$inboundSchema.parse({
42
+ success: true,
43
+ plan_selection_required: false,
44
+ extra: 1,
45
+ });
46
+
47
+ expect(parsed).toEqual({ success: true, plan_selection_required: false, extra: 1 });
48
+ });
49
+
50
+ it("rejects a response without plan_selection_required", () => {
51
+ expect(subscriptionPlanSelectionResponse$inboundSchema.safeParse({ success: true }).success).toBe(false);
52
+ });
53
+ });
@@ -121,7 +121,7 @@ test("Vendors List Vendor Credits", async () => {
121
121
  page: 1,
122
122
  useUrlParams: false,
123
123
  },
124
- creditBalance: 2457.03,
124
+ creditBalance: 8833.6,
125
125
  });
126
126
  });
127
127
 
@@ -35,37 +35,40 @@ test("Zones List Or Search Security Zones", async () => {
35
35
  useUrlParams: false,
36
36
  },
37
37
  items: [
38
- {
39
- facility: {},
40
- },
41
38
  {
42
39
  facility: {
43
40
  contacts: {
44
- contact: null,
41
+ contact: {
42
+ status: "Active",
43
+ department: 123,
44
+ },
45
45
  adminContact: {
46
- status: "Inactive",
46
+ status: "Active",
47
47
  department: 123,
48
48
  },
49
49
  techContact: {
50
- status: "Active",
50
+ status: "Inactive",
51
51
  department: 123,
52
52
  },
53
53
  greenSecurityCsm: {
54
- status: "Active",
54
+ status: "Deleted",
55
55
  department: 123,
56
56
  },
57
57
  accountManager: {
58
- status: "Deleted",
58
+ status: "Active",
59
59
  department: 123,
60
60
  },
61
61
  },
62
62
  vendorGuestPolicy: {
63
63
  enabled: false,
64
64
  vendorGuestLimitAndOr: "and",
65
- vendorGuestRequireEmail: false,
65
+ vendorGuestRequireEmail: true,
66
66
  },
67
67
  },
68
68
  },
69
+ {
70
+ facility: {},
71
+ },
69
72
  ],
70
73
  });
71
74
  });
@@ -83,7 +86,7 @@ test("Zones Security Zone Checkin", async () => {
83
86
 
84
87
  const result = await greenSecurity.zones.securityZoneCheckin({
85
88
  qrCode: "<value>",
86
- zoneId: 416448,
89
+ zoneId: 450895,
87
90
  });
88
91
  expect(result).toBeDefined();
89
92
  expect(result).toEqual({});
@@ -20,9 +20,11 @@ import { Result } from "../types/fp.js";
20
20
  import { getInternalCore } from "./initializeCore.js";
21
21
  import { encodeJSON } from "../lib/encodings.js";
22
22
 
23
- export type internalApiResult = APIPromise<
23
+ // An internal call whose response is validated against a schema for `T` (see $doPost's
24
+ // responseSchema). internalApiResult is the untyped default.
25
+ export type internalApiResultOf<T> = APIPromise<
24
26
  Result<
25
- Json,
27
+ T,
26
28
  | errors.ApiErrorResponse
27
29
  | GreenSecurityError
28
30
  | SDKValidationError
@@ -34,6 +36,8 @@ export type internalApiResult = APIPromise<
34
36
  >
35
37
  >;
36
38
 
39
+ export type internalApiResult = internalApiResultOf<Json>;
40
+
37
41
  // This creates a generic JSON schema that can be used to validate any JSON object
38
42
  const literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
39
43
  type Literal = z.infer<typeof literalSchema>;
@@ -201,10 +205,10 @@ export async function $doGetSingle<T extends object>(
201
205
  return [result, { status: "complete", request: req, response }];
202
206
  }
203
207
 
204
- type BodyResult = Promise<
208
+ type BodyResult<T = Json> = Promise<
205
209
  [
206
210
  Result<
207
- Json,
211
+ T,
208
212
  | errors.ApiErrorResponse
209
213
  | GreenSecurityError
210
214
  | ResponseValidationError
@@ -222,13 +226,18 @@ type BodyResult = Promise<
222
226
  // Shared by the JSON and multipart requests below: everything except the method, how the body
223
227
  // is built and whether we name a Content-Type. A multipart body must NOT carry one, because only
224
228
  // fetch can append the boundary it generates.
225
- async function $doBodyRequest(
229
+ async function $doBodyRequest<R = Json>(
226
230
  method: "POST" | "PUT",
227
231
  route: string,
228
232
  body: BodyInit | undefined,
229
233
  contentTypeHeader: Record<string, string>,
230
234
  options?: RequestOptions,
231
- ): BodyResult {
235
+ responseSchema?: z.ZodType<R>,
236
+ ): BodyResult<R> {
237
+ // Without a schema the body is only checked to be JSON, which is every caller before typed
238
+ // responses existed.
239
+ const schema = (responseSchema ?? jsonSchema) as z.ZodType<R>;
240
+
232
241
  const client = getInternalCore();
233
242
  if (!client) {
234
243
  throw new Error("GreenSecurityCore client is not initialized.");
@@ -290,7 +299,7 @@ async function $doBodyRequest(
290
299
  };
291
300
 
292
301
  const [result] = await M.match<
293
- Json,
302
+ R,
294
303
  | errors.ApiErrorResponse
295
304
  | GreenSecurityError
296
305
  | ResponseValidationError
@@ -301,10 +310,10 @@ async function $doBodyRequest(
301
310
  | RequestTimeoutError
302
311
  | ConnectionError
303
312
  >(
304
- M.json(200, jsonSchema),
313
+ M.json(200, schema),
305
314
  // A REST create answers 201, which matches none of the cases below — an unmatched status is
306
315
  // an error, so the caller saw a failure for a request the server had accepted.
307
- M.json(201, jsonSchema),
316
+ M.json(201, schema),
308
317
  // 422 is a real answer here, not a surprise: the create returns it for a refused certificate
309
318
  // and for a model validation failure. Left out, it fell through to M.fail("4XX"), which
310
319
  // yields a generic APIError and hides the server's message from the form.
@@ -319,17 +328,21 @@ async function $doBodyRequest(
319
328
  return [result, { status: "complete", request: req, response }];
320
329
  }
321
330
 
322
- export async function $doPost<T extends object>(
331
+ // Pass responseSchema to validate and type the 200/201 body; a body that does not match it comes
332
+ // back as a ResponseValidationError instead of being handed to the caller.
333
+ export async function $doPost<T extends object, R = Json>(
323
334
  route: string,
324
335
  postData: T,
325
336
  options?: RequestOptions,
326
- ): BodyResult {
337
+ responseSchema?: z.ZodType<R>,
338
+ ): BodyResult<R> {
327
339
  return $doBodyRequest(
328
340
  "POST",
329
341
  route,
330
342
  encodeJSON("body", postData, { explode: true }),
331
343
  { "Content-Type": "application/json" },
332
344
  options,
345
+ responseSchema,
333
346
  );
334
347
  }
335
348
 
@@ -1,13 +1,21 @@
1
1
  import { APIPromise } from "../types/async.js";
2
- import { $doPost, internalApiResult } from "./doAdmin.js";
2
+ import { $doPost, internalApiResultOf } from "./doAdmin.js";
3
+ import {
4
+ subscriptionPlanSelectionResponse,
5
+ subscriptionPlanSelectionResponse$inboundSchema,
6
+ } from "./subscriptionPlanSelection.js";
3
7
 
4
8
  export type subscriptionFinishScreeningQuestionsRequest = {
5
9
  vendor_id: number;
6
10
  };
7
11
 
8
- export function subscriptionFinishScreeningQuestions(request: subscriptionFinishScreeningQuestionsRequest): internalApiResult {
12
+ export function subscriptionFinishScreeningQuestions(
13
+ request: subscriptionFinishScreeningQuestionsRequest,
14
+ ): internalApiResultOf<subscriptionPlanSelectionResponse> {
9
15
  return new APIPromise($doPost(
10
16
  "/subscription/screening-questions",
11
- request
17
+ request,
18
+ undefined,
19
+ subscriptionPlanSelectionResponse$inboundSchema,
12
20
  ));
13
21
  }
@@ -0,0 +1,17 @@
1
+ import * as z from "zod/v3";
2
+
3
+ // What finishing the screening questions or choosing a vendor type answers. GSSD-7289.
4
+ export type subscriptionPlanSelectionResponse = {
5
+ success: boolean;
6
+ // false when Standard is the vendor's only plan (e.g. Level 1, which cannot buy Emerald): the
7
+ // server has already selected it, so the plan step is skipped and the next step is the invoice.
8
+ plan_selection_required: boolean;
9
+ };
10
+
11
+ // Unknown fields pass through, so the server can add to the response without breaking callers.
12
+ export const subscriptionPlanSelectionResponse$inboundSchema: z.ZodType<subscriptionPlanSelectionResponse> = z
13
+ .object({
14
+ success: z.boolean(),
15
+ plan_selection_required: z.boolean(),
16
+ })
17
+ .passthrough();
@@ -1,14 +1,22 @@
1
1
  import { APIPromise } from "../types/async.js";
2
- import { $doPost, internalApiResult } from "./doAdmin.js";
2
+ import { $doPost, internalApiResultOf } from "./doAdmin.js";
3
+ import {
4
+ subscriptionPlanSelectionResponse,
5
+ subscriptionPlanSelectionResponse$inboundSchema,
6
+ } from "./subscriptionPlanSelection.js";
3
7
 
4
8
  export type subscriptionUpdateVendorTypeRequest = {
5
9
  vendor_id: number;
6
10
  vendor_type_id: number[];
7
11
  };
8
12
 
9
- export function subscriptionUpdateVendorType(request: subscriptionUpdateVendorTypeRequest): internalApiResult {
13
+ export function subscriptionUpdateVendorType(
14
+ request: subscriptionUpdateVendorTypeRequest,
15
+ ): internalApiResultOf<subscriptionPlanSelectionResponse> {
10
16
  return new APIPromise($doPost(
11
17
  "/subscription/vendor-type",
12
- request
18
+ request,
19
+ undefined,
20
+ subscriptionPlanSelectionResponse$inboundSchema,
13
21
  ));
14
22
  }
package/src/lib/config.ts CHANGED
@@ -80,8 +80,8 @@ export function serverURLFromOptions(options: SDKOptions): URL | null {
80
80
  export const SDK_METADATA = {
81
81
  language: "typescript",
82
82
  openapiDocVersion: "0.47.0",
83
- sdkVersion: "0.48.0-beta.10",
83
+ sdkVersion: "0.48.0-beta.11",
84
84
  genVersion: "2.950.13",
85
85
  userAgent:
86
- "speakeasy-sdk/typescript 0.48.0-beta.10 2.950.13 0.47.0 @greensecurity/javascript-sdk",
86
+ "speakeasy-sdk/typescript 0.48.0-beta.11 2.950.13 0.47.0 @greensecurity/javascript-sdk",
87
87
  } as const;