protons 7.7.0 → 8.0.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.
Files changed (60) hide show
  1. package/README.md +5 -5
  2. package/dist/bin/protons.js +1 -1
  3. package/dist/src/fields/array-field.d.ts +18 -0
  4. package/dist/src/fields/array-field.d.ts.map +1 -0
  5. package/dist/src/fields/array-field.js +83 -0
  6. package/dist/src/fields/array-field.js.map +1 -0
  7. package/dist/src/fields/enum-field.d.ts +9 -0
  8. package/dist/src/fields/enum-field.d.ts.map +1 -0
  9. package/dist/src/fields/enum-field.js +21 -0
  10. package/dist/src/fields/enum-field.js.map +1 -0
  11. package/dist/src/fields/field.d.ts +45 -0
  12. package/dist/src/fields/field.d.ts.map +1 -0
  13. package/dist/src/fields/field.js +147 -0
  14. package/dist/src/fields/field.js.map +1 -0
  15. package/dist/src/fields/map-field.d.ts +22 -0
  16. package/dist/src/fields/map-field.d.ts.map +1 -0
  17. package/dist/src/fields/map-field.js +83 -0
  18. package/dist/src/fields/map-field.js.map +1 -0
  19. package/dist/src/fields/message-field.d.ts +9 -0
  20. package/dist/src/fields/message-field.d.ts.map +1 -0
  21. package/dist/src/fields/message-field.js +23 -0
  22. package/dist/src/fields/message-field.js.map +1 -0
  23. package/dist/src/index.d.ts +190 -16
  24. package/dist/src/index.d.ts.map +1 -1
  25. package/dist/src/index.js +5 -963
  26. package/dist/src/index.js.map +1 -1
  27. package/dist/src/types/enum.d.ts +21 -0
  28. package/dist/src/types/enum.d.ts.map +1 -0
  29. package/dist/src/types/enum.js +87 -0
  30. package/dist/src/types/enum.js.map +1 -0
  31. package/dist/src/types/index.d.ts +20 -0
  32. package/dist/src/types/index.d.ts.map +1 -0
  33. package/dist/src/types/index.js +2 -0
  34. package/dist/src/types/index.js.map +1 -0
  35. package/dist/src/types/message.d.ts +49 -0
  36. package/dist/src/types/message.d.ts.map +1 -0
  37. package/dist/src/types/message.js +478 -0
  38. package/dist/src/types/message.js.map +1 -0
  39. package/dist/src/types/module.d.ts +30 -0
  40. package/dist/src/types/module.d.ts.map +1 -0
  41. package/dist/src/types/module.js +184 -0
  42. package/dist/src/types/module.js.map +1 -0
  43. package/dist/src/types/primitive.d.ts +13 -0
  44. package/dist/src/types/primitive.d.ts.map +1 -0
  45. package/dist/src/types/primitive.js +174 -0
  46. package/dist/src/types/primitive.js.map +1 -0
  47. package/dist/typedoc-urls.json +2 -4
  48. package/package.json +103 -16
  49. package/src/fields/array-field.ts +109 -0
  50. package/src/fields/enum-field.ts +30 -0
  51. package/src/fields/field.ts +201 -0
  52. package/src/fields/map-field.ts +107 -0
  53. package/src/fields/message-field.ts +29 -0
  54. package/src/index.ts +6 -1202
  55. package/src/types/enum.ts +112 -0
  56. package/src/types/index.ts +21 -0
  57. package/src/types/message.ts +558 -0
  58. package/src/types/module.ts +234 -0
  59. package/src/types/primitive.ts +215 -0
  60. 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
+ }