deere-sdk 2.0.0 → 2.1.1
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 +194 -0
- package/README.md +130 -20
- package/dist/api-servers.generated.d.ts +1 -1
- package/dist/api-servers.generated.js +1 -1
- package/dist/deere.d.ts +14 -0
- package/dist/deere.d.ts.map +1 -1
- package/dist/deere.js +20 -0
- package/dist/deere.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/safe/equipment.d.ts +92 -0
- package/dist/safe/equipment.d.ts.map +1 -0
- package/dist/safe/equipment.js +85 -0
- package/dist/safe/equipment.js.map +1 -0
- package/dist/safe/field-operations.d.ts +114 -0
- package/dist/safe/field-operations.d.ts.map +1 -0
- package/dist/safe/field-operations.js +112 -0
- package/dist/safe/field-operations.js.map +1 -0
- package/dist/safe/index.d.ts +52 -0
- package/dist/safe/index.d.ts.map +1 -0
- package/dist/safe/index.js +60 -0
- package/dist/safe/index.js.map +1 -0
- package/dist/safe/products.d.ts +53 -0
- package/dist/safe/products.d.ts.map +1 -0
- package/dist/safe/products.js +46 -0
- package/dist/safe/products.js.map +1 -0
- package/dist/types/generated/field-operations-api.d.ts +19 -0
- package/dist/types/generated/field-operations-api.d.ts.map +1 -1
- package/dist/types/generated/index.d.ts +1 -1
- package/dist/types/generated/index.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SafeEquipmentApi — hand-written facade over the generated EquipmentApi.
|
|
3
|
+
*
|
|
4
|
+
* John Deere's equipment API has six methods that accept an optional `embed`
|
|
5
|
+
* query parameter. JD documents narrow enum values for each (`devices`,
|
|
6
|
+
* `equipment`, `icon`, `pairingDetails`, `offsets`, `capabilities`, `make`,
|
|
7
|
+
* `type`, `isgType`, `equipmentModels`, `recordMetadata`) and the description
|
|
8
|
+
* on the parameter explicitly notes that `pairingDetails` "is only supported
|
|
9
|
+
* along with 'devices' or 'equipment' embeds" — strong signal that JD's API
|
|
10
|
+
* silently strips response fields when the embed is missing, same pattern as
|
|
11
|
+
* `fieldOperations.measurementTypes`.
|
|
12
|
+
*
|
|
13
|
+
* Unlike field-operations, we don't yet have wire traces confirming exactly
|
|
14
|
+
* which response fields each embed value populates, so the narrowed return
|
|
15
|
+
* types DON'T add spec patches. Instead, this facade offers forcing functions
|
|
16
|
+
* at the TYPE level: every `*WithEmbed` method requires the caller to pass a
|
|
17
|
+
* non-undefined `embed` value. Consumers can no longer call the safe variant
|
|
18
|
+
* and forget the embed. Once field-mcp probes capture the real response
|
|
19
|
+
* shapes, a follow-up can tighten the return types via spec patches (same
|
|
20
|
+
* mechanism as v2.1.0 used for measurementTypes).
|
|
21
|
+
*
|
|
22
|
+
* See scripts/embed-contracts.yaml for the contract registry that would house
|
|
23
|
+
* those future patches.
|
|
24
|
+
*/
|
|
25
|
+
import type { EquipmentApi } from '../api/equipment.js';
|
|
26
|
+
import type { PaginatedResponse, RequestOptions } from '../client.js';
|
|
27
|
+
import type { components } from '../types/generated/equipment.js';
|
|
28
|
+
type RequireEmbed<P> = P extends {
|
|
29
|
+
embed?: infer E;
|
|
30
|
+
} ? Omit<P, 'embed'> & {
|
|
31
|
+
embed: NonNullable<E>;
|
|
32
|
+
} : never;
|
|
33
|
+
type RawGetParams = NonNullable<Parameters<EquipmentApi['get']>[0]>;
|
|
34
|
+
type SafeGetParams = RequireEmbed<RawGetParams>;
|
|
35
|
+
type RawGetEquipmentParams = NonNullable<Parameters<EquipmentApi['getEquipment']>[1]>;
|
|
36
|
+
type SafeGetEquipmentParams = RequireEmbed<RawGetEquipmentParams>;
|
|
37
|
+
type RawListEquipmentmodelsParams = NonNullable<Parameters<EquipmentApi['listEquipmentmodels']>[0]>;
|
|
38
|
+
type SafeListEquipmentmodelsParams = RequireEmbed<RawListEquipmentmodelsParams>;
|
|
39
|
+
type RawListEquipmentisgtypesParams = NonNullable<Parameters<EquipmentApi['listEquipmentisgtypes']>[0]>;
|
|
40
|
+
type SafeListEquipmentisgtypesParams = RequireEmbed<RawListEquipmentisgtypesParams>;
|
|
41
|
+
type RawGetEquipmentisgtypesParams = NonNullable<Parameters<EquipmentApi['getEquipmentisgtypes']>[1]>;
|
|
42
|
+
type SafeGetEquipmentisgtypesParams = RequireEmbed<RawGetEquipmentisgtypesParams>;
|
|
43
|
+
type RawGetEquipmentisgtypes2Params = NonNullable<Parameters<EquipmentApi['getEquipmentisgtypes2']>[2]>;
|
|
44
|
+
type SafeGetEquipmentisgtypes2Params = RequireEmbed<RawGetEquipmentisgtypes2Params>;
|
|
45
|
+
export declare class SafeEquipmentApi {
|
|
46
|
+
private readonly raw;
|
|
47
|
+
constructor(raw: EquipmentApi);
|
|
48
|
+
/**
|
|
49
|
+
* Get paginated equipment list, with a required `embed` parameter.
|
|
50
|
+
* Wraps `deere.equipment.get`. Forces the caller to pick an embed value
|
|
51
|
+
* (`devices`, `equipment`, `icon`, or `pairingDetails`) that controls
|
|
52
|
+
* which optional response fields JD populates. See JD's spec note:
|
|
53
|
+
* "embed 'pairingDetails' is only supported along with 'devices' or
|
|
54
|
+
* 'equipment' embeds."
|
|
55
|
+
*
|
|
56
|
+
* Return type is the raw `PaginatedResponse<equipmentForList>` — fields
|
|
57
|
+
* added by the embed remain optional on the type because we don't yet
|
|
58
|
+
* have wire traces to confirm their shape. Once field-mcp probes them, a
|
|
59
|
+
* follow-up can tighten via spec patches.
|
|
60
|
+
*/
|
|
61
|
+
getWithEmbed(params: SafeGetParams, options?: RequestOptions): Promise<PaginatedResponse<components['schemas']['equipmentForList']>>;
|
|
62
|
+
/**
|
|
63
|
+
* Get a single equipment by ID, with a required `embed` parameter.
|
|
64
|
+
* Wraps `deere.equipment.getEquipment`. Embed values: `devices`,
|
|
65
|
+
* `equipment`, `pairingDetails`, `icon`, `offsets`, `capabilities`.
|
|
66
|
+
*/
|
|
67
|
+
getEquipmentWithEmbed(id: string, params: SafeGetEquipmentParams, options?: RequestOptions): Promise<components['schemas']['equipment']>;
|
|
68
|
+
/**
|
|
69
|
+
* List equipment models with a required `embed` parameter. Wraps
|
|
70
|
+
* `deere.equipment.listEquipmentmodels`. Embed values: `make`, `type`,
|
|
71
|
+
* `isgType`.
|
|
72
|
+
*/
|
|
73
|
+
listEquipmentmodelsWithEmbed(params: SafeListEquipmentmodelsParams, options?: RequestOptions): Promise<PaginatedResponse<components['schemas']['equipment-model']>>;
|
|
74
|
+
/**
|
|
75
|
+
* List equipment ISG types with a required `embed` parameter. Wraps
|
|
76
|
+
* `deere.equipment.listEquipmentisgtypes`. Embed values: `equipmentModels`,
|
|
77
|
+
* `recordMetadata`.
|
|
78
|
+
*/
|
|
79
|
+
listEquipmentisgtypesWithEmbed(params: SafeListEquipmentisgtypesParams, options?: RequestOptions): Promise<PaginatedResponse<components['schemas']['equipment-isg-type']>>;
|
|
80
|
+
/**
|
|
81
|
+
* Get equipment ISG types by make ID, with a required `embed` parameter.
|
|
82
|
+
* Wraps `deere.equipment.getEquipmentisgtypes`.
|
|
83
|
+
*/
|
|
84
|
+
getEquipmentisgtypesWithEmbed(equipmentMakeId: string, params: SafeGetEquipmentisgtypesParams, options?: RequestOptions): Promise<PaginatedResponse<components['schemas']['equipment-isg-type']>>;
|
|
85
|
+
/**
|
|
86
|
+
* Get a single equipment ISG type by make ID and ISG type ID, with a
|
|
87
|
+
* required `embed` parameter. Wraps `deere.equipment.getEquipmentisgtypes2`.
|
|
88
|
+
*/
|
|
89
|
+
getEquipmentisgtypes2WithEmbed(equipmentMakeId: string, equipmentISGTypeId: string, params: SafeGetEquipmentisgtypes2Params, options?: RequestOptions): Promise<components['schemas']['equipment-isg-type']>;
|
|
90
|
+
}
|
|
91
|
+
export {};
|
|
92
|
+
//# sourceMappingURL=equipment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"equipment.d.ts","sourceRoot":"","sources":["../../src/safe/equipment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SafeEquipmentApi — hand-written facade over the generated EquipmentApi.
|
|
3
|
+
*
|
|
4
|
+
* John Deere's equipment API has six methods that accept an optional `embed`
|
|
5
|
+
* query parameter. JD documents narrow enum values for each (`devices`,
|
|
6
|
+
* `equipment`, `icon`, `pairingDetails`, `offsets`, `capabilities`, `make`,
|
|
7
|
+
* `type`, `isgType`, `equipmentModels`, `recordMetadata`) and the description
|
|
8
|
+
* on the parameter explicitly notes that `pairingDetails` "is only supported
|
|
9
|
+
* along with 'devices' or 'equipment' embeds" — strong signal that JD's API
|
|
10
|
+
* silently strips response fields when the embed is missing, same pattern as
|
|
11
|
+
* `fieldOperations.measurementTypes`.
|
|
12
|
+
*
|
|
13
|
+
* Unlike field-operations, we don't yet have wire traces confirming exactly
|
|
14
|
+
* which response fields each embed value populates, so the narrowed return
|
|
15
|
+
* types DON'T add spec patches. Instead, this facade offers forcing functions
|
|
16
|
+
* at the TYPE level: every `*WithEmbed` method requires the caller to pass a
|
|
17
|
+
* non-undefined `embed` value. Consumers can no longer call the safe variant
|
|
18
|
+
* and forget the embed. Once field-mcp probes capture the real response
|
|
19
|
+
* shapes, a follow-up can tighten the return types via spec patches (same
|
|
20
|
+
* mechanism as v2.1.0 used for measurementTypes).
|
|
21
|
+
*
|
|
22
|
+
* See scripts/embed-contracts.yaml for the contract registry that would house
|
|
23
|
+
* those future patches.
|
|
24
|
+
*/
|
|
25
|
+
export class SafeEquipmentApi {
|
|
26
|
+
raw;
|
|
27
|
+
constructor(raw) {
|
|
28
|
+
this.raw = raw;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get paginated equipment list, with a required `embed` parameter.
|
|
32
|
+
* Wraps `deere.equipment.get`. Forces the caller to pick an embed value
|
|
33
|
+
* (`devices`, `equipment`, `icon`, or `pairingDetails`) that controls
|
|
34
|
+
* which optional response fields JD populates. See JD's spec note:
|
|
35
|
+
* "embed 'pairingDetails' is only supported along with 'devices' or
|
|
36
|
+
* 'equipment' embeds."
|
|
37
|
+
*
|
|
38
|
+
* Return type is the raw `PaginatedResponse<equipmentForList>` — fields
|
|
39
|
+
* added by the embed remain optional on the type because we don't yet
|
|
40
|
+
* have wire traces to confirm their shape. Once field-mcp probes them, a
|
|
41
|
+
* follow-up can tighten via spec patches.
|
|
42
|
+
*/
|
|
43
|
+
async getWithEmbed(params, options) {
|
|
44
|
+
return this.raw.get(params, options);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get a single equipment by ID, with a required `embed` parameter.
|
|
48
|
+
* Wraps `deere.equipment.getEquipment`. Embed values: `devices`,
|
|
49
|
+
* `equipment`, `pairingDetails`, `icon`, `offsets`, `capabilities`.
|
|
50
|
+
*/
|
|
51
|
+
async getEquipmentWithEmbed(id, params, options) {
|
|
52
|
+
return this.raw.getEquipment(id, params, options);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* List equipment models with a required `embed` parameter. Wraps
|
|
56
|
+
* `deere.equipment.listEquipmentmodels`. Embed values: `make`, `type`,
|
|
57
|
+
* `isgType`.
|
|
58
|
+
*/
|
|
59
|
+
async listEquipmentmodelsWithEmbed(params, options) {
|
|
60
|
+
return this.raw.listEquipmentmodels(params, options);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* List equipment ISG types with a required `embed` parameter. Wraps
|
|
64
|
+
* `deere.equipment.listEquipmentisgtypes`. Embed values: `equipmentModels`,
|
|
65
|
+
* `recordMetadata`.
|
|
66
|
+
*/
|
|
67
|
+
async listEquipmentisgtypesWithEmbed(params, options) {
|
|
68
|
+
return this.raw.listEquipmentisgtypes(params, options);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get equipment ISG types by make ID, with a required `embed` parameter.
|
|
72
|
+
* Wraps `deere.equipment.getEquipmentisgtypes`.
|
|
73
|
+
*/
|
|
74
|
+
async getEquipmentisgtypesWithEmbed(equipmentMakeId, params, options) {
|
|
75
|
+
return this.raw.getEquipmentisgtypes(equipmentMakeId, params, options);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get a single equipment ISG type by make ID and ISG type ID, with a
|
|
79
|
+
* required `embed` parameter. Wraps `deere.equipment.getEquipmentisgtypes2`.
|
|
80
|
+
*/
|
|
81
|
+
async getEquipmentisgtypes2WithEmbed(equipmentMakeId, equipmentISGTypeId, params, options) {
|
|
82
|
+
return this.raw.getEquipmentisgtypes2(equipmentMakeId, equipmentISGTypeId, params, options);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=equipment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"equipment.js","sourceRoot":"","sources":["../../src/safe/equipment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAqCH,MAAM,OAAO,gBAAgB;IACE;IAA7B,YAA6B,GAAiB;QAAjB,QAAG,GAAH,GAAG,CAAc;IAAG,CAAC;IAElD;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,YAAY,CAChB,MAAqB,EACrB,OAAwB;QAExB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,qBAAqB,CACzB,EAAU,EACV,MAA8B,EAC9B,OAAwB;QAExB,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,4BAA4B,CAChC,MAAqC,EACrC,OAAwB;QAExB,OAAO,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,8BAA8B,CAClC,MAAuC,EACvC,OAAwB;QAExB,OAAO,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,6BAA6B,CACjC,eAAuB,EACvB,MAAsC,EACtC,OAAwB;QAExB,OAAO,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACzE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,8BAA8B,CAClC,eAAuB,EACvB,kBAA0B,EAC1B,MAAuC,EACvC,OAAwB;QAExB,OAAO,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC,eAAe,EAAE,kBAAkB,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9F,CAAC;CACF"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SafeFieldOperationsApi — hand-written facade over the generated
|
|
3
|
+
* FieldOperationsApi.
|
|
4
|
+
*
|
|
5
|
+
* The raw FieldOperationsApi has THREE methods that accept the same
|
|
6
|
+
* `embed: 'measurementTypes'` query param with the same silent-zero failure
|
|
7
|
+
* mode:
|
|
8
|
+
*
|
|
9
|
+
* - list(orgId, fieldId, opts) — single-page paginated
|
|
10
|
+
* - listAll(orgId, fieldId, opts) — auto-paginated
|
|
11
|
+
* - get(operationId, opts) — single operation by ID
|
|
12
|
+
*
|
|
13
|
+
* John Deere's API silently omits the measurementTypes array on every
|
|
14
|
+
* returned FieldOperation / FieldOperationId unless the request passes
|
|
15
|
+
* `?embed=measurementTypes`, and JD's OpenAPI spec never encodes that
|
|
16
|
+
* invariant. Three separate times in FieldMCP, developers called listAll
|
|
17
|
+
* without the embed param and shipped placeholder zeros to production because
|
|
18
|
+
* the downstream normalizer couldn't distinguish "missing data" from "real
|
|
19
|
+
* zero."
|
|
20
|
+
*
|
|
21
|
+
* v2.1.0 wrapped listAll only. v2.1.1 completes the family — all three raw
|
|
22
|
+
* methods get `*WithMeasurements` variants that force the embed, narrow the
|
|
23
|
+
* return type to guarantee measurementTypes is present, and runtime-verify
|
|
24
|
+
* the guarantee so JD wire drift fails loudly instead of silently.
|
|
25
|
+
*
|
|
26
|
+
* See scripts/embed-contracts.yaml for the contract registry that makes the
|
|
27
|
+
* narrowed types (measurementTypes non-optional) honest at the type level.
|
|
28
|
+
*/
|
|
29
|
+
import type { FieldOperationsApi } from '../api/field-operations-api.js';
|
|
30
|
+
import type { PaginatedResponse } from '../client.js';
|
|
31
|
+
import type { components } from '../types/generated/field-operations-api.js';
|
|
32
|
+
type RawFieldOperation = components['schemas']['FieldOperation'];
|
|
33
|
+
type RawFieldOperationId = components['schemas']['FieldOperationId'];
|
|
34
|
+
type FieldOperationMeasurement = components['schemas']['FieldOperationMeasurement'];
|
|
35
|
+
/**
|
|
36
|
+
* A list-shape FieldOperation guaranteed to carry its measurementTypes array.
|
|
37
|
+
*
|
|
38
|
+
* Returned by `listWithMeasurements` and `listAllWithMeasurements`. Raw
|
|
39
|
+
* `FieldOperation` marks `measurementTypes` optional because JD's API only
|
|
40
|
+
* populates it when `?embed=measurementTypes` is passed; this narrowed type
|
|
41
|
+
* is honest because the safe wrapper forces the embed AND verifies every
|
|
42
|
+
* returned operation actually carries the array (throwing `DeereError` on
|
|
43
|
+
* contract violation).
|
|
44
|
+
*
|
|
45
|
+
* An empty `measurementTypes: []` is valid (operation exists but has no
|
|
46
|
+
* recorded measurements yet). `undefined` is a contract violation and throws.
|
|
47
|
+
*/
|
|
48
|
+
export type FieldOperationWithMeasurements = RawFieldOperation & {
|
|
49
|
+
measurementTypes: FieldOperationMeasurement[];
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* A get-by-id FieldOperationId guaranteed to carry its measurementTypes array.
|
|
53
|
+
*
|
|
54
|
+
* Returned by `getWithMeasurements`. JD treats the list-shape and get-shape
|
|
55
|
+
* as different schemas (`FieldOperation` vs `FieldOperationId`) even though
|
|
56
|
+
* the embedded `measurementTypes` array is structurally identical on both.
|
|
57
|
+
* v2.1.1 added a spec patch for the `FieldOperationId` schema mirroring
|
|
58
|
+
* v2.1.0's patch on `FieldOperation`; this narrowed type reflects that.
|
|
59
|
+
*/
|
|
60
|
+
export type FieldOperationIdWithMeasurements = RawFieldOperationId & {
|
|
61
|
+
measurementTypes: FieldOperationMeasurement[];
|
|
62
|
+
};
|
|
63
|
+
type RawListParams = NonNullable<Parameters<FieldOperationsApi['list']>[2]>;
|
|
64
|
+
type SafeListParams = Omit<RawListParams, 'embed'>;
|
|
65
|
+
type RawListAllParams = NonNullable<Parameters<FieldOperationsApi['listAll']>[2]>;
|
|
66
|
+
type SafeListAllParams = Omit<RawListAllParams, 'embed'>;
|
|
67
|
+
type RawGetParams = NonNullable<Parameters<FieldOperationsApi['get']>[1]>;
|
|
68
|
+
type SafeGetParams = Omit<RawGetParams, 'embed'>;
|
|
69
|
+
export declare class SafeFieldOperationsApi {
|
|
70
|
+
private readonly raw;
|
|
71
|
+
constructor(raw: FieldOperationsApi);
|
|
72
|
+
/**
|
|
73
|
+
* List all field operations on a field with measurement data embedded.
|
|
74
|
+
* Auto-paginates through every page and returns a flat array. Prefer this
|
|
75
|
+
* over `list*` when you want every operation.
|
|
76
|
+
*
|
|
77
|
+
* Forces `embed=measurementTypes` on the outgoing request, so yield, area,
|
|
78
|
+
* moisture, application rate, and seeding population are guaranteed present
|
|
79
|
+
* where JD has recorded them. Empty `measurementTypes: []` is a valid
|
|
80
|
+
* response (JD has no measurements for that operation yet). `undefined`
|
|
81
|
+
* `measurementTypes` on any returned operation is treated as a contract
|
|
82
|
+
* violation and throws `DeereError` naming the offending operation id.
|
|
83
|
+
*
|
|
84
|
+
* @throws {DeereError} if any returned operation lacks `measurementTypes`.
|
|
85
|
+
*/
|
|
86
|
+
listAllWithMeasurements(orgId: string, fieldId: string, params?: SafeListAllParams): Promise<FieldOperationWithMeasurements[]>;
|
|
87
|
+
/**
|
|
88
|
+
* List ONE page of field operations on a field with measurement data
|
|
89
|
+
* embedded. Returns the raw `PaginatedResponse<>` envelope so callers can
|
|
90
|
+
* walk `.links` and fetch subsequent pages manually. Prefer
|
|
91
|
+
* `listAllWithMeasurements` unless you explicitly need page-at-a-time
|
|
92
|
+
* control.
|
|
93
|
+
*
|
|
94
|
+
* Forces `embed=measurementTypes` on the outgoing request and runtime-
|
|
95
|
+
* verifies every operation on the returned page carries the array.
|
|
96
|
+
*
|
|
97
|
+
* @throws {DeereError} if any returned operation lacks `measurementTypes`.
|
|
98
|
+
*/
|
|
99
|
+
listWithMeasurements(orgId: string, fieldId: string, params?: SafeListParams): Promise<PaginatedResponse<FieldOperationWithMeasurements>>;
|
|
100
|
+
/**
|
|
101
|
+
* Get a single field operation by ID with measurement data embedded.
|
|
102
|
+
*
|
|
103
|
+
* Forces `embed=measurementTypes` and runtime-verifies the returned
|
|
104
|
+
* operation carries the array. Narrowed return type is
|
|
105
|
+
* `FieldOperationIdWithMeasurements` — JD treats the list-shape and
|
|
106
|
+
* get-shape as separate schemas, so the single-op type is named differently
|
|
107
|
+
* from `FieldOperationWithMeasurements`.
|
|
108
|
+
*
|
|
109
|
+
* @throws {DeereError} if the returned operation lacks `measurementTypes`.
|
|
110
|
+
*/
|
|
111
|
+
getWithMeasurements(operationId: string, params?: SafeGetParams): Promise<FieldOperationIdWithMeasurements>;
|
|
112
|
+
}
|
|
113
|
+
export {};
|
|
114
|
+
//# sourceMappingURL=field-operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-operations.d.ts","sourceRoot":"","sources":["../../src/safe/field-operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4CAA4C,CAAC;AAE7E,KAAK,iBAAiB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,gBAAgB,CAAC,CAAC;AACjE,KAAK,mBAAmB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,kBAAkB,CAAC,CAAC;AACrE,KAAK,yBAAyB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,2BAA2B,CAAC,CAAC;AAEpF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,8BAA8B,GAAG,iBAAiB,GAAG;IAC/D,gBAAgB,EAAE,yBAAyB,EAAE,CAAC;CAC/C,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,gCAAgC,GAAG,mBAAmB,GAAG;IACnE,gBAAgB,EAAE,yBAAyB,EAAE,CAAC;CAC/C,CAAC;AAEF,KAAK,aAAa,GAAG,WAAW,CAAC,UAAU,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5E,KAAK,cAAc,GAAG,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AAEnD,KAAK,gBAAgB,GAAG,WAAW,CAAC,UAAU,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClF,KAAK,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;AAEzD,KAAK,YAAY,GAAG,WAAW,CAAC,UAAU,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1E,KAAK,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;AAoBjD,qBAAa,sBAAsB;IACrB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,kBAAkB;IAEpD;;;;;;;;;;;;;OAaG;IACG,uBAAuB,CAC3B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,iBAAiB,GACzB,OAAO,CAAC,8BAA8B,EAAE,CAAC;IAW5C;;;;;;;;;;;OAWG;IACG,oBAAoB,CACxB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;IAW7D;;;;;;;;;;OAUG;IACG,mBAAmB,CACvB,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,gCAAgC,CAAC;CAQ7C"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SafeFieldOperationsApi — hand-written facade over the generated
|
|
3
|
+
* FieldOperationsApi.
|
|
4
|
+
*
|
|
5
|
+
* The raw FieldOperationsApi has THREE methods that accept the same
|
|
6
|
+
* `embed: 'measurementTypes'` query param with the same silent-zero failure
|
|
7
|
+
* mode:
|
|
8
|
+
*
|
|
9
|
+
* - list(orgId, fieldId, opts) — single-page paginated
|
|
10
|
+
* - listAll(orgId, fieldId, opts) — auto-paginated
|
|
11
|
+
* - get(operationId, opts) — single operation by ID
|
|
12
|
+
*
|
|
13
|
+
* John Deere's API silently omits the measurementTypes array on every
|
|
14
|
+
* returned FieldOperation / FieldOperationId unless the request passes
|
|
15
|
+
* `?embed=measurementTypes`, and JD's OpenAPI spec never encodes that
|
|
16
|
+
* invariant. Three separate times in FieldMCP, developers called listAll
|
|
17
|
+
* without the embed param and shipped placeholder zeros to production because
|
|
18
|
+
* the downstream normalizer couldn't distinguish "missing data" from "real
|
|
19
|
+
* zero."
|
|
20
|
+
*
|
|
21
|
+
* v2.1.0 wrapped listAll only. v2.1.1 completes the family — all three raw
|
|
22
|
+
* methods get `*WithMeasurements` variants that force the embed, narrow the
|
|
23
|
+
* return type to guarantee measurementTypes is present, and runtime-verify
|
|
24
|
+
* the guarantee so JD wire drift fails loudly instead of silently.
|
|
25
|
+
*
|
|
26
|
+
* See scripts/embed-contracts.yaml for the contract registry that makes the
|
|
27
|
+
* narrowed types (measurementTypes non-optional) honest at the type level.
|
|
28
|
+
*/
|
|
29
|
+
import { DeereError } from '../errors.js';
|
|
30
|
+
/** Shared contract-violation thrower. Runtime-validates that every returned
|
|
31
|
+
* operation carries the measurementTypes array the embed param is supposed
|
|
32
|
+
* to populate, and throws DeereError naming the offending op on drift. */
|
|
33
|
+
function assertMeasurementsPresent(op, methodName) {
|
|
34
|
+
if (op.measurementTypes === undefined) {
|
|
35
|
+
throw new DeereError(`deere-sdk contract violation in ${methodName}: field operation ${String(op.id ?? '(unknown id)')} ` +
|
|
36
|
+
`(type=${String(op.fieldOperationType ?? 'unknown')}) has no measurementTypes array ` +
|
|
37
|
+
`despite embed=measurementTypes being passed. JD's wire format may have drifted from the ` +
|
|
38
|
+
`documented contract. Capture a fresh fixture and update scripts/embed-contracts.yaml if needed.`, 0, 'CONTRACT_VIOLATION');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export class SafeFieldOperationsApi {
|
|
42
|
+
raw;
|
|
43
|
+
constructor(raw) {
|
|
44
|
+
this.raw = raw;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* List all field operations on a field with measurement data embedded.
|
|
48
|
+
* Auto-paginates through every page and returns a flat array. Prefer this
|
|
49
|
+
* over `list*` when you want every operation.
|
|
50
|
+
*
|
|
51
|
+
* Forces `embed=measurementTypes` on the outgoing request, so yield, area,
|
|
52
|
+
* moisture, application rate, and seeding population are guaranteed present
|
|
53
|
+
* where JD has recorded them. Empty `measurementTypes: []` is a valid
|
|
54
|
+
* response (JD has no measurements for that operation yet). `undefined`
|
|
55
|
+
* `measurementTypes` on any returned operation is treated as a contract
|
|
56
|
+
* violation and throws `DeereError` naming the offending operation id.
|
|
57
|
+
*
|
|
58
|
+
* @throws {DeereError} if any returned operation lacks `measurementTypes`.
|
|
59
|
+
*/
|
|
60
|
+
async listAllWithMeasurements(orgId, fieldId, params) {
|
|
61
|
+
const result = await this.raw.listAll(orgId, fieldId, {
|
|
62
|
+
...params,
|
|
63
|
+
embed: 'measurementTypes',
|
|
64
|
+
});
|
|
65
|
+
for (const op of result) {
|
|
66
|
+
assertMeasurementsPresent(op, 'listAllWithMeasurements');
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* List ONE page of field operations on a field with measurement data
|
|
72
|
+
* embedded. Returns the raw `PaginatedResponse<>` envelope so callers can
|
|
73
|
+
* walk `.links` and fetch subsequent pages manually. Prefer
|
|
74
|
+
* `listAllWithMeasurements` unless you explicitly need page-at-a-time
|
|
75
|
+
* control.
|
|
76
|
+
*
|
|
77
|
+
* Forces `embed=measurementTypes` on the outgoing request and runtime-
|
|
78
|
+
* verifies every operation on the returned page carries the array.
|
|
79
|
+
*
|
|
80
|
+
* @throws {DeereError} if any returned operation lacks `measurementTypes`.
|
|
81
|
+
*/
|
|
82
|
+
async listWithMeasurements(orgId, fieldId, params) {
|
|
83
|
+
const result = await this.raw.list(orgId, fieldId, {
|
|
84
|
+
...params,
|
|
85
|
+
embed: 'measurementTypes',
|
|
86
|
+
});
|
|
87
|
+
for (const op of result.values ?? []) {
|
|
88
|
+
assertMeasurementsPresent(op, 'listWithMeasurements');
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get a single field operation by ID with measurement data embedded.
|
|
94
|
+
*
|
|
95
|
+
* Forces `embed=measurementTypes` and runtime-verifies the returned
|
|
96
|
+
* operation carries the array. Narrowed return type is
|
|
97
|
+
* `FieldOperationIdWithMeasurements` — JD treats the list-shape and
|
|
98
|
+
* get-shape as separate schemas, so the single-op type is named differently
|
|
99
|
+
* from `FieldOperationWithMeasurements`.
|
|
100
|
+
*
|
|
101
|
+
* @throws {DeereError} if the returned operation lacks `measurementTypes`.
|
|
102
|
+
*/
|
|
103
|
+
async getWithMeasurements(operationId, params) {
|
|
104
|
+
const result = await this.raw.get(operationId, {
|
|
105
|
+
...params,
|
|
106
|
+
embed: 'measurementTypes',
|
|
107
|
+
});
|
|
108
|
+
assertMeasurementsPresent(result, 'getWithMeasurements');
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=field-operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-operations.js","sourceRoot":"","sources":["../../src/safe/field-operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA8C1C;;2EAE2E;AAC3E,SAAS,yBAAyB,CAEhC,EAAK,EAAE,UAAkB;IACzB,IAAI,EAAE,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,IAAI,UAAU,CAClB,mCAAmC,UAAU,qBAAqB,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,cAAc,CAAC,GAAG;YAClG,SAAS,MAAM,CAAC,EAAE,CAAC,kBAAkB,IAAI,SAAS,CAAC,kCAAkC;YACrF,0FAA0F;YAC1F,iGAAiG,EACnG,CAAC,EACD,oBAAoB,CACrB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,OAAO,sBAAsB;IACJ;IAA7B,YAA6B,GAAuB;QAAvB,QAAG,GAAH,GAAG,CAAoB;IAAG,CAAC;IAExD;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,uBAAuB,CAC3B,KAAa,EACb,OAAe,EACf,MAA0B;QAE1B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE;YACpD,GAAG,MAAM;YACT,KAAK,EAAE,kBAAkB;SAC1B,CAAC,CAAC;QACH,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;YACxB,yBAAyB,CAAC,EAAE,EAAE,yBAAyB,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO,MAA0C,CAAC;IACpD,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,oBAAoB,CACxB,KAAa,EACb,OAAe,EACf,MAAuB;QAEvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE;YACjD,GAAG,MAAM;YACT,KAAK,EAAE,kBAAkB;SAC1B,CAAC,CAAC;QACH,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;YACrC,yBAAyB,CAAC,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,MAA2D,CAAC;IACrE,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,mBAAmB,CACvB,WAAmB,EACnB,MAAsB;QAEtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE;YAC7C,GAAG,MAAM;YACT,KAAK,EAAE,kBAAkB;SAC1B,CAAC,CAAC;QACH,yBAAyB,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;QACzD,OAAO,MAA0C,CAAC;IACpD,CAAC;CACF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/safe — hand-written "safe" facades over generated API classes.
|
|
3
|
+
*
|
|
4
|
+
* Each file in this directory wraps a generated FooApi class with a FooSafeApi
|
|
5
|
+
* class whose methods force query params that the raw API leaves optional but
|
|
6
|
+
* that John Deere's real API requires for a complete response. See
|
|
7
|
+
* scripts/embed-contracts.yaml for the registry that documents the
|
|
8
|
+
* invariants these wrappers enforce.
|
|
9
|
+
*
|
|
10
|
+
* SafeFacades is the composition root. The generated Deere class constructs
|
|
11
|
+
* one instance as its last init step and exposes it as `deere.safe`, so
|
|
12
|
+
* consumers reach every safe wrapper through `deere.safe.<resource>.<method>`.
|
|
13
|
+
* Adding a new safe wrapper means adding a file here, then adding a field and
|
|
14
|
+
* a constructor init to SafeFacades below. Never touch scripts/generate-sdk.ts
|
|
15
|
+
* for new safe wrappers — the generator deliberately knows nothing about this
|
|
16
|
+
* module beyond its import path.
|
|
17
|
+
*/
|
|
18
|
+
import type { Deere } from '../deere.js';
|
|
19
|
+
import { SafeEquipmentApi } from './equipment.js';
|
|
20
|
+
import { SafeFieldOperationsApi } from './field-operations.js';
|
|
21
|
+
import { SafeProductsApi } from './products.js';
|
|
22
|
+
export { SafeEquipmentApi } from './equipment.js';
|
|
23
|
+
export type { FieldOperationIdWithMeasurements, FieldOperationWithMeasurements, } from './field-operations.js';
|
|
24
|
+
export { SafeFieldOperationsApi } from './field-operations.js';
|
|
25
|
+
export { SafeProductsApi } from './products.js';
|
|
26
|
+
/**
|
|
27
|
+
* Composition root for all safe facades.
|
|
28
|
+
*
|
|
29
|
+
* Constructed by the generated `Deere` class as its last init step (after all
|
|
30
|
+
* generated API fields have been initialized). Expose as `deere.safe`.
|
|
31
|
+
*
|
|
32
|
+
* Init-order invariant: SafeFacades' constructor reads generated API fields
|
|
33
|
+
* (`deere.fieldOperations`, `deere.equipment`, `deere.products`). The
|
|
34
|
+
* generator's `generateMainClass()` emits `this.safe = new SafeFacades(this)`
|
|
35
|
+
* AFTER the `${assignments}` substitution for exactly this reason. If a
|
|
36
|
+
* future generator refactor ever reorders those emissions, the runtime guard
|
|
37
|
+
* in this constructor fires loudly rather than silently initializing fields
|
|
38
|
+
* to undefined and failing ten minutes later in a downstream method call.
|
|
39
|
+
*
|
|
40
|
+
* Adding a new safe facade: write the class under `src/safe/`, import it
|
|
41
|
+
* here, add a `readonly` field, add an init line in the constructor, and
|
|
42
|
+
* extend the init-order guard to cover the required raw API. The generator
|
|
43
|
+
* never learns about the new facade — `scripts/generate-sdk.ts` only wires
|
|
44
|
+
* up `SafeFacades` as a black box.
|
|
45
|
+
*/
|
|
46
|
+
export declare class SafeFacades {
|
|
47
|
+
readonly fieldOperations: SafeFieldOperationsApi;
|
|
48
|
+
readonly equipment: SafeEquipmentApi;
|
|
49
|
+
readonly products: SafeProductsApi;
|
|
50
|
+
constructor(deere: Deere);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,YAAY,EACV,gCAAgC,EAChC,8BAA8B,GAC/B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,WAAW;IACtB,QAAQ,CAAC,eAAe,EAAE,sBAAsB,CAAC;IACjD,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;gBAEvB,KAAK,EAAE,KAAK;CAazB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/safe — hand-written "safe" facades over generated API classes.
|
|
3
|
+
*
|
|
4
|
+
* Each file in this directory wraps a generated FooApi class with a FooSafeApi
|
|
5
|
+
* class whose methods force query params that the raw API leaves optional but
|
|
6
|
+
* that John Deere's real API requires for a complete response. See
|
|
7
|
+
* scripts/embed-contracts.yaml for the registry that documents the
|
|
8
|
+
* invariants these wrappers enforce.
|
|
9
|
+
*
|
|
10
|
+
* SafeFacades is the composition root. The generated Deere class constructs
|
|
11
|
+
* one instance as its last init step and exposes it as `deere.safe`, so
|
|
12
|
+
* consumers reach every safe wrapper through `deere.safe.<resource>.<method>`.
|
|
13
|
+
* Adding a new safe wrapper means adding a file here, then adding a field and
|
|
14
|
+
* a constructor init to SafeFacades below. Never touch scripts/generate-sdk.ts
|
|
15
|
+
* for new safe wrappers — the generator deliberately knows nothing about this
|
|
16
|
+
* module beyond its import path.
|
|
17
|
+
*/
|
|
18
|
+
import { SafeEquipmentApi } from './equipment.js';
|
|
19
|
+
import { SafeFieldOperationsApi } from './field-operations.js';
|
|
20
|
+
import { SafeProductsApi } from './products.js';
|
|
21
|
+
export { SafeEquipmentApi } from './equipment.js';
|
|
22
|
+
export { SafeFieldOperationsApi } from './field-operations.js';
|
|
23
|
+
export { SafeProductsApi } from './products.js';
|
|
24
|
+
/**
|
|
25
|
+
* Composition root for all safe facades.
|
|
26
|
+
*
|
|
27
|
+
* Constructed by the generated `Deere` class as its last init step (after all
|
|
28
|
+
* generated API fields have been initialized). Expose as `deere.safe`.
|
|
29
|
+
*
|
|
30
|
+
* Init-order invariant: SafeFacades' constructor reads generated API fields
|
|
31
|
+
* (`deere.fieldOperations`, `deere.equipment`, `deere.products`). The
|
|
32
|
+
* generator's `generateMainClass()` emits `this.safe = new SafeFacades(this)`
|
|
33
|
+
* AFTER the `${assignments}` substitution for exactly this reason. If a
|
|
34
|
+
* future generator refactor ever reorders those emissions, the runtime guard
|
|
35
|
+
* in this constructor fires loudly rather than silently initializing fields
|
|
36
|
+
* to undefined and failing ten minutes later in a downstream method call.
|
|
37
|
+
*
|
|
38
|
+
* Adding a new safe facade: write the class under `src/safe/`, import it
|
|
39
|
+
* here, add a `readonly` field, add an init line in the constructor, and
|
|
40
|
+
* extend the init-order guard to cover the required raw API. The generator
|
|
41
|
+
* never learns about the new facade — `scripts/generate-sdk.ts` only wires
|
|
42
|
+
* up `SafeFacades` as a black box.
|
|
43
|
+
*/
|
|
44
|
+
export class SafeFacades {
|
|
45
|
+
fieldOperations;
|
|
46
|
+
equipment;
|
|
47
|
+
products;
|
|
48
|
+
constructor(deere) {
|
|
49
|
+
if (!deere.fieldOperations || !deere.equipment || !deere.products) {
|
|
50
|
+
throw new Error('SafeFacades constructed before all required raw API fields were initialized ' +
|
|
51
|
+
'(fieldOperations, equipment, products). scripts/generate-sdk.ts must emit ' +
|
|
52
|
+
'`this.safe = new SafeFacades(this)` AFTER the generated API field initializations ' +
|
|
53
|
+
'in generateMainClass(). Check the output order of the template substitutions.');
|
|
54
|
+
}
|
|
55
|
+
this.fieldOperations = new SafeFieldOperationsApi(deere.fieldOperations);
|
|
56
|
+
this.equipment = new SafeEquipmentApi(deere.equipment);
|
|
57
|
+
this.products = new SafeProductsApi(deere.products);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAKlD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,WAAW;IACb,eAAe,CAAyB;IACxC,SAAS,CAAmB;IAC5B,QAAQ,CAAkB;IAEnC,YAAY,KAAY;QACtB,IAAI,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YAClE,MAAM,IAAI,KAAK,CACb,8EAA8E;gBAC5E,4EAA4E;gBAC5E,oFAAoF;gBACpF,+EAA+E,CAClF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,eAAe,GAAG,IAAI,sBAAsB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACzE,IAAI,CAAC,SAAS,GAAG,IAAI,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;CACF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SafeProductsApi — hand-written facade over the generated ProductsApi.
|
|
3
|
+
*
|
|
4
|
+
* The products API has three methods (`list`, `listAll`, `get`) accepting
|
|
5
|
+
* `embed?: 'documents' | 'showMergedProducts'`. JD's spec names the embed
|
|
6
|
+
* "documents" and the description of the variety schema mentions a
|
|
7
|
+
* `documentsList` field, so the documented behavior strongly suggests
|
|
8
|
+
* embed=documents populates a list of document references on the variety
|
|
9
|
+
* response.
|
|
10
|
+
*
|
|
11
|
+
* Like SafeEquipmentApi, we don't yet have wire traces confirming the exact
|
|
12
|
+
* conditional response shape. This facade provides type-level forcing of the
|
|
13
|
+
* embed parameter without narrowing the return type. Future follow-ups can
|
|
14
|
+
* tighten via spec patches once field-mcp probes capture the real shapes.
|
|
15
|
+
*
|
|
16
|
+
* See scripts/embed-contracts.yaml for the contract registry.
|
|
17
|
+
*/
|
|
18
|
+
import type { ProductsApi } from '../api/products.js';
|
|
19
|
+
import type { PaginatedResponse, RequestOptions } from '../client.js';
|
|
20
|
+
import type { components } from '../types/generated/products.js';
|
|
21
|
+
type RequireEmbed<P> = P extends {
|
|
22
|
+
embed?: infer E;
|
|
23
|
+
} ? Omit<P, 'embed'> & {
|
|
24
|
+
embed: NonNullable<E>;
|
|
25
|
+
} : never;
|
|
26
|
+
type RawListParams = NonNullable<Parameters<ProductsApi['list']>[1]>;
|
|
27
|
+
type SafeListParams = RequireEmbed<RawListParams>;
|
|
28
|
+
type RawListAllParams = NonNullable<Parameters<ProductsApi['listAll']>[1]>;
|
|
29
|
+
type SafeListAllParams = RequireEmbed<RawListAllParams>;
|
|
30
|
+
type RawGetParams = NonNullable<Parameters<ProductsApi['get']>[2]>;
|
|
31
|
+
type SafeGetParams = RequireEmbed<RawGetParams>;
|
|
32
|
+
export declare class SafeProductsApi {
|
|
33
|
+
private readonly raw;
|
|
34
|
+
constructor(raw: ProductsApi);
|
|
35
|
+
/**
|
|
36
|
+
* List one page of varieties for an org, with a required `embed` parameter.
|
|
37
|
+
* Wraps `deere.products.list`. Embed values: `documents`,
|
|
38
|
+
* `showMergedProducts`.
|
|
39
|
+
*/
|
|
40
|
+
listWithEmbed(organizationId: string, params: SafeListParams, options?: RequestOptions): Promise<PaginatedResponse<components['schemas']['VarietyCollection']>>;
|
|
41
|
+
/**
|
|
42
|
+
* List all varieties for an org (auto-paginated), with a required `embed`
|
|
43
|
+
* parameter. Wraps `deere.products.listAll`.
|
|
44
|
+
*/
|
|
45
|
+
listAllWithEmbed(organizationId: string, params: SafeListAllParams, options?: RequestOptions): Promise<components['schemas']['VarietyCollection'][]>;
|
|
46
|
+
/**
|
|
47
|
+
* Get a single variety by ERID, with a required `embed` parameter.
|
|
48
|
+
* Wraps `deere.products.get`.
|
|
49
|
+
*/
|
|
50
|
+
getWithEmbed(organizationId: string, erid: string, params: SafeGetParams, options?: RequestOptions): Promise<components['schemas']['Variety']>;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=products.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../src/safe/products.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAEjE,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC,CAAA;CAAE,GAChD,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAA;CAAE,GAC5C,KAAK,CAAC;AAEV,KAAK,aAAa,GAAG,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrE,KAAK,cAAc,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC;AAElD,KAAK,gBAAgB,GAAG,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3E,KAAK,iBAAiB,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAC;AAExD,KAAK,YAAY,GAAG,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,KAAK,aAAa,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;AAEhD,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,WAAW;IAE7C;;;;OAIG;IACG,aAAa,CACjB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAIzE;;;OAGG;IACG,gBAAgB,CACpB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAAC;IAIxD;;;OAGG;IACG,YAAY,CAChB,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC;CAG7C"}
|