stated-protocol-parser 1.0.7 → 5.0.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 +231 -22
- package/dist/constants.d.ts +193 -15
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +197 -20
- package/dist/constants.js.map +1 -1
- package/dist/esm/constants.d.ts +193 -15
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/{hash.browser.d.ts → hash.d.ts} +11 -5
- package/dist/esm/hash.d.ts.map +1 -0
- package/dist/esm/index.d.ts +4 -42
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2102 -641
- package/dist/esm/index.js.map +7 -1
- package/dist/esm/protocol.d.ts +18 -30
- package/dist/esm/protocol.d.ts.map +1 -1
- package/dist/esm/signature.d.ts +49 -0
- package/dist/esm/signature.d.ts.map +1 -0
- package/dist/esm/types.d.ts +26 -60
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/utils.d.ts +10 -0
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/{hash.browser.d.ts → hash.d.ts} +11 -5
- package/dist/hash.d.ts.map +1 -0
- package/dist/{hash.browser.js → hash.js} +44 -10
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +4 -42
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -674
- package/dist/index.js.map +1 -1
- package/dist/protocol.d.ts +18 -30
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +565 -572
- package/dist/protocol.js.map +1 -1
- package/dist/signature.d.ts +49 -0
- package/dist/signature.d.ts.map +1 -0
- package/dist/signature.js +169 -0
- package/dist/signature.js.map +1 -0
- package/dist/types.d.ts +26 -60
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +27 -0
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +79 -11
- package/dist/utils.js.map +1 -1
- package/package.json +32 -27
- package/src/constants.ts +228 -44
- package/src/fixtures.test.ts +236 -0
- package/src/hash.test.ts +217 -215
- package/src/hash.ts +99 -0
- package/src/index.ts +5 -0
- package/src/organisation-verification.test.ts +50 -0
- package/src/person-verification.test.ts +55 -0
- package/src/poll.test.ts +28 -0
- package/src/protocol.ts +855 -650
- package/src/rating.test.ts +25 -0
- package/src/signature.test.ts +200 -0
- package/src/signature.ts +159 -0
- package/src/statement.test.ts +101 -0
- package/src/types.ts +155 -156
- package/src/utils.test.ts +140 -0
- package/src/utils.ts +102 -16
- package/dist/esm/constants.js +0 -47
- package/dist/esm/constants.js.map +0 -1
- package/dist/esm/hash.browser.d.ts.map +0 -1
- package/dist/esm/hash.browser.js +0 -58
- package/dist/esm/hash.browser.js.map +0 -1
- package/dist/esm/hash.node.d.ts +0 -31
- package/dist/esm/hash.node.d.ts.map +0 -1
- package/dist/esm/hash.node.js +0 -43
- package/dist/esm/hash.node.js.map +0 -1
- package/dist/esm/hash.test.d.ts +0 -2
- package/dist/esm/hash.test.d.ts.map +0 -1
- package/dist/esm/hash.test.js +0 -181
- package/dist/esm/hash.test.js.map +0 -1
- package/dist/esm/index.browser.d.ts +0 -3
- package/dist/esm/index.browser.d.ts.map +0 -1
- package/dist/esm/index.browser.js +0 -5
- package/dist/esm/index.browser.js.map +0 -1
- package/dist/esm/index.node.d.ts +0 -3
- package/dist/esm/index.node.d.ts.map +0 -1
- package/dist/esm/index.node.js +0 -5
- package/dist/esm/index.node.js.map +0 -1
- package/dist/esm/index.test.d.ts +0 -2
- package/dist/esm/index.test.d.ts.map +0 -1
- package/dist/esm/index.test.js +0 -293
- package/dist/esm/index.test.js.map +0 -1
- package/dist/esm/protocol.js +0 -639
- package/dist/esm/protocol.js.map +0 -1
- package/dist/esm/types.js +0 -2
- package/dist/esm/types.js.map +0 -1
- package/dist/esm/utils.js +0 -23
- package/dist/esm/utils.js.map +0 -1
- package/dist/esm/v3.d.ts +0 -5
- package/dist/esm/v3.d.ts.map +0 -1
- package/dist/esm/v3.js +0 -60
- package/dist/esm/v3.js.map +0 -1
- package/dist/hash.browser.d.ts.map +0 -1
- package/dist/hash.browser.js.map +0 -1
- package/dist/hash.node.d.ts +0 -31
- package/dist/hash.node.d.ts.map +0 -1
- package/dist/hash.node.js +0 -53
- package/dist/hash.node.js.map +0 -1
- package/dist/hash.test.d.ts +0 -2
- package/dist/hash.test.d.ts.map +0 -1
- package/dist/hash.test.js +0 -183
- package/dist/hash.test.js.map +0 -1
- package/dist/index.browser.d.ts +0 -3
- package/dist/index.browser.d.ts.map +0 -1
- package/dist/index.browser.js +0 -21
- package/dist/index.browser.js.map +0 -1
- package/dist/index.node.d.ts +0 -3
- package/dist/index.node.d.ts.map +0 -1
- package/dist/index.node.js +0 -21
- package/dist/index.node.js.map +0 -1
- package/dist/index.test.d.ts +0 -2
- package/dist/index.test.d.ts.map +0 -1
- package/dist/index.test.js +0 -295
- package/dist/index.test.js.map +0 -1
- package/dist/v3.d.ts +0 -5
- package/dist/v3.d.ts.map +0 -1
- package/dist/v3.js +0 -64
- package/dist/v3.js.map +0 -1
- package/src/hash.browser.ts +0 -65
- package/src/hash.node.ts +0 -47
- package/src/index.browser.ts +0 -4
- package/src/index.node.ts +0 -4
- package/src/index.test.ts +0 -378
- package/src/v3.ts +0 -62
package/src/types.ts
CHANGED
|
@@ -1,186 +1,185 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import type { SupportedLanguage } from './constants';
|
|
2
|
+
|
|
3
|
+
export type LegalForm =
|
|
4
|
+
| 'local government'
|
|
5
|
+
| 'state government'
|
|
6
|
+
| 'foreign affairs ministry'
|
|
7
|
+
| 'corporation';
|
|
8
|
+
|
|
9
|
+
export type PeopleCountBucket =
|
|
10
|
+
| '0-10'
|
|
11
|
+
| '10-100'
|
|
12
|
+
| '100-1000'
|
|
13
|
+
| '1000-10,000'
|
|
14
|
+
| '10,000-100,000'
|
|
15
|
+
| '100,000+'
|
|
16
|
+
| '1,000,000+'
|
|
17
|
+
| '10,000,000+';
|
|
18
|
+
|
|
19
|
+
// Type guards
|
|
20
|
+
export function isLegalForm(value: string): value is LegalForm {
|
|
21
|
+
return [
|
|
22
|
+
'local government',
|
|
23
|
+
'state government',
|
|
24
|
+
'foreign affairs ministry',
|
|
25
|
+
'corporation',
|
|
26
|
+
].includes(value);
|
|
27
|
+
}
|
|
16
28
|
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
export function isPeopleCountBucket(value: string): value is PeopleCountBucket {
|
|
30
|
+
return [
|
|
31
|
+
'0-10',
|
|
32
|
+
'10-100',
|
|
33
|
+
'100-1000',
|
|
34
|
+
'1000-10,000',
|
|
35
|
+
'10,000-100,000',
|
|
36
|
+
'100,000+',
|
|
37
|
+
'1,000,000+',
|
|
38
|
+
'10,000,000+',
|
|
39
|
+
].includes(value);
|
|
26
40
|
}
|
|
27
41
|
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
authorVerification: string
|
|
31
|
-
originalTime?: string
|
|
32
|
-
source?: string
|
|
33
|
-
quotation?: string
|
|
34
|
-
paraphrasedStatement?: string
|
|
35
|
-
picture?: string
|
|
36
|
-
confidence?: string
|
|
42
|
+
export function isRatingValue(value: number): value is RatingValue {
|
|
43
|
+
return [1, 2, 3, 4, 5].includes(value);
|
|
37
44
|
}
|
|
38
45
|
|
|
46
|
+
export type StatementTypeValue =
|
|
47
|
+
| 'statement'
|
|
48
|
+
| 'organisation_verification'
|
|
49
|
+
| 'person_verification'
|
|
50
|
+
| 'poll'
|
|
51
|
+
| 'vote'
|
|
52
|
+
| 'response'
|
|
53
|
+
| 'dispute_statement_content'
|
|
54
|
+
| 'dispute_statement_authenticity'
|
|
55
|
+
| 'rating'
|
|
56
|
+
| 'sign_pdf';
|
|
57
|
+
|
|
58
|
+
export type Statement = {
|
|
59
|
+
domain: string;
|
|
60
|
+
author: string;
|
|
61
|
+
time: Date;
|
|
62
|
+
tags?: string[];
|
|
63
|
+
content: string;
|
|
64
|
+
representative?: string;
|
|
65
|
+
supersededStatement?: string;
|
|
66
|
+
formatVersion?: string;
|
|
67
|
+
translations?: Partial<Record<SupportedLanguage, string>>;
|
|
68
|
+
attachments?: string[];
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export type CryptographicallySignedStatement = {
|
|
72
|
+
statement: string;
|
|
73
|
+
statementHash: string;
|
|
74
|
+
publicKey: string;
|
|
75
|
+
signature: string;
|
|
76
|
+
algorithm: string;
|
|
77
|
+
};
|
|
78
|
+
|
|
39
79
|
export type Poll = {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
poll: string
|
|
47
|
-
scopeDescription?: string
|
|
48
|
-
scopeQueryLink?: string
|
|
49
|
-
options: string[]
|
|
50
|
-
allowArbitraryVote?: boolean
|
|
51
|
-
requiredProperty?: string
|
|
52
|
-
requiredPropertyValue?: string
|
|
53
|
-
requiredPropertyObserver?: string
|
|
54
|
-
requiredMinConfidence?: number
|
|
55
|
-
}
|
|
80
|
+
deadline: Date | undefined;
|
|
81
|
+
poll: string;
|
|
82
|
+
scopeDescription?: string;
|
|
83
|
+
options: string[];
|
|
84
|
+
allowArbitraryVote?: boolean;
|
|
85
|
+
};
|
|
56
86
|
|
|
57
87
|
export type OrganisationVerification = {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
name: string;
|
|
89
|
+
englishName?: string;
|
|
90
|
+
country: string;
|
|
91
|
+
city?: string;
|
|
92
|
+
province?: string;
|
|
93
|
+
legalForm: LegalForm;
|
|
94
|
+
department?: string;
|
|
95
|
+
domain: string;
|
|
96
|
+
foreignDomain?: string;
|
|
97
|
+
serialNumber?: string;
|
|
98
|
+
confidence?: number;
|
|
99
|
+
reliabilityPolicy?: string;
|
|
100
|
+
employeeCount?: PeopleCountBucket;
|
|
101
|
+
pictureHash?: string;
|
|
102
|
+
latitude?: number;
|
|
103
|
+
longitude?: number;
|
|
104
|
+
population?: PeopleCountBucket;
|
|
105
|
+
publicKey?: string;
|
|
106
|
+
};
|
|
76
107
|
|
|
77
108
|
export type withOwnDomain = {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
109
|
+
ownDomain: string;
|
|
110
|
+
foreignDomain?: string;
|
|
111
|
+
};
|
|
81
112
|
|
|
82
113
|
export type withForeignDomain = {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
114
|
+
foreignDomain: string;
|
|
115
|
+
ownDomain?: string;
|
|
116
|
+
};
|
|
86
117
|
|
|
87
118
|
export type PersonVerification = {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
119
|
+
name: string;
|
|
120
|
+
countryOfBirth: string;
|
|
121
|
+
cityOfBirth: string;
|
|
122
|
+
dateOfBirth: Date;
|
|
123
|
+
jobTitle?: string;
|
|
124
|
+
employer?: string;
|
|
125
|
+
verificationMethod?: string;
|
|
126
|
+
confidence?: number;
|
|
127
|
+
picture?: string;
|
|
128
|
+
reliabilityPolicy?: string;
|
|
129
|
+
publicKey?: string;
|
|
130
|
+
} & (withOwnDomain | withForeignDomain);
|
|
99
131
|
|
|
100
132
|
export type Vote = {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
133
|
+
pollHash: string;
|
|
134
|
+
poll: string;
|
|
135
|
+
vote: string;
|
|
136
|
+
};
|
|
105
137
|
|
|
106
138
|
export type DisputeAuthenticity = {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
139
|
+
hash: string;
|
|
140
|
+
confidence?: number;
|
|
141
|
+
reliabilityPolicy?: string;
|
|
142
|
+
};
|
|
111
143
|
|
|
112
144
|
export type DisputeContent = {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
145
|
+
hash: string;
|
|
146
|
+
confidence?: number;
|
|
147
|
+
reliabilityPolicy?: string;
|
|
148
|
+
};
|
|
117
149
|
|
|
118
150
|
export type ResponseContent = {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
151
|
+
hash: string;
|
|
152
|
+
response: string;
|
|
153
|
+
};
|
|
122
154
|
|
|
123
155
|
export type PDFSigning = {
|
|
124
|
-
|
|
125
|
-
}
|
|
156
|
+
hash: string;
|
|
157
|
+
};
|
|
126
158
|
|
|
127
159
|
export type RatingSubjectTypeValue =
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
160
|
+
| 'Organisation'
|
|
161
|
+
| 'Policy proposal'
|
|
162
|
+
| 'Treaty draft'
|
|
163
|
+
| 'Research publication'
|
|
164
|
+
| 'Regulation'
|
|
165
|
+
| 'Product';
|
|
166
|
+
|
|
167
|
+
export type RatingValue = 1 | 2 | 3 | 4 | 5;
|
|
134
168
|
|
|
135
169
|
export type Rating = {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
170
|
+
subjectType?: RatingSubjectTypeValue;
|
|
171
|
+
subjectName: string;
|
|
172
|
+
subjectReference?: string;
|
|
173
|
+
documentFileHash?: string;
|
|
174
|
+
rating: RatingValue;
|
|
175
|
+
quality?: string;
|
|
176
|
+
comment?: string;
|
|
177
|
+
};
|
|
144
178
|
|
|
145
179
|
export type Bounty = {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export type Observation = {
|
|
154
|
-
description?: string
|
|
155
|
-
approach?: string
|
|
156
|
-
confidence?: number
|
|
157
|
-
reliabilityPolicy?: string
|
|
158
|
-
subject: string
|
|
159
|
-
subjectReference?: string
|
|
160
|
-
observationReference?: string
|
|
161
|
-
property: string
|
|
162
|
-
value?: string
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export type PollV3 = {
|
|
166
|
-
country: string | undefined
|
|
167
|
-
city: string | undefined
|
|
168
|
-
legalEntity: string | undefined
|
|
169
|
-
domainScope: string[] | undefined
|
|
170
|
-
judges?: string
|
|
171
|
-
deadline: Date
|
|
172
|
-
poll: string
|
|
173
|
-
scopeDescription?: string
|
|
174
|
-
scopeQueryLink?: string
|
|
175
|
-
scopeProperty?: string
|
|
176
|
-
propertyScopeObserver?: string
|
|
177
|
-
pollType?: string
|
|
178
|
-
options: string[]
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export type Boycott = {
|
|
182
|
-
description?: string
|
|
183
|
-
reliabilityPolicy?: string
|
|
184
|
-
subject: string
|
|
185
|
-
subjectReference?: string
|
|
186
|
-
}
|
|
180
|
+
motivation?: string;
|
|
181
|
+
bounty: string;
|
|
182
|
+
reward: string;
|
|
183
|
+
judge: string;
|
|
184
|
+
judgePay?: string;
|
|
185
|
+
};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import { buildStatement } from './protocol';
|
|
4
|
+
import {
|
|
5
|
+
generateFileHash,
|
|
6
|
+
validateFileHash,
|
|
7
|
+
generateStatementContentHash,
|
|
8
|
+
validateStatementContentHash,
|
|
9
|
+
generateStatementHash,
|
|
10
|
+
validateStatementHash,
|
|
11
|
+
generateStatementsFile,
|
|
12
|
+
parseStatementsFile,
|
|
13
|
+
generateStatementFilename,
|
|
14
|
+
generateAttachmentFilename,
|
|
15
|
+
} from './utils';
|
|
16
|
+
|
|
17
|
+
describe('Statement Utils', () => {
|
|
18
|
+
const testContent = 'test content';
|
|
19
|
+
const testFileContent = Buffer.from('test file content');
|
|
20
|
+
|
|
21
|
+
describe('File Hash Functions', () => {
|
|
22
|
+
it('should generate file hash', () => {
|
|
23
|
+
const hash = generateFileHash(testFileContent);
|
|
24
|
+
assert.ok(hash);
|
|
25
|
+
assert.strictEqual(typeof hash, 'string');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should validate file hash', () => {
|
|
29
|
+
const hash = generateFileHash(testFileContent);
|
|
30
|
+
assert.strictEqual(validateFileHash(testFileContent, hash), true);
|
|
31
|
+
assert.strictEqual(validateFileHash(testFileContent, 'invalid-hash'), false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should generate attachment filename', () => {
|
|
35
|
+
const filename = generateAttachmentFilename(testFileContent, 'pdf');
|
|
36
|
+
assert.ok(/^[A-Za-z0-9_-]+\.pdf$/.test(filename));
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should handle extension with dot', () => {
|
|
40
|
+
const filename = generateAttachmentFilename(testFileContent, '.jpg');
|
|
41
|
+
assert.ok(/^[A-Za-z0-9_-]+\.jpg$/.test(filename));
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('Statement Content Hash Functions', () => {
|
|
46
|
+
it('should generate statement content hash', () => {
|
|
47
|
+
const hash = generateStatementContentHash(testContent);
|
|
48
|
+
assert.ok(hash);
|
|
49
|
+
assert.strictEqual(typeof hash, 'string');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should validate statement content hash', () => {
|
|
53
|
+
const hash = generateStatementContentHash(testContent);
|
|
54
|
+
assert.strictEqual(validateStatementContentHash(testContent, hash), true);
|
|
55
|
+
assert.strictEqual(validateStatementContentHash(testContent, 'invalid-hash'), false);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('Statement Hash Functions', () => {
|
|
60
|
+
const statement = buildStatement({
|
|
61
|
+
domain: 'example.com',
|
|
62
|
+
author: 'Test Author',
|
|
63
|
+
time: new Date('2023-06-15T20:01:26.000Z'),
|
|
64
|
+
content: 'Test statement content',
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should generate statement hash', () => {
|
|
68
|
+
const hash = generateStatementHash(statement);
|
|
69
|
+
assert.ok(hash);
|
|
70
|
+
assert.strictEqual(typeof hash, 'string');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should validate statement hash', () => {
|
|
74
|
+
const hash = generateStatementHash(statement);
|
|
75
|
+
assert.strictEqual(validateStatementHash(statement, hash), true);
|
|
76
|
+
assert.strictEqual(validateStatementHash(statement, 'invalid-hash'), false);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should generate statement filename', () => {
|
|
80
|
+
const filename = generateStatementFilename(statement);
|
|
81
|
+
assert.ok(/^[A-Za-z0-9_-]+\.txt$/.test(filename));
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should exclude signature fields from hash', () => {
|
|
85
|
+
const signedStatement =
|
|
86
|
+
statement +
|
|
87
|
+
'---\n' +
|
|
88
|
+
'Statement hash: test-hash\n' +
|
|
89
|
+
'Public key: test-key\n' +
|
|
90
|
+
'Signature: test-signature\n' +
|
|
91
|
+
'Algorithm: Ed25519\n';
|
|
92
|
+
|
|
93
|
+
const hash = generateStatementHash(signedStatement);
|
|
94
|
+
const hashWithoutSignature = generateStatementHash(statement);
|
|
95
|
+
assert.strictEqual(hash, hashWithoutSignature);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('Statements File Functions', () => {
|
|
100
|
+
const statement1 = buildStatement({
|
|
101
|
+
domain: 'example.com',
|
|
102
|
+
author: 'Test Author',
|
|
103
|
+
time: new Date('2023-06-15T20:01:26.000Z'),
|
|
104
|
+
content: 'First statement',
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const statement2 = buildStatement({
|
|
108
|
+
domain: 'example.com',
|
|
109
|
+
author: 'Test Author',
|
|
110
|
+
time: new Date('2023-06-16T10:30:00.000Z'),
|
|
111
|
+
content: 'Second statement',
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should generate statements file', () => {
|
|
115
|
+
const statementsFile = generateStatementsFile([statement1, statement2]);
|
|
116
|
+
assert.ok(statementsFile.includes(statement1));
|
|
117
|
+
assert.ok(statementsFile.includes(statement2));
|
|
118
|
+
assert.ok(statementsFile.includes('\n\n'));
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('should parse statements file', () => {
|
|
122
|
+
const statementsFile = generateStatementsFile([statement1, statement2]);
|
|
123
|
+
const parsed = parseStatementsFile(statementsFile);
|
|
124
|
+
assert.strictEqual(parsed.length, 2);
|
|
125
|
+
assert.strictEqual(parsed[0], statement1);
|
|
126
|
+
assert.strictEqual(parsed[1], statement2);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('should throw error for invalid statement in file', () => {
|
|
130
|
+
const invalidFile = 'Invalid statement\n\nAnother invalid statement';
|
|
131
|
+
assert.throws(() => parseStatementsFile(invalidFile));
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should filter empty statements', () => {
|
|
135
|
+
const fileWithEmpty = statement1 + '\n\n\n\n' + statement2;
|
|
136
|
+
const parsed = parseStatementsFile(fileWithEmpty);
|
|
137
|
+
assert.strictEqual(parsed.length, 2);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
});
|
package/src/utils.ts
CHANGED
|
@@ -1,18 +1,104 @@
|
|
|
1
|
-
import { peopleCountBuckets } from './constants'
|
|
1
|
+
import { peopleCountBuckets } from './constants';
|
|
2
|
+
|
|
3
|
+
import { sha256, verify } from './hash';
|
|
4
|
+
import { parseStatement } from './protocol';
|
|
5
|
+
|
|
6
|
+
export const generateFileHash = (fileContent: Buffer | string): string => {
|
|
7
|
+
return sha256(fileContent);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const validateFileHash = (fileContent: Buffer | string, expectedHash: string): boolean => {
|
|
11
|
+
return verify(fileContent, expectedHash);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const generateStatementContentHash = (statementContent: string): string => {
|
|
15
|
+
return sha256(statementContent);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const validateStatementContentHash = (
|
|
19
|
+
statementContent: string,
|
|
20
|
+
expectedHash: string
|
|
21
|
+
): boolean => {
|
|
22
|
+
return verify(statementContent, expectedHash);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const generateStatementHash = (statement: string): string => {
|
|
26
|
+
const signatureRegex = /^([\s\S]+?)---\n[\s\S]+$/;
|
|
27
|
+
const match = statement.match(signatureRegex);
|
|
28
|
+
|
|
29
|
+
if (match && match[1]) {
|
|
30
|
+
return sha256(match[1]);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return sha256(statement);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const validateStatementHash = (statement: string, expectedHash: string): boolean => {
|
|
37
|
+
const computedHash = generateStatementHash(statement);
|
|
38
|
+
return computedHash === expectedHash;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const generateStatementsFile = (statements: string[]): string => {
|
|
42
|
+
return statements.join('\n\n');
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const parseStatementsFile = (statementsFileContent: string): string[] => {
|
|
46
|
+
const statementParts = statementsFileContent.split(/\n\nStated protocol version: /);
|
|
47
|
+
const statements: string[] = [];
|
|
48
|
+
|
|
49
|
+
for (let i = 0; i < statementParts.length; i++) {
|
|
50
|
+
let statement = statementParts[i];
|
|
51
|
+
|
|
52
|
+
if (i === 0 && statement.trim().length === 0) continue;
|
|
53
|
+
|
|
54
|
+
if (i > 0) {
|
|
55
|
+
statement = 'Stated protocol version: ' + statement;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
statement = statement.replace(/\n+$/, '\n');
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
parseStatement({ statement });
|
|
62
|
+
statements.push(statement);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Invalid statement at index ${i}: ${error instanceof Error ? error.message : String(error)}`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return statements;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const generateStatementFilename = (statement: string): string => {
|
|
74
|
+
const hash = generateStatementHash(statement);
|
|
75
|
+
return `${hash}.txt`;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const generateAttachmentFilename = (
|
|
79
|
+
fileContent: Buffer | string,
|
|
80
|
+
extension: string
|
|
81
|
+
): string => {
|
|
82
|
+
const hash = generateFileHash(fileContent);
|
|
83
|
+
const ext = extension.startsWith('.') ? extension.substring(1) : extension;
|
|
84
|
+
return `${hash}.${ext}`;
|
|
85
|
+
};
|
|
2
86
|
|
|
3
87
|
export const minPeopleCountToRange = (n: number): string | undefined => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const monthIndex = (month: string): number =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
88
|
+
if (n >= 10000000) return peopleCountBuckets['10000000'];
|
|
89
|
+
if (n >= 1000000) return peopleCountBuckets['1000000'];
|
|
90
|
+
if (n >= 100000) return peopleCountBuckets['100000'];
|
|
91
|
+
if (n >= 10000) return peopleCountBuckets['10000'];
|
|
92
|
+
if (n >= 1000) return peopleCountBuckets['1000'];
|
|
93
|
+
if (n >= 100) return peopleCountBuckets['100'];
|
|
94
|
+
if (n >= 10) return peopleCountBuckets['10'];
|
|
95
|
+
if (n >= 0) return peopleCountBuckets['0'];
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const monthIndex = (month: string): number =>
|
|
99
|
+
['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'].indexOf(
|
|
100
|
+
month.toLowerCase().substr(0, 3)
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
export const birthDateFormat: RegExp =
|
|
104
|
+
/(?<d>\d{1,2})\s(?<month>Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(?<y>\d{4})/;
|
package/dist/esm/constants.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export const legalForms = {
|
|
2
|
-
local_government: 'local government',
|
|
3
|
-
state_government: 'state government',
|
|
4
|
-
foreign_affairs_ministry: 'foreign affairs ministry',
|
|
5
|
-
corporation: 'corporation',
|
|
6
|
-
};
|
|
7
|
-
export const statementTypes = {
|
|
8
|
-
statement: 'statement',
|
|
9
|
-
quotation: 'quotation',
|
|
10
|
-
organisationVerification: 'organisation_verification',
|
|
11
|
-
personVerification: 'person_verification',
|
|
12
|
-
poll: 'poll',
|
|
13
|
-
vote: 'vote',
|
|
14
|
-
response: 'response',
|
|
15
|
-
disputeContent: 'dispute_statement_content',
|
|
16
|
-
disputeAuthenticity: 'dispute_statement_authenticity',
|
|
17
|
-
boycott: 'boycott',
|
|
18
|
-
observation: 'observation',
|
|
19
|
-
rating: 'rating',
|
|
20
|
-
signPdf: "sign_pdf",
|
|
21
|
-
bounty: "bounty",
|
|
22
|
-
unsupported: "unsupported",
|
|
23
|
-
};
|
|
24
|
-
export const peopleCountBuckets = {
|
|
25
|
-
"0": "0-10",
|
|
26
|
-
"10": "10-100",
|
|
27
|
-
"100": "100-1000",
|
|
28
|
-
"1000": "1000-10,000",
|
|
29
|
-
"10000": "10,000-100,000",
|
|
30
|
-
"100000": "100,000+",
|
|
31
|
-
"1000000": "1,000,000+",
|
|
32
|
-
"10000000": "10,000,000+",
|
|
33
|
-
};
|
|
34
|
-
export const UTCFormat = /(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s\d{2}\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT/;
|
|
35
|
-
export const pollKeys = /(Type: |The poll outcome is finalized when the following nodes agree: |Voting deadline: |Poll: |Option 1: |Option 2: |Option 3: |Option 4: |Option 5: |Allow free text votes: |Who can vote: |Description: |Country scope: |City scope: |Legal form scope: |Domain scope: |All entities with the following property: |As observed by: |Link to query defining who can vote: )/g;
|
|
36
|
-
export const organisationVerificationKeys = /(Type: |Description: |Name: |English name: |Country: |Legal entity: |Legal form: |Department using the domain: |Owner of the domain: |Foreign domain used for publishing statements: |Province or state: |Business register number: |City: |Longitude: |Latitude: |Population: |Logo: |Employee count: |Reliability policy: |Confidence: )/g;
|
|
37
|
-
export const personVerificationKeys = /(Type: |Description: |Name: |Date of birth: |City of birth: |Country of birth: |Job title: |Employer: |Owner of the domain: |Foreign domain used for publishing statements: |Picture: |Verification method: |Confidence: |Reliability policy: )/g;
|
|
38
|
-
export const voteKeys = /(Type: |Poll id: |Poll: |Option: )/g;
|
|
39
|
-
export const disputeAuthenticityKeys = /(Type: |Description: |Hash of referenced statement: |Confidence: |Reliability policy: )/g;
|
|
40
|
-
export const disputeContentKeys = /(Type: |Description: |Hash of referenced statement: |Confidence: |Reliability policy: )/g;
|
|
41
|
-
export const responseKeys = /(Type: |Hash of referenced statement: |Response: )/;
|
|
42
|
-
export const PDFSigningKeys = /(Type: |Description: |PDF file hash: )/;
|
|
43
|
-
export const ratingKeys = /(Type: |Subject type: |Subject name: |URL that identifies the subject: |Document file hash: |Rated quality: |Our rating: |Comment: )/;
|
|
44
|
-
export const BountyKeys = /(Type: |In order to: |We will reward any entity that: |The reward is: |In case of dispute, bounty claims are judged by: |The judge will be paid per investigated case with a maxium of: )/;
|
|
45
|
-
export const ObservationKeys = /(Type: |Approach: |Confidence: |Reliability policy: |Subject: |Subject identity reference: |Observation reference: |Observed property: |Observed value: )/;
|
|
46
|
-
export const BoycottKeys = /(Type: |Description: |Subject: |Subject identity reference: )/;
|
|
47
|
-
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;IACtB,gBAAgB,EAAE,kBAAkB;IACpC,gBAAgB,EAAE,kBAAkB;IACpC,wBAAwB,EAAE,0BAA0B;IACpD,WAAW,EAAE,aAAa;CAC7B,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG;IAC1B,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,WAAW;IACtB,wBAAwB,EAAE,2BAA2B;IACrD,kBAAkB,EAAE,qBAAqB;IACzC,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,2BAA2B;IAC3C,mBAAmB,EAAE,gCAAgC;IACrD,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,aAAa;IAC1B,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,UAAU;IACnB,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,aAAa;CAC7B,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAC9B,GAAG,EAAE,MAAM;IACX,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,UAAU;IACjB,MAAM,EAAE,aAAa;IACrB,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,YAAY;IACvB,UAAU,EAAE,aAAa;CAC5B,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAW,yHAAyH,CAAA;AAE1J,MAAM,CAAC,MAAM,QAAQ,GAAG,gXAAgX,CAAA;AAExY,MAAM,CAAC,MAAM,4BAA4B,GAAG,6UAA6U,CAAA;AAEzX,MAAM,CAAC,MAAM,sBAAsB,GAAG,kPAAkP,CAAA;AAExR,MAAM,CAAC,MAAM,QAAQ,GAAG,qCAAqC,CAAA;AAE7D,MAAM,CAAC,MAAM,uBAAuB,GAAG,0FAA0F,CAAA;AAEjI,MAAM,CAAC,MAAM,kBAAkB,GAAG,0FAA0F,CAAA;AAE5H,MAAM,CAAC,MAAM,YAAY,GAAG,oDAAoD,CAAA;AAEhF,MAAM,CAAC,MAAM,cAAc,GAAG,wCAAwC,CAAA;AAEtE,MAAM,CAAC,MAAM,UAAU,GAAG,sIAAsI,CAAA;AAEhK,MAAM,CAAC,MAAM,UAAU,GAAG,2LAA2L,CAAA;AAErN,MAAM,CAAC,MAAM,eAAe,GAAG,2JAA2J,CAAA;AAE1L,MAAM,CAAC,MAAM,WAAW,GAAG,+DAA+D,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hash.browser.d.ts","sourceRoot":"","sources":["../../src/hash.browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAU,OAAO,MAAM,GAAG,UAAU,KAAG,OAAO,CAAC,MAAM,CAqBvE,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAU,SAAS,MAAM,GAAG,UAAU,EAAE,MAAM,MAAM,KAAG,OAAO,CAAC,OAAO,CAGxF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,KAAG,MAKnD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,KAAG,MAEhD,CAAA"}
|