@matech/thebigpos-sdk 3.2.0-stag-881 → 3.2.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 +39 -0
- package/dist/index.d.ts +1 -1
- package/docs/sdk_generation.md +149 -0
- package/package.json +15 -5
- package/scripts/apply-json-patch-content-type.js +129 -36
- package/src/index.ts +1 -1
package/README.md
CHANGED
|
@@ -40,5 +40,44 @@ apiClient.api.getSiteConfiguration().then((response) => {
|
|
|
40
40
|
});
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
## Generate SDK from Swagger
|
|
44
|
+
|
|
45
|
+
To regenerate the SDK from a specific API version, run:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npx swagger-typescript-api generate -p https://api.thebigpos.dev/swagger/{version}/swagger.json -o ./src -n index.ts -r true --axios --enum-names-as-values --enum-style union
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Replace `{version}` with the target API version (e.g. `v2.34.0`):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx swagger-typescript-api generate -p https://api.thebigpos.dev/swagger/v2.34.0/swagger.json -o ./src -n index.ts -r true --axios --enum-names-as-values --enum-style union
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Then apply the PATCH content-type fixup, passing the **same** spec that was given
|
|
58
|
+
to the generator. The generator does not propagate `application/json-patch+json`,
|
|
59
|
+
so this step sets each PATCH method's content type from the spec (no hard-coded
|
|
60
|
+
endpoint list):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
node scripts/apply-json-patch-content-type.js https://api.thebigpos.dev/swagger/v2.34.0/swagger.json
|
|
64
|
+
yarn build
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Publishing
|
|
68
|
+
|
|
69
|
+
1. Update the `version` field in `package.json` before publishing.
|
|
70
|
+
2. Build the project:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
yarn build
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
3. Publish to npm:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
yarn publish
|
|
80
|
+
```
|
|
81
|
+
|
|
43
82
|
____
|
|
44
83
|
© 2024 Mortgage Automation Technologies. All rights reserved
|
package/dist/index.d.ts
CHANGED
|
@@ -4526,7 +4526,7 @@ export interface NotificationTemplateVersionUpdateRequest {
|
|
|
4526
4526
|
}
|
|
4527
4527
|
export interface Operation {
|
|
4528
4528
|
op?: string;
|
|
4529
|
-
value?:
|
|
4529
|
+
value?: object | null;
|
|
4530
4530
|
path?: string;
|
|
4531
4531
|
}
|
|
4532
4532
|
export interface OutboundFailureBucket {
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Publishing the POS Typescript SDK
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
1. Clone the repository (if you haven't already):
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/MortgageAutomationTechnologies/thebigpos-sdk-typescript
|
|
9
|
+
cd thebigpos-sdk-typescript
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
2. Install swagger-typescript-api globally:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm i -g swagger-typescript-api
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
3. Connect to the MAT VPN
|
|
19
|
+
|
|
20
|
+
## Step 1: Create a release branch
|
|
21
|
+
|
|
22
|
+
Create a new branch for the version you're releasing:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
git checkout develop
|
|
26
|
+
git pull origin develop
|
|
27
|
+
git checkout -b release/X.Y.Z
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Step 2: Generate the SDK
|
|
31
|
+
|
|
32
|
+
Replace `{version}` with the target API version (e.g., `v2.31.0`):
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx swagger-typescript-api generate -p https://api.thebigpos.dev/swagger/{version}/swagger.json -o ./src -n index.ts -r true --axios --enum-names-as-values --generate-union-enums
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
> **Note:** If generating locally, use `http://localhost:5212/swagger/{version}/swagger.json` due to self-signed cert issues with https.
|
|
39
|
+
|
|
40
|
+
## Step 3: Apply post-generation fixes
|
|
41
|
+
|
|
42
|
+
Run the script to fix PATCH methods content type and Operation interface:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
node scripts/apply-json-patch-content-type.js
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This script:
|
|
49
|
+
- Sets all PATCH methods to use `ContentType.JsonPatch`
|
|
50
|
+
- Adds `JsonPatch` to the `ContentType` enum
|
|
51
|
+
- Fixes the `Operation` interface to allow any value type
|
|
52
|
+
|
|
53
|
+
## Step 4: Update the version
|
|
54
|
+
|
|
55
|
+
Use npm's version command to update the version in `package.json`:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm version X.Y.Z
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Version conventions:**
|
|
62
|
+
|
|
63
|
+
- Match the SDK version to the API version being released
|
|
64
|
+
- For release candidates (pre-release), use: `npm version X.Y.Z-rc.N --preid=rc`
|
|
65
|
+
- For patch increments: `npm version patch`
|
|
66
|
+
- For minor increments: `npm version minor`
|
|
67
|
+
|
|
68
|
+
## Step 5: Build the SDK
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npm run build
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Ensure there are no TypeScript compilation errors.
|
|
75
|
+
|
|
76
|
+
## Step 6: Merge develop (if needed)
|
|
77
|
+
|
|
78
|
+
If there are changes in develop that need to be included:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
git fetch origin develop
|
|
82
|
+
git merge origin/develop
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
If there are conflicts in `src/index.ts` or `dist/*`, regenerate the SDK (Step 2), apply fixes (Step 3), and rebuild (Step 5) to resolve them.
|
|
86
|
+
|
|
87
|
+
## Step 7: Commit and push
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
git add .
|
|
91
|
+
git commit -m "X.Y.Z"
|
|
92
|
+
git push -u origin release/X.Y.Z
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Step 8: Publish to NPM
|
|
96
|
+
|
|
97
|
+
### Authentication
|
|
98
|
+
|
|
99
|
+
NPM requires a granular access token with publish permissions and 2FA bypass enabled.
|
|
100
|
+
|
|
101
|
+
1. Go to [npmjs.com](https://www.npmjs.com) > Access Tokens > Generate New Token
|
|
102
|
+
2. Select "Granular Access Token"
|
|
103
|
+
3. Enable "Bypass 2FA for automation"
|
|
104
|
+
4. Set permissions to publish to `@matech/thebigpos-sdk`
|
|
105
|
+
|
|
106
|
+
Configure the token:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npm config set //registry.npmjs.org/:_authToken YOUR_TOKEN
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Publish
|
|
113
|
+
|
|
114
|
+
**To latest (stable release):**
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npm publish --access public
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**To next (pre-release):**
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npm publish --tag next
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**To a feature tag (for testing):**
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
npm publish --tag feature-name
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Installing the SDK
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Latest stable
|
|
136
|
+
yarn add @matech/thebigpos-sdk
|
|
137
|
+
|
|
138
|
+
# Next pre-release
|
|
139
|
+
yarn add @matech/thebigpos-sdk@next
|
|
140
|
+
|
|
141
|
+
# Specific version
|
|
142
|
+
yarn add @matech/thebigpos-sdk@X.Y.Z
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Step 9: Clean up
|
|
146
|
+
|
|
147
|
+
1. **Revoke the NPM token** after publishing for security
|
|
148
|
+
2. **Create a Pull Request** from `release/X.Y.Z` to `develop` and `main`
|
|
149
|
+
3. **Create a GitHub Release** with release notes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matech/thebigpos-sdk",
|
|
3
|
-
"version": "3.2.0
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "The Big POS Typescript SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -26,14 +26,24 @@
|
|
|
26
26
|
"url": "https://github.com/MortgageAutomationTechnologies/thebigpos-sdk-typescript/issues"
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://github.com/MortgageAutomationTechnologies/thebigpos-sdk-typescript#readme",
|
|
29
|
-
"
|
|
30
|
-
"
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"axios": "^1"
|
|
31
34
|
},
|
|
32
35
|
"devDependencies": {
|
|
33
|
-
"
|
|
36
|
+
"axios": "^1.16.1",
|
|
37
|
+
"esbuild": "^0.28.1",
|
|
34
38
|
"husky": "^9.1.5",
|
|
35
|
-
"rimraf": "6.1.
|
|
39
|
+
"rimraf": "6.1.3",
|
|
36
40
|
"ts-node": "^10.9.2",
|
|
37
41
|
"typescript": "^5.5.4"
|
|
42
|
+
},
|
|
43
|
+
"resolutions": {
|
|
44
|
+
"diff": "^4.0.4",
|
|
45
|
+
"brace-expansion": "^5.0.8",
|
|
46
|
+
"follow-redirects": "^1.16.0",
|
|
47
|
+
"form-data": "^4.0.6"
|
|
38
48
|
}
|
|
39
49
|
}
|
|
@@ -1,56 +1,149 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
1
|
+
/*
|
|
2
|
+
Post-generation fixup for the generated TypeScript SDK.
|
|
3
3
|
|
|
4
|
-
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
swagger-typescript-api does not propagate the `application/json-patch+json`
|
|
5
|
+
request content type into the generated code, so PATCH methods that use JSON
|
|
6
|
+
Patch would otherwise go out with the wrong Content-Type. This script restores
|
|
7
|
+
it by reading the OpenAPI spec the SDK was generated from and, for every
|
|
8
|
+
generated PATCH method, setting:
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
- ContentType.JsonPatch -> when the spec's requestBody for that path
|
|
11
|
+
advertises application/json-patch+json
|
|
12
|
+
- ContentType.Json -> for every other PATCH method
|
|
13
|
+
(e.g. updateLoan, which the backend declares as
|
|
14
|
+
[Consumes("application/json")])
|
|
15
|
+
|
|
16
|
+
The decision is taken entirely from the spec — there is no hard-coded list of
|
|
17
|
+
endpoints to keep in sync. It also ensures the ContentType enum includes
|
|
18
|
+
JsonPatch and relaxes the Operation interface `value` to accept any value.
|
|
19
|
+
|
|
20
|
+
Usage (pass the SAME spec given to `swagger-typescript-api -p`):
|
|
21
|
+
node scripts/apply-json-patch-content-type.js https://api.thebigpos.dev/swagger/<version>/swagger.json
|
|
22
|
+
node scripts/apply-json-patch-content-type.js ./swagger.json
|
|
23
|
+
SWAGGER_SPEC=<url-or-file> node scripts/apply-json-patch-content-type.js
|
|
24
|
+
|
|
25
|
+
Design notes:
|
|
26
|
+
- The rewrite is scoped to a single generated method block at a time
|
|
27
|
+
(anchored on that method's own `...params,`), so it can never bleed across
|
|
28
|
+
method boundaries.
|
|
29
|
+
- It sets each method's content type to its target value rather than doing a
|
|
30
|
+
conditional replace, so it is idempotent and self-healing (it also repairs
|
|
31
|
+
a previously-seen ContentType.JsonPatchPatch double-application).
|
|
32
|
+
- If no spec is provided (e.g. a plain commit-hook run), the content-type
|
|
33
|
+
rewrite is skipped instead of guessing, so it can never silently corrupt
|
|
34
|
+
the generated output.
|
|
9
35
|
*/
|
|
10
36
|
|
|
11
37
|
const fs = require('fs')
|
|
38
|
+
const nodePath = require('path')
|
|
12
39
|
|
|
13
|
-
const
|
|
40
|
+
const SRC = nodePath.resolve(__dirname, '../src/index.ts')
|
|
14
41
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
42
|
+
async function loadSpec(source) {
|
|
43
|
+
if (!source) return null
|
|
44
|
+
if (/^https?:\/\//i.test(source)) {
|
|
45
|
+
const res = await fetch(source)
|
|
46
|
+
if (!res.ok) throw new Error(`Failed to fetch spec from "${source}": HTTP ${res.status}`)
|
|
47
|
+
return res.json()
|
|
48
|
+
}
|
|
49
|
+
return JSON.parse(fs.readFileSync(nodePath.resolve(source), 'utf8'))
|
|
18
50
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
process.exit(1)
|
|
51
|
+
|
|
52
|
+
// Collapse spec ("{id}") and generated ("${id}") path params to a common token
|
|
53
|
+
// so generated paths can be matched against spec paths regardless of param names.
|
|
54
|
+
function normalizePath(p) {
|
|
55
|
+
return p.replace(/\$\{[^}]+\}/g, '{}').replace(/\{[^}]+\}/g, '{}')
|
|
25
56
|
}
|
|
26
57
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
)
|
|
58
|
+
function jsonPatchPaths(spec) {
|
|
59
|
+
const set = new Set()
|
|
60
|
+
for (const [route, ops] of Object.entries(spec.paths || {})) {
|
|
61
|
+
const content = ops && ops.patch && ops.patch.requestBody && ops.patch.requestBody.content
|
|
62
|
+
if (content && Object.prototype.hasOwnProperty.call(content, 'application/json-patch+json')) {
|
|
63
|
+
set.add(normalizePath(route))
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return set
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function setContentType(block, member) {
|
|
70
|
+
const target = `type: ContentType.${member}`
|
|
71
|
+
if (/type:\s*ContentType\.\w+/.test(block)) return block.replace(/type:\s*ContentType\.\w+/, target)
|
|
72
|
+
if (/type:\s*"[^"]*"/.test(block)) return block.replace(/type:\s*"[^"]*"/, target)
|
|
73
|
+
if (/\n(\s*)format:/.test(block)) return block.replace(/\n(\s*)format:/, `\n$1${target},\n$1format:`)
|
|
74
|
+
return block.replace(/\n(\s*)\.\.\.params,/, `\n$1${target},\n$1...params,`)
|
|
75
|
+
}
|
|
32
76
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/export enum ContentType\s*{([\s\S]*?)}/,
|
|
36
|
-
(match, enumBody) => {
|
|
77
|
+
function ensureJsonPatchEnum(content) {
|
|
78
|
+
return content.replace(/export enum ContentType\s*{([\s\S]*?)}/, (match, enumBody) => {
|
|
37
79
|
if (enumBody.includes('JsonPatch')) return match
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
80
|
+
return `export enum ContentType {\n JsonPatch = "application/json-patch+json",\n ${enumBody.trim()}\n}`
|
|
81
|
+
})
|
|
82
|
+
}
|
|
42
83
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
/export interface Operation\s*{([\s\S]*?)}/,
|
|
46
|
-
(match, body) => {
|
|
84
|
+
function relaxOperationValue(content) {
|
|
85
|
+
return content.replace(/export interface Operation\s*{([\s\S]*?)}/, (match, body) => {
|
|
47
86
|
const updated = body.replace(
|
|
48
87
|
/value\?:\s*object\s*\|?\s*null?;/,
|
|
49
88
|
'value?: string | number | boolean | null | object;'
|
|
50
89
|
)
|
|
51
90
|
return `export interface Operation {\n ${updated.trim()}\n}`
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function applyContentTypes(content, patchPaths) {
|
|
95
|
+
// Heal any earlier double-application (ContentType.JsonPatchPatch...).
|
|
96
|
+
content = content.replace(/ContentType\.JsonPatch(?:Patch)+\b/g, 'ContentType.JsonPatch')
|
|
97
|
+
|
|
98
|
+
const METHOD_BLOCK = /[a-zA-Z0-9_]+:\s*\([\s\S]*?\)\s*=>\s*this\.request<[^>]*>\(\{[\s\S]*?\.\.\.params,/g
|
|
99
|
+
return content.replace(METHOD_BLOCK, (block) => {
|
|
100
|
+
if (!/method:\s*"PATCH"/.test(block)) {
|
|
101
|
+
// Non-PATCH methods must never be JSON Patch.
|
|
102
|
+
return /type:\s*ContentType\.JsonPatch\b/.test(block)
|
|
103
|
+
? block.replace(/type:\s*ContentType\.JsonPatch\b/, 'type: ContentType.Json')
|
|
104
|
+
: block
|
|
105
|
+
}
|
|
106
|
+
const routeMatch = block.match(/path:\s*`([^`]*)`/)
|
|
107
|
+
const route = routeMatch ? normalizePath(routeMatch[1]) : ''
|
|
108
|
+
return setContentType(block, patchPaths.has(route) ? 'JsonPatch' : 'Json')
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
;(async () => {
|
|
113
|
+
if (!fs.existsSync(SRC)) {
|
|
114
|
+
console.error(`Error: File not found at "${SRC}". Generate the SDK first.`)
|
|
115
|
+
process.exit(1)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const source = process.argv[2] || process.env.SWAGGER_SPEC || process.env.SWAGGER_URL
|
|
119
|
+
let spec
|
|
120
|
+
try {
|
|
121
|
+
spec = await loadSpec(source)
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.error(`Error loading OpenAPI spec: ${err.message}`)
|
|
124
|
+
process.exit(1)
|
|
52
125
|
}
|
|
53
|
-
)
|
|
54
126
|
|
|
55
|
-
fs.
|
|
56
|
-
|
|
127
|
+
let content = fs.readFileSync(SRC, 'utf8')
|
|
128
|
+
content = ensureJsonPatchEnum(content)
|
|
129
|
+
content = relaxOperationValue(content)
|
|
130
|
+
|
|
131
|
+
if (!spec) {
|
|
132
|
+
console.warn(
|
|
133
|
+
'No OpenAPI spec provided (argument / SWAGGER_SPEC / SWAGGER_URL) — skipping PATCH content-type rewrite.\n' +
|
|
134
|
+
'Re-run with the spec used for generation to apply it, e.g.:\n' +
|
|
135
|
+
' node scripts/apply-json-patch-content-type.js https://api.thebigpos.dev/swagger/<version>/swagger.json'
|
|
136
|
+
)
|
|
137
|
+
fs.writeFileSync(SRC, content)
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const patchPaths = jsonPatchPaths(spec)
|
|
142
|
+
content = applyContentTypes(content, patchPaths)
|
|
143
|
+
|
|
144
|
+
fs.writeFileSync(SRC, content)
|
|
145
|
+
console.log(`SDK patch complete: PATCH content types set from the OpenAPI spec (${patchPaths.size} json-patch endpoint(s)).`)
|
|
146
|
+
})().catch((err) => {
|
|
147
|
+
console.error(err)
|
|
148
|
+
process.exit(1)
|
|
149
|
+
})
|
package/src/index.ts
CHANGED