protons 7.7.0 → 8.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 +5 -5
- package/dist/bin/protons.js +1 -1
- package/dist/src/fields/array-field.d.ts +18 -0
- package/dist/src/fields/array-field.d.ts.map +1 -0
- package/dist/src/fields/array-field.js +83 -0
- package/dist/src/fields/array-field.js.map +1 -0
- package/dist/src/fields/enum-field.d.ts +9 -0
- package/dist/src/fields/enum-field.d.ts.map +1 -0
- package/dist/src/fields/enum-field.js +21 -0
- package/dist/src/fields/enum-field.js.map +1 -0
- package/dist/src/fields/field.d.ts +45 -0
- package/dist/src/fields/field.d.ts.map +1 -0
- package/dist/src/fields/field.js +147 -0
- package/dist/src/fields/field.js.map +1 -0
- package/dist/src/fields/map-field.d.ts +22 -0
- package/dist/src/fields/map-field.d.ts.map +1 -0
- package/dist/src/fields/map-field.js +83 -0
- package/dist/src/fields/map-field.js.map +1 -0
- package/dist/src/fields/message-field.d.ts +9 -0
- package/dist/src/fields/message-field.d.ts.map +1 -0
- package/dist/src/fields/message-field.js +23 -0
- package/dist/src/fields/message-field.js.map +1 -0
- package/dist/src/index.d.ts +190 -16
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -963
- package/dist/src/index.js.map +1 -1
- package/dist/src/types/enum.d.ts +21 -0
- package/dist/src/types/enum.d.ts.map +1 -0
- package/dist/src/types/enum.js +87 -0
- package/dist/src/types/enum.js.map +1 -0
- package/dist/src/types/index.d.ts +20 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +2 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/types/message.d.ts +49 -0
- package/dist/src/types/message.d.ts.map +1 -0
- package/dist/src/types/message.js +478 -0
- package/dist/src/types/message.js.map +1 -0
- package/dist/src/types/module.d.ts +30 -0
- package/dist/src/types/module.d.ts.map +1 -0
- package/dist/src/types/module.js +184 -0
- package/dist/src/types/module.js.map +1 -0
- package/dist/src/types/primitive.d.ts +13 -0
- package/dist/src/types/primitive.d.ts.map +1 -0
- package/dist/src/types/primitive.js +174 -0
- package/dist/src/types/primitive.js.map +1 -0
- package/dist/typedoc-urls.json +2 -4
- package/package.json +102 -15
- package/src/fields/array-field.ts +109 -0
- package/src/fields/enum-field.ts +30 -0
- package/src/fields/field.ts +201 -0
- package/src/fields/map-field.ts +107 -0
- package/src/fields/message-field.ts +29 -0
- package/src/index.ts +6 -1202
- package/src/types/enum.ts +112 -0
- package/src/types/index.ts +21 -0
- package/src/types/message.ts +558 -0
- package/src/types/module.ts +234 -0
- package/src/types/primitive.ts +215 -0
- package/LICENSE +0 -4
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Enum } from '../types/enum.ts'
|
|
2
|
+
import { Field } from './field.ts'
|
|
3
|
+
import type { FieldDef } from './field.ts'
|
|
4
|
+
import type { Parent } from '../types/index.ts'
|
|
5
|
+
|
|
6
|
+
export class EnumField extends Field {
|
|
7
|
+
private enum: Enum
|
|
8
|
+
|
|
9
|
+
constructor (name: string, def: FieldDef, parent: Parent) {
|
|
10
|
+
super(name, def, parent)
|
|
11
|
+
|
|
12
|
+
const type = parent.findType(def.type)
|
|
13
|
+
|
|
14
|
+
if (!(type instanceof Enum)) {
|
|
15
|
+
throw new Error(`Type "${def.type}" was not an Enum`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
this.enum = type
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
getDefaultField (parent: Parent): string {
|
|
22
|
+
if (this.optional) {
|
|
23
|
+
return ''
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const type = parent.findType(this.type)
|
|
27
|
+
|
|
28
|
+
return `${this.name}: ${type.pbType}.${this.enum.lowestValueName}`
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { ParseError } from 'protons-runtime'
|
|
2
|
+
import { Enum } from '../types/enum.ts'
|
|
3
|
+
import { Message } from '../types/message.ts'
|
|
4
|
+
import type { Parent, Type } from '../types/index.ts'
|
|
5
|
+
|
|
6
|
+
export const CODEC_TYPES = {
|
|
7
|
+
VARINT: 0,
|
|
8
|
+
BIT64: 1,
|
|
9
|
+
LENGTH_DELIMITED: 2,
|
|
10
|
+
START_GROUP: 3,
|
|
11
|
+
END_GROUP: 4,
|
|
12
|
+
BIT32: 5
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const codecTypes: Record<string, number> = {
|
|
16
|
+
bool: CODEC_TYPES.VARINT,
|
|
17
|
+
bytes: CODEC_TYPES.LENGTH_DELIMITED,
|
|
18
|
+
double: CODEC_TYPES.BIT64,
|
|
19
|
+
enum: CODEC_TYPES.VARINT,
|
|
20
|
+
fixed32: CODEC_TYPES.BIT32,
|
|
21
|
+
fixed64: CODEC_TYPES.BIT64,
|
|
22
|
+
float: CODEC_TYPES.BIT32,
|
|
23
|
+
int32: CODEC_TYPES.VARINT,
|
|
24
|
+
int64: CODEC_TYPES.VARINT,
|
|
25
|
+
message: CODEC_TYPES.LENGTH_DELIMITED,
|
|
26
|
+
sfixed32: CODEC_TYPES.BIT32,
|
|
27
|
+
sfixed64: CODEC_TYPES.BIT64,
|
|
28
|
+
sint32: CODEC_TYPES.VARINT,
|
|
29
|
+
sint64: CODEC_TYPES.VARINT,
|
|
30
|
+
string: CODEC_TYPES.LENGTH_DELIMITED,
|
|
31
|
+
uint32: CODEC_TYPES.VARINT,
|
|
32
|
+
uint64: CODEC_TYPES.VARINT
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const jsTypeOverrides: Record<string, 'number' | 'string'> = {
|
|
36
|
+
JS_NUMBER: 'number',
|
|
37
|
+
JS_STRING: 'string'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface DefaultValueGenerator {
|
|
41
|
+
(): string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const defaultValueGenerators: Record<string, DefaultValueGenerator> = {
|
|
45
|
+
bool: () => 'false',
|
|
46
|
+
bytes: () => 'uint8ArrayAlloc(0)',
|
|
47
|
+
double: () => '0',
|
|
48
|
+
fixed32: () => '0',
|
|
49
|
+
fixed64: () => '0n',
|
|
50
|
+
float: () => '0',
|
|
51
|
+
int32: () => '0',
|
|
52
|
+
int64: () => '0n',
|
|
53
|
+
sfixed32: () => '0',
|
|
54
|
+
sfixed64: () => '0n',
|
|
55
|
+
sint32: () => '0',
|
|
56
|
+
sint64: () => '0n',
|
|
57
|
+
string: () => "''",
|
|
58
|
+
uint32: () => '0',
|
|
59
|
+
uint64: () => '0n'
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const defaultValueGeneratorsJsTypeOverrides: Record<string, DefaultValueGenerator> = {
|
|
63
|
+
number: () => '0',
|
|
64
|
+
string: () => "''"
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface FieldOptions extends Record<string, any> {
|
|
68
|
+
proto3_optional?: boolean
|
|
69
|
+
jstype?: 'string' | 'number'
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface FieldDef {
|
|
73
|
+
id: number
|
|
74
|
+
type: string
|
|
75
|
+
repeated?: boolean
|
|
76
|
+
options?: FieldOptions
|
|
77
|
+
rule?: string
|
|
78
|
+
oneof?: string[]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface MessageField {
|
|
82
|
+
/**
|
|
83
|
+
* Return a string that can be used in a typescript interface for this field
|
|
84
|
+
*/
|
|
85
|
+
getInterfaceField (parent: Parent, indent?: string): string
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export class Field implements MessageField {
|
|
89
|
+
public id: number
|
|
90
|
+
public name: string
|
|
91
|
+
public optional: boolean
|
|
92
|
+
public type: string
|
|
93
|
+
public proto2Required: boolean
|
|
94
|
+
public jsTypeOverride?: 'string' | 'number'
|
|
95
|
+
public oneof?: string[]
|
|
96
|
+
|
|
97
|
+
constructor (name: string, def: FieldDef, parent: Parent) {
|
|
98
|
+
this.id = def.id
|
|
99
|
+
this.name = name
|
|
100
|
+
|
|
101
|
+
// the default type for a message is unset so they are always optional
|
|
102
|
+
// https://developers.google.com/protocol-buffers/docs/proto3#default
|
|
103
|
+
this.optional = def.repeated !== true && def.options?.proto3_optional === true
|
|
104
|
+
this.type = def.type ?? 'string'
|
|
105
|
+
this.oneof = def.oneof
|
|
106
|
+
this.proto2Required = false
|
|
107
|
+
|
|
108
|
+
if (def.options?.jstype != null) {
|
|
109
|
+
this.jsTypeOverride = jsTypeOverrides[def.options.jstype]
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (this.jsTypeOverride != null && !['int64', 'uint64', 'sint64', 'fixed64', 'sfixed64'].includes(this.type)) {
|
|
113
|
+
throw new Error(`jstype override option is only allowed on int64, uint64, sint64, fixed64 or sfixed64 fields - got "${this.type}"`)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (def.rule === 'required') {
|
|
117
|
+
const message = `field "${name}" is required, this is not allowed in proto3. Please convert your proto2 definitions to proto3 - see https://github.com/ipfs/protons/wiki/Required-fields-and-protobuf-3`
|
|
118
|
+
|
|
119
|
+
if (parent.flags?.strict === true) {
|
|
120
|
+
throw new ParseError(message)
|
|
121
|
+
} else {
|
|
122
|
+
this.proto2Required = true
|
|
123
|
+
|
|
124
|
+
// eslint-disable-next-line no-console
|
|
125
|
+
console.info(`[WARN] ${message}`)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
getInterfaceField (parent: Parent, indent = ''): string {
|
|
131
|
+
return `${indent}${this.name}${this.optional ? '?' : ''}: ${this.jsTypeOverride ?? parent.findType(this.type).jsType}`
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
getDefaultField (parent: Parent): string {
|
|
135
|
+
if (this.optional) {
|
|
136
|
+
return ''
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const type = parent.findType(this.type)
|
|
140
|
+
|
|
141
|
+
if (type.pbType === 'bytes') {
|
|
142
|
+
parent.addImport('uint8arrays/alloc', 'alloc', 'uint8ArrayAlloc')
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
let defaultValueGenerator = defaultValueGenerators[type.pbType]
|
|
146
|
+
|
|
147
|
+
if (this.jsTypeOverride) {
|
|
148
|
+
defaultValueGenerator = defaultValueGeneratorsJsTypeOverrides[this.jsTypeOverride]
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (defaultValueGenerator == null) {
|
|
152
|
+
return ''
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return `${this.name}: ${defaultValueGenerator()}`
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
getDecoder (parent: Parent): string {
|
|
159
|
+
const type: Type = parent.findType(this.type)
|
|
160
|
+
|
|
161
|
+
return `case ${this.id}: {
|
|
162
|
+
obj.${this.name} = ${type.getDecoder(this)}
|
|
163
|
+
break
|
|
164
|
+
}`
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
getStreamingDecoder (parent: Parent): string {
|
|
168
|
+
const type: Type = parent.findType(this.type)
|
|
169
|
+
|
|
170
|
+
return `case ${this.id}: {
|
|
171
|
+
yield {
|
|
172
|
+
field: \`\${prefix != null ? \`\${prefix}\` : '$'}.${this.name}\`,
|
|
173
|
+
value: ${type.getDecoder(this, ' ')}
|
|
174
|
+
}
|
|
175
|
+
break
|
|
176
|
+
}`
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
getEncoder (parent: Parent): string {
|
|
180
|
+
const type = parent.findType(this.type)
|
|
181
|
+
let id = (this.id << 3) | codecTypes[this.type]
|
|
182
|
+
|
|
183
|
+
if (type instanceof Message) {
|
|
184
|
+
id = (this.id << 3) | codecTypes.message
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (type instanceof Enum) {
|
|
188
|
+
id = (this.id << 3) | codecTypes.enum
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return `
|
|
192
|
+
if (${type.getValueTest(this, `obj.${this.name}`)}) {
|
|
193
|
+
w.uint32(${id})
|
|
194
|
+
${type.getEncoder(this, `obj.${this.name}`)}
|
|
195
|
+
}`
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
getLimitField (): string {
|
|
199
|
+
return ''
|
|
200
|
+
}
|
|
201
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { codecTypes, Field } from './field.ts'
|
|
2
|
+
import type { FieldDef } from './field.ts'
|
|
3
|
+
import type { Parent } from '../types/index.ts'
|
|
4
|
+
|
|
5
|
+
export interface MapFieldDef extends FieldDef {
|
|
6
|
+
keyType?: string
|
|
7
|
+
valueType: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function isMapFieldDef (obj?: any): obj is MapFieldDef {
|
|
11
|
+
return obj?.keyType != null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class MapField extends Field {
|
|
15
|
+
public keyType: string
|
|
16
|
+
public valueType: string
|
|
17
|
+
public entryType: string
|
|
18
|
+
private lengthLimit?: number
|
|
19
|
+
|
|
20
|
+
constructor (name: string, def: MapFieldDef, parent: Parent) {
|
|
21
|
+
super(name, def, parent)
|
|
22
|
+
|
|
23
|
+
this.type = 'message'
|
|
24
|
+
this.keyType = def.keyType ?? 'string'
|
|
25
|
+
this.valueType = def.valueType
|
|
26
|
+
this.entryType = def.type
|
|
27
|
+
this.lengthLimit = def.options?.['(protons.options).limit']
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getInterfaceField (parent: Parent): string {
|
|
31
|
+
return `${this.name}: Map<${parent.findType(this.keyType).jsType}, ${parent.findType(this.valueType).jsType}>`
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getDefaultField (parent: Parent): string {
|
|
35
|
+
return `${this.name}: new Map<${parent.findType(this.keyType).jsType}, ${parent.findType(this.valueType).jsType}>()`
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getEncoder (parent: Parent): string {
|
|
39
|
+
const id = (this.id << 3) | codecTypes.message
|
|
40
|
+
const entryType = parent.findType(this.entryType)
|
|
41
|
+
|
|
42
|
+
return `
|
|
43
|
+
if (${entryType.getValueTest(this, 'value')}) {
|
|
44
|
+
for (const [key, value] of obj.${this.name}.entries()) {
|
|
45
|
+
w.uint32(${id})
|
|
46
|
+
${entryType.getEncoder(this, '{ key, value }')}
|
|
47
|
+
}
|
|
48
|
+
}`
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getDecoder (parent: Parent): string {
|
|
52
|
+
parent.addImport('protons-runtime', 'MaxSizeError')
|
|
53
|
+
const entryType = parent.findType(this.entryType)
|
|
54
|
+
|
|
55
|
+
let limit = `
|
|
56
|
+
if (opts.limits?.${this.name} != null && obj.${this.name}.size === opts.limits.${this.name}) {
|
|
57
|
+
throw new MaxSizeError('Decode error - map field "${this.name}" had too many elements')
|
|
58
|
+
}
|
|
59
|
+
`
|
|
60
|
+
|
|
61
|
+
if (this.lengthLimit != null) {
|
|
62
|
+
limit += `
|
|
63
|
+
if (obj.${this.name}.size === ${this.lengthLimit}) {
|
|
64
|
+
throw new MaxSizeError('Decode error - map field "${this.name}" had too many elements')
|
|
65
|
+
}
|
|
66
|
+
`
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return `case ${this.id}: {${limit}
|
|
70
|
+
const entry = ${entryType.getDecoder(this)}
|
|
71
|
+
obj.${this.name}.set(entry.key, entry.value)
|
|
72
|
+
break
|
|
73
|
+
}`
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getStreamingDecoder (parent: Parent): string {
|
|
77
|
+
parent.addImport('protons-runtime', 'MaxLengthError')
|
|
78
|
+
|
|
79
|
+
let limit = `
|
|
80
|
+
if (opts.limits?.${this.name} != null && obj.${this.name} === opts.limits.${this.name}) {
|
|
81
|
+
throw new MaxLengthError('Decode error - map field "${this.name}" had too many elements')
|
|
82
|
+
}
|
|
83
|
+
`
|
|
84
|
+
|
|
85
|
+
if (this.lengthLimit != null) {
|
|
86
|
+
limit += `
|
|
87
|
+
if (obj.${this.name} === ${this.lengthLimit}) {
|
|
88
|
+
throw new MaxLengthError('Decode error - repeated field "${this.name}" had too many elements')
|
|
89
|
+
}
|
|
90
|
+
`
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const type = parent.findType(this.entryType)
|
|
94
|
+
|
|
95
|
+
return `case ${this.id}: {${limit}
|
|
96
|
+
${type.getStreamingDecoder(this, `\`\${prefix != null ? \`\${prefix}\` : '$'}.${this.name}{}\``, ' ')}
|
|
97
|
+
|
|
98
|
+
obj.${this.name}++
|
|
99
|
+
|
|
100
|
+
break
|
|
101
|
+
}`
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
getLimitField (): string {
|
|
105
|
+
return `${this.name}: ${this.lengthLimit ?? 0}`
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Message } from '../types/message.ts'
|
|
2
|
+
import { Field } from './field.ts'
|
|
3
|
+
import type { Parent, Type } from '../types/index.ts'
|
|
4
|
+
|
|
5
|
+
export class MessageField extends Field {
|
|
6
|
+
getInterfaceField (parent: Parent, indent = ''): string {
|
|
7
|
+
return `${indent}${this.name}?: ${parent.findType(this.type).jsType}`
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
getMessage (parent: Parent): Message {
|
|
11
|
+
const type = parent.findType(this.type)
|
|
12
|
+
|
|
13
|
+
if (!(type instanceof Message)) {
|
|
14
|
+
throw new Error(`Field ${this.name} was not a message field`)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return type
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
getStreamingDecoder (parent: Parent): string {
|
|
21
|
+
const type: Type = parent.findType(this.type)
|
|
22
|
+
|
|
23
|
+
return `case ${this.id}: {
|
|
24
|
+
${type.getStreamingDecoder(this, `\`\${prefix != null ? \`\${prefix}\` : '$'}.${this.name}\``, ' ')}
|
|
25
|
+
|
|
26
|
+
break
|
|
27
|
+
}`
|
|
28
|
+
}
|
|
29
|
+
}
|