@tamtamchik/app-store-receipt-parser 2.1.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/README.md CHANGED
@@ -9,11 +9,13 @@
9
9
 
10
10
  A lightweight TypeScript library for extracting transaction IDs from Apple's ASN.1 encoded Unified Receipts.
11
11
 
12
- > **Warning!** This library is not a full-fledged receipt parser.
12
+ > [!IMPORTANT]
13
+ > This library is not a full-fledged receipt parser.
13
14
  > It only extracts some information from Apple's ASN.1 encoded Unified Receipts.
14
- > It does not work with the old-style transactions receipts.
15
+ > It does not work with the old-style transaction receipts.
15
16
 
16
- > **Documentation for the version 1.x of the library can be found [here](https://github.com/tamtamchik/app-store-receipt-parser/tree/1.x/README.md).**
17
+ > [!NOTE]
18
+ > Documentation for the version 1.x of the library can be found [here](https://github.com/tamtamchik/app-store-receipt-parser/tree/1.x/README.md).
17
19
 
18
20
  ## Installation
19
21
 
@@ -76,10 +78,11 @@ console.log(data);
76
78
  ## Special Thanks
77
79
 
78
80
  - [@Jurajzovinec](https://github.com/Jurajzovinec) for his superb contribution to the project.
81
+ - [@fechy](https://github.com/fechy) for bringing environment variable support to the lib.
79
82
 
80
83
  ## Contributing
81
84
 
82
- Pull requests are always welcome. If you have bigger changes in mind, please open an issue first to discuss your ideas.
85
+ Pull requests are always welcome. If you have bigger changes, please open an issue first to discuss your ideas.
83
86
 
84
87
  ## License
85
88
 
@@ -87,7 +90,7 @@ Apple Receipt Parser is [MIT licensed](./LICENSE).
87
90
 
88
91
  ## Third-Party Licenses
89
92
 
90
- This project uses `ASN1.js`, which is licensed under the BSD-3-Clause License. The license text can be found in [LICENSE](./LICENSE).
93
+ This project uses `ASN1.js`, licensed under the BSD-3-Clause License. The license text can be found in [LICENSE](./LICENSE).
91
94
 
92
95
  ---
93
96
  [![Buy Me A Coffee][ico-coffee]][link-coffee]
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -25,7 +35,7 @@ __export(src_exports, {
25
35
  module.exports = __toCommonJS(src_exports);
26
36
 
27
37
  // src/parser.ts
28
- var import_asn1js2 = require("asn1js");
38
+ var ASN1 = __toESM(require("asn1js"));
29
39
 
30
40
  // src/mappings.ts
31
41
  var RECEIPT_FIELDS_MAP = /* @__PURE__ */ new Map([
@@ -109,10 +119,8 @@ function verifyFieldSchema(sequence) {
109
119
  return fieldVerification;
110
120
  }
111
121
 
112
- // src/utils.ts
113
- var uniqueArrayValues = (array) => Array.from(new Set(array));
114
-
115
122
  // src/parser.ts
123
+ var uniqueArrayValues = (array) => Array.from(new Set(array));
116
124
  function isReceiptFieldKey(value) {
117
125
  return Boolean(typeof value === "number" && RECEIPT_FIELDS_MAP.has(value));
118
126
  }
@@ -126,7 +134,7 @@ function isParsedReceiptContentComplete(data) {
126
134
  }
127
135
  function extractFieldValue(field) {
128
136
  const [fieldValue] = field.valueBlock.value;
129
- if (fieldValue instanceof import_asn1js2.IA5String || fieldValue instanceof import_asn1js2.Utf8String) {
137
+ if (fieldValue instanceof ASN1.IA5String || fieldValue instanceof ASN1.Utf8String) {
130
138
  return fieldValue.valueBlock.value;
131
139
  }
132
140
  return field.toJSON().valueBlock.valueHex;
@@ -153,7 +161,7 @@ function processField(parsed, fieldKey, fieldValue) {
153
161
  }
154
162
  function parseOctetStringContent(parsed, content) {
155
163
  const [contentSet] = content.valueBlock.value;
156
- const contentSetSequences = contentSet.valueBlock.value.filter((v) => v instanceof import_asn1js2.Sequence);
164
+ const contentSetSequences = contentSet.valueBlock.value.filter((v) => v instanceof ASN1.Sequence);
157
165
  for (const sequence of contentSetSequences) {
158
166
  const verifiedSequence = verifyFieldSchema(sequence);
159
167
  if (verifiedSequence) {
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/parser.ts
2
- import { IA5String, Sequence as Sequence2, Utf8String } from "asn1js";
2
+ import * as ASN1 from "asn1js";
3
3
 
4
4
  // src/mappings.ts
5
5
  var RECEIPT_FIELDS_MAP = /* @__PURE__ */ new Map([
@@ -83,10 +83,8 @@ function verifyFieldSchema(sequence) {
83
83
  return fieldVerification;
84
84
  }
85
85
 
86
- // src/utils.ts
87
- var uniqueArrayValues = (array) => Array.from(new Set(array));
88
-
89
86
  // src/parser.ts
87
+ var uniqueArrayValues = (array) => Array.from(new Set(array));
90
88
  function isReceiptFieldKey(value) {
91
89
  return Boolean(typeof value === "number" && RECEIPT_FIELDS_MAP.has(value));
92
90
  }
@@ -100,7 +98,7 @@ function isParsedReceiptContentComplete(data) {
100
98
  }
101
99
  function extractFieldValue(field) {
102
100
  const [fieldValue] = field.valueBlock.value;
103
- if (fieldValue instanceof IA5String || fieldValue instanceof Utf8String) {
101
+ if (fieldValue instanceof ASN1.IA5String || fieldValue instanceof ASN1.Utf8String) {
104
102
  return fieldValue.valueBlock.value;
105
103
  }
106
104
  return field.toJSON().valueBlock.valueHex;
@@ -127,7 +125,7 @@ function processField(parsed, fieldKey, fieldValue) {
127
125
  }
128
126
  function parseOctetStringContent(parsed, content) {
129
127
  const [contentSet] = content.valueBlock.value;
130
- const contentSetSequences = contentSet.valueBlock.value.filter((v) => v instanceof Sequence2);
128
+ const contentSetSequences = contentSet.valueBlock.value.filter((v) => v instanceof ASN1.Sequence);
131
129
  for (const sequence of contentSetSequences) {
132
130
  const verifiedSequence = verifyFieldSchema(sequence);
133
131
  if (verifiedSequence) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamtamchik/app-store-receipt-parser",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "A lightweight TypeScript library for extracting transaction IDs from Apple's ASN.1 encoded receipts.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -35,9 +35,9 @@
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/jest": "29.5.12",
38
- "@types/node": "20.12.7",
39
- "@typescript-eslint/eslint-plugin": "7.6.0",
40
- "@typescript-eslint/parser": "7.6.0",
38
+ "@types/node": "^20.12.8",
39
+ "@typescript-eslint/eslint-plugin": "^7.8.0",
40
+ "@typescript-eslint/parser": "^7.8.0",
41
41
  "eslint": "8.57.0",
42
42
  "jest": "29.7.0",
43
43
  "ts-jest": "29.1.2",
package/src/mappings.ts CHANGED
@@ -1,21 +1,21 @@
1
1
  export type ReceiptFieldsKeyValues =
2
- | 0
3
- | 2
4
- | 3
5
- | 4
6
- | 5
7
- | 12
8
- | 18
9
- | 19
10
- | 1701
11
- | 1702
12
- | 1703
13
- | 1704
14
- | 1705
15
- | 1706
16
- | 1708
17
- | 1711
18
- | 1712
2
+ | 0 // Environment
3
+ | 2 // Bundle ID
4
+ | 3 // App version
5
+ | 4 // Opaque value
6
+ | 5 // SHA-1 hash
7
+ | 12 // Receipt creation date
8
+ | 18 // Original purchase date
9
+ | 19 // Original app version
10
+ | 1701 // In-app quantity
11
+ | 1702 // In-app product ID
12
+ | 1703 // In-app transaction ID
13
+ | 1704 // In-app purchase date
14
+ | 1705 // In-app original transaction ID
15
+ | 1706 // In-app original purchase date
16
+ | 1708 // In-app expires date
17
+ | 1711 // In-app web order line item ID
18
+ | 1712 // In-app cancellation date
19
19
 
20
20
  export type ReceiptFieldsKeyNames =
21
21
  | 'ENVIRONMENT'
@@ -58,5 +58,4 @@ export const RECEIPT_FIELDS_MAP: ReadonlyMap<ReceiptFieldsKeyValues, ReceiptFiel
58
58
  [1708, 'IN_APP_EXPIRES_DATE'],
59
59
  [1711, 'IN_APP_WEB_ORDER_LINE_ITEM_ID'],
60
60
  [1712, 'IN_APP_CANCELLATION_DATE'],
61
- ])
62
-
61
+ ])
package/src/parser.ts CHANGED
@@ -1,12 +1,13 @@
1
- import { IA5String, Integer, OctetString, Sequence, Set, Utf8String } from 'asn1js'
1
+ import * as ASN1 from 'asn1js'
2
2
 
3
3
  import { RECEIPT_FIELDS_MAP, ReceiptFieldsKeyNames, ReceiptFieldsKeyValues } from './mappings'
4
4
  import { CONTENT_ID, FIELD_TYPE_ID, FIELD_VALUE_ID, IN_APP } from './constants'
5
5
  import { verifyFieldSchema, verifyReceiptSchema } from './verifications'
6
- import { uniqueArrayValues } from './utils'
7
6
 
8
7
  export type Environment = 'Production' | 'ProductionSandbox' | string
9
8
 
9
+ const uniqueArrayValues = (array: string[]) => Array.from(new Set(array))
10
+
10
11
  export type ParsedReceipt = Partial<Record<ReceiptFieldsKeyNames, string>> & {
11
12
  ENVIRONMENT: Environment
12
13
  IN_APP_ORIGINAL_TRANSACTION_IDS: string[]
@@ -27,10 +28,10 @@ function isParsedReceiptContentComplete (data: ParsedReceipt): data is ParsedRec
27
28
  return true
28
29
  }
29
30
 
30
- function extractFieldValue (field: OctetString): string {
31
+ function extractFieldValue (field: ASN1.OctetString): string {
31
32
  const [fieldValue] = field.valueBlock.value
32
33
 
33
- if (fieldValue instanceof IA5String || fieldValue instanceof Utf8String) {
34
+ if (fieldValue instanceof ASN1.IA5String || fieldValue instanceof ASN1.Utf8String) {
34
35
  return fieldValue.valueBlock.value
35
36
  }
36
37
 
@@ -49,7 +50,7 @@ function appendField (parsed: ParsedReceipt, name: ReceiptFieldsKeyNames, value:
49
50
  parsed[name] = value
50
51
  }
51
52
 
52
- function processField (parsed: ParsedReceipt, fieldKey: number, fieldValue: OctetString) {
53
+ function processField (parsed: ParsedReceipt, fieldKey: number, fieldValue: ASN1.OctetString) {
53
54
  if (fieldKey === IN_APP) {
54
55
  parseOctetStringContent(parsed, fieldValue)
55
56
  return
@@ -63,16 +64,17 @@ function processField (parsed: ParsedReceipt, fieldKey: number, fieldValue: Octe
63
64
  appendField(parsed, name, extractFieldValue(fieldValue))
64
65
  }
65
66
 
66
- function parseOctetStringContent (parsed: ParsedReceipt, content: OctetString) {
67
- const [contentSet] = content.valueBlock.value as Set[]
68
- const contentSetSequences = contentSet.valueBlock.value.filter(v => v instanceof Sequence) as Sequence[]
67
+ function parseOctetStringContent (parsed: ParsedReceipt, content: ASN1.OctetString) {
68
+ const [contentSet] = content.valueBlock.value as ASN1.Set[]
69
+ const contentSetSequences = contentSet.valueBlock.value
70
+ .filter(v => v instanceof ASN1.Sequence) as ASN1.Sequence[]
69
71
 
70
72
  for (const sequence of contentSetSequences) {
71
73
  const verifiedSequence = verifyFieldSchema(sequence)
72
74
  if (verifiedSequence) {
73
75
  // We are confident to use "as" assertion because Integer type is guaranteed by positive verification above
74
- const fieldKey = (verifiedSequence.result[FIELD_TYPE_ID] as Integer).valueBlock.valueDec
75
- const fieldValueOctetString = verifiedSequence.result[FIELD_VALUE_ID] as OctetString
76
+ const fieldKey = (verifiedSequence.result[FIELD_TYPE_ID] as ASN1.Integer).valueBlock.valueDec
77
+ const fieldValueOctetString = verifiedSequence.result[FIELD_VALUE_ID] as ASN1.OctetString
76
78
 
77
79
  processField(parsed, fieldKey, fieldValueOctetString)
78
80
  }
@@ -87,7 +89,7 @@ function postprocessParsedReceipt (parsed: ParsedReceipt) {
87
89
  export function parseReceipt (receipt: string): ParsedReceipt {
88
90
  const rootSchemaVerification = verifyReceiptSchema(receipt)
89
91
 
90
- const content = rootSchemaVerification.result[CONTENT_ID] as OctetString
92
+ const content = rootSchemaVerification.result[CONTENT_ID] as ASN1.OctetString
91
93
  const parsed: ParsedReceipt = {
92
94
  ENVIRONMENT: 'Production',
93
95
  IN_APP_ORIGINAL_TRANSACTION_IDS: [],
package/src/utils.ts CHANGED
@@ -1 +1 @@
1
- export const uniqueArrayValues = (array: string[]) => Array.from(new Set(array))
1
+