@sachitv/avro-typescript 0.4.1 → 0.5.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.
Files changed (122) hide show
  1. package/esm/avro_reader_sync.d.ts +48 -0
  2. package/esm/avro_reader_sync.js +79 -0
  3. package/esm/avro_writer_sync.d.ts +28 -0
  4. package/esm/avro_writer_sync.js +63 -0
  5. package/esm/internal/collections/circular_buffer.d.ts +4 -3
  6. package/esm/internal/collections/circular_buffer.js +8 -6
  7. package/esm/mod.d.ts +17 -0
  8. package/esm/mod.js +11 -0
  9. package/esm/schemas/base_type.d.ts +8 -0
  10. package/esm/schemas/base_type.js +21 -0
  11. package/esm/schemas/complex/array_type.d.ts +31 -10
  12. package/esm/schemas/complex/array_type.js +129 -39
  13. package/esm/schemas/complex/enum_type.d.ts +24 -7
  14. package/esm/schemas/complex/enum_type.js +61 -15
  15. package/esm/schemas/complex/fixed_type.d.ts +27 -12
  16. package/esm/schemas/complex/fixed_type.js +40 -27
  17. package/esm/schemas/complex/map_type.d.ts +31 -10
  18. package/esm/schemas/complex/map_type.js +88 -47
  19. package/esm/schemas/complex/named_type.d.ts +1 -1
  20. package/esm/schemas/complex/named_type.js +2 -2
  21. package/esm/schemas/complex/record_field.d.ts +62 -0
  22. package/esm/schemas/complex/record_field.js +112 -0
  23. package/esm/schemas/complex/record_resolver.d.ts +45 -0
  24. package/esm/schemas/complex/record_resolver.js +92 -0
  25. package/esm/schemas/complex/record_type.d.ts +45 -70
  26. package/esm/schemas/complex/record_type.js +158 -213
  27. package/esm/schemas/complex/record_writer_cache.d.ts +44 -0
  28. package/esm/schemas/complex/record_writer_cache.js +141 -0
  29. package/esm/schemas/complex/record_writer_strategy.d.ts +123 -0
  30. package/esm/schemas/complex/record_writer_strategy.js +309 -0
  31. package/esm/schemas/complex/union_type.d.ts +23 -11
  32. package/esm/schemas/complex/union_type.js +77 -29
  33. package/esm/schemas/logical/decimal_logical_type.d.ts +1 -1
  34. package/esm/schemas/logical/decimal_logical_type.js +2 -2
  35. package/esm/schemas/logical/duration_logical_type.d.ts +1 -1
  36. package/esm/schemas/logical/duration_logical_type.js +2 -2
  37. package/esm/schemas/logical/logical_type.d.ts +27 -9
  38. package/esm/schemas/logical/logical_type.js +50 -17
  39. package/esm/schemas/logical/temporal_logical_types.d.ts +9 -9
  40. package/esm/schemas/logical/temporal_logical_types.js +18 -18
  41. package/esm/schemas/logical/uuid_logical_type.d.ts +1 -1
  42. package/esm/schemas/logical/uuid_logical_type.js +2 -2
  43. package/esm/schemas/primitive/boolean_type.d.ts +15 -4
  44. package/esm/schemas/primitive/boolean_type.js +22 -7
  45. package/esm/schemas/primitive/bytes_type.d.ts +16 -5
  46. package/esm/schemas/primitive/bytes_type.js +31 -16
  47. package/esm/schemas/primitive/double_type.d.ts +13 -2
  48. package/esm/schemas/primitive/double_type.js +34 -5
  49. package/esm/schemas/primitive/fixed_size_base_type.d.ts +11 -7
  50. package/esm/schemas/primitive/fixed_size_base_type.js +14 -14
  51. package/esm/schemas/primitive/float_type.d.ts +11 -2
  52. package/esm/schemas/primitive/float_type.js +26 -5
  53. package/esm/schemas/primitive/int_type.d.ts +17 -6
  54. package/esm/schemas/primitive/int_type.js +26 -17
  55. package/esm/schemas/primitive/long_type.d.ts +16 -5
  56. package/esm/schemas/primitive/long_type.js +30 -16
  57. package/esm/schemas/primitive/null_type.d.ts +15 -4
  58. package/esm/schemas/primitive/null_type.js +20 -7
  59. package/esm/schemas/primitive/primitive_type.d.ts +2 -0
  60. package/esm/schemas/primitive/primitive_type.js +4 -0
  61. package/esm/schemas/primitive/string_type.d.ts +17 -6
  62. package/esm/schemas/primitive/string_type.js +33 -18
  63. package/esm/schemas/resolver.d.ts +6 -0
  64. package/esm/schemas/type.d.ts +64 -4
  65. package/esm/schemas/type.js +97 -0
  66. package/esm/serialization/avro_file_parser_sync.d.ts +34 -0
  67. package/esm/serialization/avro_file_parser_sync.js +160 -0
  68. package/esm/serialization/avro_file_writer_sync.d.ts +47 -0
  69. package/esm/serialization/avro_file_writer_sync.js +211 -0
  70. package/esm/serialization/buffers/blob_readable_buffer.d.ts +4 -3
  71. package/esm/serialization/buffers/blob_readable_buffer.js +20 -6
  72. package/esm/serialization/buffers/buffer.d.ts +6 -1
  73. package/esm/serialization/buffers/buffer.js +3 -0
  74. package/esm/serialization/buffers/buffer_error.d.ts +28 -0
  75. package/esm/serialization/buffers/buffer_error.js +70 -0
  76. package/esm/serialization/buffers/buffer_sync.d.ts +51 -0
  77. package/esm/serialization/buffers/buffer_sync.js +4 -0
  78. package/esm/serialization/buffers/in_memory_buffer.d.ts +1 -0
  79. package/esm/serialization/buffers/in_memory_buffer.js +7 -5
  80. package/esm/serialization/buffers/in_memory_buffer_sync.d.ts +133 -0
  81. package/esm/serialization/buffers/in_memory_buffer_sync.js +259 -0
  82. package/esm/serialization/counting_writable_tap.d.ts +45 -0
  83. package/esm/serialization/counting_writable_tap.js +90 -0
  84. package/esm/serialization/counting_writable_tap_sync.d.ts +46 -0
  85. package/esm/serialization/counting_writable_tap_sync.js +87 -0
  86. package/esm/serialization/decoders/decoder_null_sync.d.ts +12 -0
  87. package/esm/serialization/decoders/decoder_null_sync.js +13 -0
  88. package/esm/serialization/decoders/decoder_sync.d.ts +15 -0
  89. package/esm/serialization/decoders/decoder_sync.js +1 -0
  90. package/esm/serialization/encoders/encoder_null_sync.d.ts +12 -0
  91. package/esm/serialization/encoders/encoder_null_sync.js +13 -0
  92. package/esm/serialization/encoders/encoder_sync.d.ts +15 -0
  93. package/esm/serialization/encoders/encoder_sync.js +1 -0
  94. package/esm/serialization/streams/fixed_size_stream_readable_buffer_adapter.d.ts +3 -2
  95. package/esm/serialization/streams/fixed_size_stream_readable_buffer_adapter.js +19 -9
  96. package/esm/serialization/streams/fixed_size_stream_reader_sync.d.ts +25 -0
  97. package/esm/serialization/streams/fixed_size_stream_reader_sync.js +63 -0
  98. package/esm/serialization/streams/fixed_size_stream_writer_sync.d.ts +45 -0
  99. package/esm/serialization/streams/fixed_size_stream_writer_sync.js +98 -0
  100. package/esm/serialization/streams/forward_only_stream_readable_buffer_adapter.d.ts +5 -3
  101. package/esm/serialization/streams/forward_only_stream_readable_buffer_adapter.js +18 -8
  102. package/esm/serialization/streams/stream_readable_buffer_adapter.d.ts +3 -2
  103. package/esm/serialization/streams/stream_readable_buffer_adapter.js +19 -6
  104. package/esm/serialization/streams/stream_readable_buffer_adapter_sync.d.ts +36 -0
  105. package/esm/serialization/streams/stream_readable_buffer_adapter_sync.js +93 -0
  106. package/esm/serialization/streams/stream_writable_buffer_adapter_sync.d.ts +45 -0
  107. package/esm/serialization/streams/stream_writable_buffer_adapter_sync.js +78 -0
  108. package/esm/serialization/streams/streams_sync.d.ts +36 -0
  109. package/esm/serialization/streams/streams_sync.js +4 -0
  110. package/esm/serialization/tap.d.ts +15 -32
  111. package/esm/serialization/tap.js +45 -134
  112. package/esm/serialization/tap_sync.d.ts +240 -0
  113. package/esm/serialization/tap_sync.js +545 -0
  114. package/esm/serialization/text_encoding.d.ts +16 -0
  115. package/esm/serialization/text_encoding.js +48 -1
  116. package/esm/type/create_type.d.ts +20 -0
  117. package/esm/type/create_type.js +49 -28
  118. package/package.json +2 -2
  119. package/esm/serialization/manipulate_bytes.d.ts +0 -6
  120. package/esm/serialization/manipulate_bytes.js +0 -13
  121. package/esm/serialization/read_uint_le.d.ts +0 -4
  122. package/esm/serialization/read_uint_le.js +0 -14
@@ -1,28 +1,16 @@
1
1
  import type { ReadableTapLike, WritableTapLike } from "../../serialization/tap.js";
2
2
  import { NamedType } from "./named_type.js";
3
- import { Resolver } from "../resolver.js";
4
- import { type JSONType, Type } from "../type.js";
5
- import { type ErrorHook } from "../error.js";
6
- import { type ResolvedNames } from "./resolve_names.js";
7
- /**
8
- * Specifies the sort order for record fields.
9
- */
10
- export type RecordFieldOrder = "ascending" | "descending" | "ignore";
11
- /**
12
- * Parameters for defining a record field.
13
- */
14
- export interface RecordFieldParams {
15
- /** The name of the field. */
16
- name: string;
17
- /** The type of the field. */
18
- type: Type;
19
- /** Optional aliases for the field. */
20
- aliases?: string[];
21
- /** Optional ordering for the field. */
22
- order?: RecordFieldOrder;
23
- /** Optional default value for the field. */
24
- default?: unknown;
25
- }
3
+ import type { Resolver } from "../resolver.js";
4
+ import type { JSONType, Type } from "../type.js";
5
+ import type { ErrorHook } from "../error.js";
6
+ import type { ResolvedNames } from "./resolve_names.js";
7
+ import type { SyncReadableTapLike, SyncWritableTapLike } from "../../serialization/tap_sync.js";
8
+ export { RecordField, type RecordFieldOrder, type RecordFieldParams, } from "./record_field.js";
9
+ export { type FieldMapping, RecordResolver } from "./record_resolver.js";
10
+ export { type CompiledSyncWriter, type CompiledWriter, CompiledWriterStrategy, defaultWriterStrategy, InterpretedWriterStrategy, type RecordWriterContext, type RecordWriterStrategy, } from "./record_writer_strategy.js";
11
+ export { RecordWriterCache } from "./record_writer_cache.js";
12
+ import { RecordField, type RecordFieldParams } from "./record_field.js";
13
+ import type { RecordWriterStrategy } from "./record_writer_strategy.js";
26
14
  /**
27
15
  * Parameters for creating a RecordType.
28
16
  */
@@ -34,51 +22,26 @@ export interface RecordTypeParams extends ResolvedNames {
34
22
  * types, enabling recursive references to the record.
35
23
  */
36
24
  fields: RecordFieldParams[] | (() => RecordFieldParams[]);
37
- }
38
- /**
39
- * Represents a field in an Avro record type.
40
- */
41
- export declare class RecordField {
42
- #private;
43
- /**
44
- * Constructs a new RecordField instance.
45
- */
46
- constructor(params: RecordFieldParams);
47
- /**
48
- * Gets the name of the field.
49
- */
50
- getName(): string;
51
- /**
52
- * Gets the type of the field.
53
- */
54
- getType(): Type;
55
25
  /**
56
- * Gets the aliases of the field.
26
+ * Whether to validate values during write operations.
27
+ *
28
+ * When set to `false`, record writes may skip runtime type checks in hot
29
+ * paths for performance. This is unsafe for untrusted inputs.
57
30
  */
58
- getAliases(): string[];
31
+ validate?: boolean;
59
32
  /**
60
- * Gets the order of the field.
33
+ * Optional writer strategy for customizing how record writers are compiled.
34
+ *
35
+ * - \`CompiledWriterStrategy\` (default): Inlines primitive tap methods for performance.
36
+ * - \`InterpretedWriterStrategy\`: Delegates to type.write() for simplicity.
37
+ *
38
+ * Custom strategies can be provided for instrumentation, debugging, or
39
+ * alternative compilation approaches.
61
40
  */
62
- getOrder(): RecordFieldOrder;
63
- /**
64
- * Returns true if the field has a default value.
65
- */
66
- hasDefault(): boolean;
67
- /**
68
- * Gets the default value for the field.
69
- * @returns The default value.
70
- * @throws Error if the field has no default.
71
- */
72
- getDefault(): unknown;
73
- /**
74
- * Checks if the given name matches the field name or any of its aliases.
75
- * @param name The name to check.
76
- * @returns True if the name matches, false otherwise.
77
- */
78
- nameMatches(name: string): boolean;
41
+ writerStrategy?: RecordWriterStrategy;
79
42
  }
80
43
  /**
81
- * Avro `record` type supporting ordered fields, aliases, and schema evolution.
44
+ * Avro \`record\` type supporting ordered fields, aliases, and schema evolution.
82
45
  */
83
46
  export declare class RecordType extends NamedType<Record<string, unknown>> {
84
47
  #private;
@@ -87,6 +50,10 @@ export declare class RecordType extends NamedType<Record<string, unknown>> {
87
50
  * @param params The record type parameters.
88
51
  */
89
52
  constructor(params: RecordTypeParams);
53
+ /**
54
+ * Gets the writer strategy used by this record type.
55
+ */
56
+ getWriterStrategy(): RecordWriterStrategy;
90
57
  /**
91
58
  * Gets the fields of the record.
92
59
  */
@@ -104,28 +71,32 @@ export declare class RecordType extends NamedType<Record<string, unknown>> {
104
71
  */
105
72
  check(value: unknown, errorHook?: ErrorHook, path?: string[]): boolean;
106
73
  /**
107
- * Writes the given record value to the tap.
108
- * @param tap The writable tap to write to.
109
- * @param value The record value to write.
74
+ * Writes the record without runtime validation.
75
+ */
76
+ writeUnchecked(tap: WritableTapLike, value: Record<string, unknown>): Promise<void>;
77
+ /**
78
+ * Writes the record synchronously without runtime validation.
110
79
  */
111
- write(tap: WritableTapLike, value: Record<string, unknown>): Promise<void>;
80
+ writeSyncUnchecked(tap: SyncWritableTapLike, value: Record<string, unknown>): void;
112
81
  /**
113
82
  * Reads a record value from the tap.
114
83
  * @param tap The readable tap to read from.
115
84
  * @returns The read record value.
116
85
  */
117
86
  read(tap: ReadableTapLike): Promise<Record<string, unknown>>;
87
+ /**
88
+ * Reads every field synchronously using each field type's sync reader.
89
+ */
90
+ readSync(tap: SyncReadableTapLike): Record<string, unknown>;
118
91
  /**
119
92
  * Skips a record value in the tap.
120
93
  * @param tap The readable tap to skip in.
121
94
  */
122
95
  skip(tap: ReadableTapLike): Promise<void>;
123
96
  /**
124
- * Converts the given record value to a buffer.
125
- * @param value The record value to convert.
126
- * @returns The buffer representation of the value.
97
+ * Skips all fields synchronously without materializing values.
127
98
  */
128
- toBuffer(value: Record<string, unknown>): Promise<ArrayBuffer>;
99
+ skipSync(tap: SyncReadableTapLike): void;
129
100
  /**
130
101
  * Clones a record value, ensuring it conforms to the schema.
131
102
  * @param value The value to clone.
@@ -156,6 +127,10 @@ export declare class RecordType extends NamedType<Record<string, unknown>> {
156
127
  * @returns A comparison result.
157
128
  */
158
129
  match(tap1: ReadableTapLike, tap2: ReadableTapLike): Promise<number>;
130
+ /**
131
+ * Matches two buffers of serialized records synchronously, honoring field order.
132
+ */
133
+ matchSync(tap1: SyncReadableTapLike, tap2: SyncReadableTapLike): number;
159
134
  /**
160
135
  * Creates a resolver for schema evolution from the writer type to this reader type.
161
136
  * @param writerType The writer type to resolve from.
@@ -1,120 +1,27 @@
1
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
- };
6
1
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
7
2
  if (kind === "m") throw new TypeError("Private method is not writable");
8
3
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
9
4
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
5
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
6
  };
12
- var _a, _RecordField_name, _RecordField_type, _RecordField_aliases, _RecordField_order, _RecordField_hasDefault, _RecordField_defaultValue, _RecordField_isValidOrder, _RecordType_instances, _RecordType_fields, _RecordType_fieldNameToIndex, _RecordType_fieldsThunk, _RecordType_ensureFields, _RecordType_setFields, _RecordType_getOrderValue, _RecordType_isRecord, _RecordType_extractFieldValue, _RecordType_checkField, _RecordType_writeField, _RecordType_getFieldBuffer, _RecordType_cloneField, _RecordType_getComparableValue, _RecordResolver_mappings, _RecordResolver_readerFields;
13
- import { NamedType } from "./named_type.js";
14
- import { Resolver } from "../resolver.js";
15
- import { Type } from "../type.js";
16
- import { throwInvalidError } from "../error.js";
17
- import { isValidName } from "./resolve_names.js";
18
- /**
19
- * Represents a field in an Avro record type.
20
- */
21
- export class RecordField {
22
- /**
23
- * Constructs a new RecordField instance.
24
- */
25
- constructor(params) {
26
- _RecordField_name.set(this, void 0);
27
- _RecordField_type.set(this, void 0);
28
- _RecordField_aliases.set(this, void 0);
29
- _RecordField_order.set(this, void 0);
30
- _RecordField_hasDefault.set(this, void 0);
31
- _RecordField_defaultValue.set(this, void 0);
32
- const { name, type, aliases = [], order = "ascending" } = params;
33
- if (typeof name !== "string" || !isValidName(name)) {
34
- throw new Error(`Invalid record field name: ${name}`);
35
- }
36
- if (!(type instanceof Type)) {
37
- throw new Error(`Invalid field type for ${name}`);
38
- }
39
- if (!__classPrivateFieldGet(_a, _a, "m", _RecordField_isValidOrder).call(_a, order)) {
40
- throw new Error(`Invalid record field order: ${order}`);
41
- }
42
- __classPrivateFieldSet(this, _RecordField_name, name, "f");
43
- __classPrivateFieldSet(this, _RecordField_type, type, "f");
44
- __classPrivateFieldSet(this, _RecordField_order, order, "f");
45
- const aliasSet = new Set();
46
- const resolvedAliases = [];
47
- for (const alias of aliases) {
48
- if (typeof alias !== "string" || !isValidName(alias)) {
49
- throw new Error(`Invalid record field alias: ${alias}`);
50
- }
51
- if (!aliasSet.has(alias)) {
52
- aliasSet.add(alias);
53
- resolvedAliases.push(alias);
54
- }
55
- }
56
- __classPrivateFieldSet(this, _RecordField_aliases, resolvedAliases, "f");
57
- __classPrivateFieldSet(this, _RecordField_hasDefault, Object.prototype.hasOwnProperty.call(params, "default"), "f");
58
- if (__classPrivateFieldGet(this, _RecordField_hasDefault, "f")) {
59
- __classPrivateFieldSet(this, _RecordField_defaultValue, __classPrivateFieldGet(this, _RecordField_type, "f").cloneFromValue(params.default), "f");
60
- }
61
- }
62
- /**
63
- * Gets the name of the field.
64
- */
65
- getName() {
66
- return __classPrivateFieldGet(this, _RecordField_name, "f");
67
- }
68
- /**
69
- * Gets the type of the field.
70
- */
71
- getType() {
72
- return __classPrivateFieldGet(this, _RecordField_type, "f");
73
- }
74
- /**
75
- * Gets the aliases of the field.
76
- */
77
- getAliases() {
78
- return __classPrivateFieldGet(this, _RecordField_aliases, "f").slice();
79
- }
80
- /**
81
- * Gets the order of the field.
82
- */
83
- getOrder() {
84
- return __classPrivateFieldGet(this, _RecordField_order, "f");
85
- }
86
- /**
87
- * Returns true if the field has a default value.
88
- */
89
- hasDefault() {
90
- return __classPrivateFieldGet(this, _RecordField_hasDefault, "f");
91
- }
92
- /**
93
- * Gets the default value for the field.
94
- * @returns The default value.
95
- * @throws Error if the field has no default.
96
- */
97
- getDefault() {
98
- if (!__classPrivateFieldGet(this, _RecordField_hasDefault, "f")) {
99
- throw new Error(`Field '${__classPrivateFieldGet(this, _RecordField_name, "f")}' has no default.`);
100
- }
101
- return __classPrivateFieldGet(this, _RecordField_type, "f").cloneFromValue(__classPrivateFieldGet(this, _RecordField_defaultValue, "f"));
102
- }
103
- /**
104
- * Checks if the given name matches the field name or any of its aliases.
105
- * @param name The name to check.
106
- * @returns True if the name matches, false otherwise.
107
- */
108
- nameMatches(name) {
109
- return name === __classPrivateFieldGet(this, _RecordField_name, "f") || __classPrivateFieldGet(this, _RecordField_aliases, "f").includes(name);
110
- }
111
- }
112
- _a = RecordField, _RecordField_name = new WeakMap(), _RecordField_type = new WeakMap(), _RecordField_aliases = new WeakMap(), _RecordField_order = new WeakMap(), _RecordField_hasDefault = new WeakMap(), _RecordField_defaultValue = new WeakMap(), _RecordField_isValidOrder = function _RecordField_isValidOrder(order) {
113
- return order === "ascending" || order === "descending" ||
114
- order === "ignore";
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
115
11
  };
12
+ var _RecordType_instances, _a, _RecordType_fields, _RecordType_fieldNameToIndex, _RecordType_fieldsThunk, _RecordType_writerCache, _RecordType_fieldNames, _RecordType_fieldTypes, _RecordType_fieldHasDefault, _RecordType_fieldDefaultGetters, _RecordType_getOrCreateCompiledWriter, _RecordType_getOrCreateCompiledSyncWriter, _RecordType_ensureFields, _RecordType_setFields, _RecordType_getOrderValue, _RecordType_isRecord, _RecordType_checkField, _RecordType_cloneField, _RecordType_getComparableValue;
13
+ import { NamedType } from "./named_type.js";
14
+ // Re-export extracted modules for backward compatibility
15
+ export { RecordField, } from "./record_field.js";
16
+ export { RecordResolver } from "./record_resolver.js";
17
+ export { CompiledWriterStrategy, defaultWriterStrategy, InterpretedWriterStrategy, } from "./record_writer_strategy.js";
18
+ export { RecordWriterCache } from "./record_writer_cache.js";
19
+ import { RecordField, } from "./record_field.js";
20
+ import { RecordResolver } from "./record_resolver.js";
21
+ import { defaultWriterStrategy } from "./record_writer_strategy.js";
22
+ import { RecordWriterCache } from "./record_writer_cache.js";
116
23
  /**
117
- * Avro `record` type supporting ordered fields, aliases, and schema evolution.
24
+ * Avro \`record\` type supporting ordered fields, aliases, and schema evolution.
118
25
  */
119
26
  export class RecordType extends NamedType {
120
27
  /**
@@ -122,14 +29,24 @@ export class RecordType extends NamedType {
122
29
  * @param params The record type parameters.
123
30
  */
124
31
  constructor(params) {
125
- const { fields, ...names } = params;
126
- super(names);
32
+ const { fields, validate, writerStrategy, ...names } = params;
33
+ super(names, validate ?? true);
127
34
  _RecordType_instances.add(this);
128
35
  _RecordType_fields.set(this, void 0);
129
36
  _RecordType_fieldNameToIndex.set(this, void 0);
130
37
  _RecordType_fieldsThunk.set(this, void 0);
38
+ _RecordType_writerCache.set(this, void 0);
39
+ _RecordType_fieldNames.set(this, void 0);
40
+ _RecordType_fieldTypes.set(this, void 0);
41
+ _RecordType_fieldHasDefault.set(this, void 0);
42
+ _RecordType_fieldDefaultGetters.set(this, void 0);
131
43
  __classPrivateFieldSet(this, _RecordType_fields, [], "f");
132
44
  __classPrivateFieldSet(this, _RecordType_fieldNameToIndex, new Map(), "f");
45
+ __classPrivateFieldSet(this, _RecordType_fieldNames, [], "f");
46
+ __classPrivateFieldSet(this, _RecordType_fieldTypes, [], "f");
47
+ __classPrivateFieldSet(this, _RecordType_fieldHasDefault, [], "f");
48
+ __classPrivateFieldSet(this, _RecordType_fieldDefaultGetters, [], "f");
49
+ __classPrivateFieldSet(this, _RecordType_writerCache, new RecordWriterCache(writerStrategy ?? defaultWriterStrategy), "f");
133
50
  if (typeof fields === "function") {
134
51
  // Defer field materialization until the first time the record is used.
135
52
  // This mirrors the classic Avro parsing strategy where named types are
@@ -140,6 +57,12 @@ export class RecordType extends NamedType {
140
57
  __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_setFields).call(this, fields);
141
58
  }
142
59
  }
60
+ /**
61
+ * Gets the writer strategy used by this record type.
62
+ */
63
+ getWriterStrategy() {
64
+ return __classPrivateFieldGet(this, _RecordType_writerCache, "f").getStrategy();
65
+ }
143
66
  /**
144
67
  * Gets the fields of the record.
145
68
  */
@@ -182,18 +105,20 @@ export class RecordType extends NamedType {
182
105
  return true;
183
106
  }
184
107
  /**
185
- * Writes the given record value to the tap.
186
- * @param tap The writable tap to write to.
187
- * @param value The record value to write.
108
+ * Writes the record without runtime validation.
188
109
  */
189
- async write(tap, value) {
110
+ async writeUnchecked(tap, value) {
190
111
  __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_ensureFields).call(this);
191
- if (!__classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_isRecord).call(this, value)) {
192
- throwInvalidError([], value, this);
193
- }
194
- for (const field of __classPrivateFieldGet(this, _RecordType_fields, "f")) {
195
- await __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_writeField).call(this, field, value, tap);
196
- }
112
+ const writer = __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_getOrCreateCompiledWriter).call(this, false);
113
+ await writer(tap, value);
114
+ }
115
+ /**
116
+ * Writes the record synchronously without runtime validation.
117
+ */
118
+ writeSyncUnchecked(tap, value) {
119
+ __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_ensureFields).call(this);
120
+ const writer = __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_getOrCreateCompiledSyncWriter).call(this, false);
121
+ writer(tap, value);
197
122
  }
198
123
  /**
199
124
  * Reads a record value from the tap.
@@ -208,6 +133,17 @@ export class RecordType extends NamedType {
208
133
  }
209
134
  return result;
210
135
  }
136
+ /**
137
+ * Reads every field synchronously using each field type's sync reader.
138
+ */
139
+ readSync(tap) {
140
+ __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_ensureFields).call(this);
141
+ const result = {};
142
+ for (const field of __classPrivateFieldGet(this, _RecordType_fields, "f")) {
143
+ result[field.getName()] = field.getType().readSync(tap);
144
+ }
145
+ return result;
146
+ }
211
147
  /**
212
148
  * Skips a record value in the tap.
213
149
  * @param tap The readable tap to skip in.
@@ -219,27 +155,13 @@ export class RecordType extends NamedType {
219
155
  }
220
156
  }
221
157
  /**
222
- * Converts the given record value to a buffer.
223
- * @param value The record value to convert.
224
- * @returns The buffer representation of the value.
158
+ * Skips all fields synchronously without materializing values.
225
159
  */
226
- async toBuffer(value) {
160
+ skipSync(tap) {
227
161
  __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_ensureFields).call(this);
228
- if (!__classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_isRecord).call(this, value)) {
229
- throwInvalidError([], value, this);
230
- }
231
- const buffers = [];
232
162
  for (const field of __classPrivateFieldGet(this, _RecordType_fields, "f")) {
233
- buffers.push(await __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_getFieldBuffer).call(this, field, value));
163
+ field.getType().skipSync(tap);
234
164
  }
235
- const totalSize = buffers.reduce((sum, buf) => sum + buf.byteLength, 0);
236
- const combined = new Uint8Array(totalSize);
237
- let offset = 0;
238
- for (const buf of buffers) {
239
- combined.set(buf, offset);
240
- offset += buf.byteLength;
241
- }
242
- return combined.buffer;
243
165
  }
244
166
  /**
245
167
  * Clones a record value, ensuring it conforms to the schema.
@@ -351,6 +273,27 @@ export class RecordType extends NamedType {
351
273
  }
352
274
  return 0;
353
275
  }
276
+ /**
277
+ * Matches two buffers of serialized records synchronously, honoring field order.
278
+ */
279
+ matchSync(tap1, tap2) {
280
+ __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_ensureFields).call(this);
281
+ for (const field of __classPrivateFieldGet(this, _RecordType_fields, "f")) {
282
+ const order = __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_getOrderValue).call(this, field.getOrder());
283
+ const type = field.getType();
284
+ if (order !== 0) {
285
+ const result = type.matchSync(tap1, tap2) * order;
286
+ if (result !== 0) {
287
+ return result;
288
+ }
289
+ }
290
+ else {
291
+ type.skipSync(tap1);
292
+ type.skipSync(tap2);
293
+ }
294
+ }
295
+ return 0;
296
+ }
354
297
  /**
355
298
  * Creates a resolver for schema evolution from the writer type to this reader type.
356
299
  * @param writerType The writer type to resolve from.
@@ -358,7 +301,7 @@ export class RecordType extends NamedType {
358
301
  */
359
302
  createResolver(writerType) {
360
303
  __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_ensureFields).call(this);
361
- if (!(writerType instanceof RecordType)) {
304
+ if (!(writerType instanceof _a)) {
362
305
  return super.createResolver(writerType);
363
306
  }
364
307
  const acceptableNames = new Set([
@@ -402,10 +345,10 @@ export class RecordType extends NamedType {
402
345
  }
403
346
  const readerField = readerFields[readerIndex];
404
347
  const readerType = readerField.getType();
405
- const writerType = writerField.getType();
406
- const resolver = readerType === writerType
348
+ const writerFieldType = writerField.getType();
349
+ const resolver = readerType === writerFieldType
407
350
  ? undefined
408
- : readerType.createResolver(writerType);
351
+ : readerType.createResolver(writerFieldType);
409
352
  mappings.push({
410
353
  readerIndex,
411
354
  writerField,
@@ -421,7 +364,49 @@ export class RecordType extends NamedType {
421
364
  return new RecordResolver(this, mappings, readerFields);
422
365
  }
423
366
  }
424
- _RecordType_fields = new WeakMap(), _RecordType_fieldNameToIndex = new WeakMap(), _RecordType_fieldsThunk = new WeakMap(), _RecordType_instances = new WeakSet(), _RecordType_ensureFields = function _RecordType_ensureFields() {
367
+ _a = RecordType, _RecordType_fields = new WeakMap(), _RecordType_fieldNameToIndex = new WeakMap(), _RecordType_fieldsThunk = new WeakMap(), _RecordType_writerCache = new WeakMap(), _RecordType_fieldNames = new WeakMap(), _RecordType_fieldTypes = new WeakMap(), _RecordType_fieldHasDefault = new WeakMap(), _RecordType_fieldDefaultGetters = new WeakMap(), _RecordType_instances = new WeakSet(), _RecordType_getOrCreateCompiledWriter = function _RecordType_getOrCreateCompiledWriter(validate) {
368
+ __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_ensureFields).call(this);
369
+ return __classPrivateFieldGet(this, _RecordType_writerCache, "f").getOrCreateWriter(validate, {
370
+ fieldNames: __classPrivateFieldGet(this, _RecordType_fieldNames, "f"),
371
+ fieldTypes: __classPrivateFieldGet(this, _RecordType_fieldTypes, "f"),
372
+ fieldDefaultGetters: __classPrivateFieldGet(this, _RecordType_fieldDefaultGetters, "f"),
373
+ fieldHasDefault: __classPrivateFieldGet(this, _RecordType_fieldHasDefault, "f"),
374
+ validate,
375
+ recordType: this,
376
+ isRecord: __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_isRecord).bind(this),
377
+ }, (type, shouldValidate) => {
378
+ if (type instanceof _a) {
379
+ return __classPrivateFieldGet(type, _RecordType_instances, "m", _RecordType_getOrCreateCompiledWriter).call(type, shouldValidate);
380
+ }
381
+ return (tap, value) => {
382
+ if (shouldValidate) {
383
+ return type.write(tap, value);
384
+ }
385
+ return type.writeUnchecked(tap, value);
386
+ };
387
+ });
388
+ }, _RecordType_getOrCreateCompiledSyncWriter = function _RecordType_getOrCreateCompiledSyncWriter(validate) {
389
+ __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_ensureFields).call(this);
390
+ return __classPrivateFieldGet(this, _RecordType_writerCache, "f").getOrCreateSyncWriter(validate, {
391
+ fieldNames: __classPrivateFieldGet(this, _RecordType_fieldNames, "f"),
392
+ fieldTypes: __classPrivateFieldGet(this, _RecordType_fieldTypes, "f"),
393
+ fieldDefaultGetters: __classPrivateFieldGet(this, _RecordType_fieldDefaultGetters, "f"),
394
+ fieldHasDefault: __classPrivateFieldGet(this, _RecordType_fieldHasDefault, "f"),
395
+ validate,
396
+ recordType: this,
397
+ isRecord: __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_isRecord).bind(this),
398
+ }, (type, shouldValidate) => {
399
+ if (type instanceof _a) {
400
+ return __classPrivateFieldGet(type, _RecordType_instances, "m", _RecordType_getOrCreateCompiledSyncWriter).call(type, shouldValidate);
401
+ }
402
+ return (tap, value) => {
403
+ if (shouldValidate) {
404
+ return type.writeSync(tap, value);
405
+ }
406
+ return type.writeSyncUnchecked(tap, value);
407
+ };
408
+ });
409
+ }, _RecordType_ensureFields = function _RecordType_ensureFields() {
425
410
  if (__classPrivateFieldGet(this, _RecordType_fieldsThunk, "f")) {
426
411
  const builder = __classPrivateFieldGet(this, _RecordType_fieldsThunk, "f");
427
412
  __classPrivateFieldSet(this, _RecordType_fieldsThunk, undefined, "f");
@@ -434,12 +419,24 @@ _RecordType_fields = new WeakMap(), _RecordType_fieldNameToIndex = new WeakMap()
434
419
  }
435
420
  __classPrivateFieldSet(this, _RecordType_fields, [], "f");
436
421
  __classPrivateFieldGet(this, _RecordType_fieldNameToIndex, "f").clear();
422
+ __classPrivateFieldSet(this, _RecordType_fieldNames, [], "f");
423
+ __classPrivateFieldSet(this, _RecordType_fieldTypes, [], "f");
424
+ __classPrivateFieldSet(this, _RecordType_fieldHasDefault, [], "f");
425
+ __classPrivateFieldSet(this, _RecordType_fieldDefaultGetters, [], "f");
426
+ __classPrivateFieldGet(this, _RecordType_writerCache, "f").clear();
437
427
  candidate.forEach((fieldParams) => {
438
428
  const field = new RecordField(fieldParams);
439
- if (__classPrivateFieldGet(this, _RecordType_fieldNameToIndex, "f").has(field.getName())) {
440
- throw new Error(`Duplicate record field name: ${field.getName()}`);
441
- }
442
- __classPrivateFieldGet(this, _RecordType_fieldNameToIndex, "f").set(field.getName(), __classPrivateFieldGet(this, _RecordType_fields, "f").length);
429
+ const name = field.getName();
430
+ if (__classPrivateFieldGet(this, _RecordType_fieldNameToIndex, "f").has(name)) {
431
+ throw new Error(`Duplicate record field name: \`${name}\``);
432
+ }
433
+ const type = field.getType();
434
+ const hasDefault = field.hasDefault();
435
+ __classPrivateFieldGet(this, _RecordType_fieldNameToIndex, "f").set(name, __classPrivateFieldGet(this, _RecordType_fields, "f").length);
436
+ __classPrivateFieldGet(this, _RecordType_fieldNames, "f").push(name);
437
+ __classPrivateFieldGet(this, _RecordType_fieldTypes, "f").push(type);
438
+ __classPrivateFieldGet(this, _RecordType_fieldHasDefault, "f").push(hasDefault);
439
+ __classPrivateFieldGet(this, _RecordType_fieldDefaultGetters, "f").push(hasDefault ? () => field.getDefault() : undefined);
443
440
  __classPrivateFieldGet(this, _RecordType_fields, "f").push(field);
444
441
  });
445
442
  }, _RecordType_getOrderValue = function _RecordType_getOrderValue(order) {
@@ -453,95 +450,43 @@ _RecordType_fields = new WeakMap(), _RecordType_fieldNameToIndex = new WeakMap()
453
450
  }
454
451
  }, _RecordType_isRecord = function _RecordType_isRecord(value) {
455
452
  return typeof value === "object" && value !== null && !Array.isArray(value);
456
- }, _RecordType_extractFieldValue = function _RecordType_extractFieldValue(record, field) {
453
+ }, _RecordType_checkField = function _RecordType_checkField(field, record, errorHook, path) {
457
454
  const name = field.getName();
458
455
  const hasValue = Object.hasOwn(record, name);
459
- const fieldValue = hasValue ? record[name] : undefined;
460
- return { hasValue, fieldValue };
461
- }, _RecordType_checkField = function _RecordType_checkField(field, record, errorHook, path) {
462
- const { hasValue, fieldValue } = __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_extractFieldValue).call(this, record, field);
463
456
  if (!hasValue) {
464
457
  if (!field.hasDefault()) {
465
458
  if (errorHook) {
466
- errorHook([...path, field.getName()], undefined, this);
459
+ errorHook([...path, name], undefined, this);
467
460
  }
468
461
  return false;
469
462
  }
470
463
  return true;
471
464
  }
472
- const nextPath = errorHook ? [...path, field.getName()] : undefined;
465
+ const fieldValue = record[name];
466
+ const nextPath = errorHook ? [...path, name] : undefined;
473
467
  const valid = field.getType().check(fieldValue, errorHook, nextPath);
474
468
  return valid || (errorHook !== undefined);
475
- }, _RecordType_writeField = async function _RecordType_writeField(field, record, tap) {
476
- const { hasValue, fieldValue } = __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_extractFieldValue).call(this, record, field);
477
- let toWrite = fieldValue;
478
- if (!hasValue) {
479
- if (!field.hasDefault()) {
480
- throwInvalidError([field.getName()], undefined, this);
481
- }
482
- toWrite = field.getDefault();
483
- }
484
- await field.getType().write(tap, toWrite);
485
- }, _RecordType_getFieldBuffer = async function _RecordType_getFieldBuffer(field, record) {
486
- const { hasValue, fieldValue } = __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_extractFieldValue).call(this, record, field);
487
- let toEncode = fieldValue;
488
- if (!hasValue) {
489
- if (!field.hasDefault()) {
490
- throwInvalidError([field.getName()], undefined, this);
491
- }
492
- toEncode = field.getDefault();
493
- }
494
- return new Uint8Array(await field.getType().toBuffer(toEncode));
495
469
  }, _RecordType_cloneField = function _RecordType_cloneField(field, record, result) {
496
- const { hasValue, fieldValue } = __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_extractFieldValue).call(this, record, field);
470
+ const name = field.getName();
471
+ const hasValue = Object.hasOwn(record, name);
472
+ const fieldValue = hasValue ? record[name] : undefined;
497
473
  if (!hasValue) {
498
474
  if (!field.hasDefault()) {
499
- throw new Error(`Missing value for record field ${field.getName()} with no default.`);
475
+ throw new Error(`Missing value for record field ${name} with no default.`);
500
476
  }
501
- result[field.getName()] = field.getDefault();
477
+ result[name] = field.getDefault();
502
478
  return;
503
479
  }
504
- result[field.getName()] = field.getType().cloneFromValue(fieldValue);
480
+ result[name] = field.getType().cloneFromValue(fieldValue);
505
481
  }, _RecordType_getComparableValue = function _RecordType_getComparableValue(record, field) {
506
- const { hasValue, fieldValue } = __classPrivateFieldGet(this, _RecordType_instances, "m", _RecordType_extractFieldValue).call(this, record, field);
482
+ const name = field.getName();
483
+ const hasValue = Object.hasOwn(record, name);
484
+ const fieldValue = hasValue ? record[name] : undefined;
507
485
  if (hasValue) {
508
486
  return fieldValue;
509
487
  }
510
488
  if (field.hasDefault()) {
511
489
  return field.getDefault();
512
490
  }
513
- throw new Error(`Missing comparable value for field '${field.getName()}' with no default.`);
491
+ throw new Error(`Missing comparable value for field '${name}' with no default.`);
514
492
  };
515
- class RecordResolver extends Resolver {
516
- constructor(reader, mappings, readerFields) {
517
- super(reader);
518
- _RecordResolver_mappings.set(this, void 0);
519
- _RecordResolver_readerFields.set(this, void 0);
520
- __classPrivateFieldSet(this, _RecordResolver_mappings, mappings, "f");
521
- __classPrivateFieldSet(this, _RecordResolver_readerFields, readerFields, "f");
522
- }
523
- async read(tap) {
524
- const result = {};
525
- const seen = new Array(__classPrivateFieldGet(this, _RecordResolver_readerFields, "f").length).fill(false);
526
- for (const mapping of __classPrivateFieldGet(this, _RecordResolver_mappings, "f")) {
527
- if (mapping.readerIndex === -1) {
528
- await mapping.writerField.getType().skip(tap);
529
- continue;
530
- }
531
- const value = mapping.resolver
532
- ? await mapping.resolver.read(tap)
533
- : await mapping.writerField.getType().read(tap);
534
- const readerField = __classPrivateFieldGet(this, _RecordResolver_readerFields, "f")[mapping.readerIndex];
535
- result[readerField.getName()] = value;
536
- seen[mapping.readerIndex] = true;
537
- }
538
- for (let i = 0; i < __classPrivateFieldGet(this, _RecordResolver_readerFields, "f").length; i++) {
539
- if (!seen[i]) {
540
- const field = __classPrivateFieldGet(this, _RecordResolver_readerFields, "f")[i];
541
- result[field.getName()] = field.getDefault();
542
- }
543
- }
544
- return result;
545
- }
546
- }
547
- _RecordResolver_mappings = new WeakMap(), _RecordResolver_readerFields = new WeakMap();