@matech/thebigpos-sdk 3.0.0-rc.0 → 3.1.2-dev-30

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/package.json CHANGED
@@ -1,40 +1,49 @@
1
- {
2
- "name": "@matech/thebigpos-sdk",
3
- "version": "3.0.0-rc.0",
4
- "description": "The Big POS Typescript SDK",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "scripts": {
8
- "build": "rimraf dist && tsc",
9
- "test": "mocha -r ts-node/register 'src/api_test.spec.ts' --exit",
10
- "browserify": "tsc && browserify -p tinyify dist/index.js -s orcaloans > dist/orcaloans.min.js",
11
- "prepare": "husky"
12
- },
13
- "repository": {
14
- "type": "git",
15
- "url": "git+https://github.com/MortgageAutomationTechnologies/thebigpos-sdk-typescript.git"
16
- },
17
- "keywords": [
18
- "pos",
19
- "loans",
20
- "mortgage",
21
- "automation"
22
- ],
23
- "author": "Mortgage Automation Technologies",
24
- "license": "MIT",
25
- "bugs": {
26
- "url": "https://github.com/MortgageAutomationTechnologies/thebigpos-sdk-typescript/issues"
27
- },
28
- "homepage": "https://github.com/MortgageAutomationTechnologies/thebigpos-sdk-typescript#readme",
29
- "dependencies": {
30
- "axios": "^1.7.7",
31
- "browserify": "^17.0.0",
32
- "tinyify": "^4.0.0"
33
- },
34
- "devDependencies": {
35
- "husky": "^9.1.5",
36
- "rimraf": "^6.0.1",
37
- "ts-node": "^10.9.2",
38
- "typescript": "^5.5.4"
39
- }
40
- }
1
+ {
2
+ "name": "@matech/thebigpos-sdk",
3
+ "version": "3.1.2-dev-30",
4
+ "description": "The Big POS Typescript SDK",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "rimraf dist && tsc",
9
+ "test": "mocha -r ts-node/register 'src/api_test.spec.ts' --exit",
10
+ "browserify": "tsc && esbuild dist/index.js --bundle --minify --sourcemap --global-name=thebigpos --outfile=dist/thebigpos.min.js",
11
+ "prepare": "husky"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/MortgageAutomationTechnologies/thebigpos-sdk-typescript.git"
16
+ },
17
+ "keywords": [
18
+ "pos",
19
+ "loans",
20
+ "mortgage",
21
+ "automation"
22
+ ],
23
+ "author": "Mortgage Automation Technologies",
24
+ "license": "MIT",
25
+ "bugs": {
26
+ "url": "https://github.com/MortgageAutomationTechnologies/thebigpos-sdk-typescript/issues"
27
+ },
28
+ "homepage": "https://github.com/MortgageAutomationTechnologies/thebigpos-sdk-typescript#readme",
29
+ "engines": {
30
+ "node": ">=18"
31
+ },
32
+ "peerDependencies": {
33
+ "axios": "^1"
34
+ },
35
+ "devDependencies": {
36
+ "axios": "^1.16.1",
37
+ "esbuild": "^0.28.1",
38
+ "husky": "^9.1.5",
39
+ "rimraf": "6.1.3",
40
+ "ts-node": "^10.9.2",
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"
48
+ }
49
+ }
@@ -0,0 +1,149 @@
1
+ /*
2
+ Post-generation fixup for the generated TypeScript SDK.
3
+
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:
9
+
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.
35
+ */
36
+
37
+ const fs = require('fs')
38
+ const nodePath = require('path')
39
+
40
+ const SRC = nodePath.resolve(__dirname, '../src/index.ts')
41
+
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'))
50
+ }
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, '{}')
56
+ }
57
+
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
+ }
76
+
77
+ function ensureJsonPatchEnum(content) {
78
+ return content.replace(/export enum ContentType\s*{([\s\S]*?)}/, (match, enumBody) => {
79
+ if (enumBody.includes('JsonPatch')) return match
80
+ return `export enum ContentType {\n JsonPatch = "application/json-patch+json",\n ${enumBody.trim()}\n}`
81
+ })
82
+ }
83
+
84
+ function relaxOperationValue(content) {
85
+ return content.replace(/export interface Operation\s*{([\s\S]*?)}/, (match, body) => {
86
+ const updated = body.replace(
87
+ /value\?:\s*object\s*\|?\s*null?;/,
88
+ 'value?: string | number | boolean | null | object;'
89
+ )
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)
125
+ }
126
+
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
+ })