@protoutil/core
A set of utilities for working with protobuf types. These utilities assume you are using protobuf-es to work with messages.
Install
Section titled “Install”npm install @protoutil/coreEntry Points
Section titled “Entry Points”The package has two entry points:
| Entry Point | Import Path | Contents |
|---|---|---|
| Core | @protoutil/core | CheckSum, Fields, integer validators, error classes |
| Well-Known Types | @protoutil/core/wkt | Duration, FieldMask, Timestamp |
CheckSum
Section titled “CheckSum”The checksum function calculates a non-cryptographic checksum for a given message. Any two messages with identical values produce identical checksums. Internally, this is used for pagination page tokens and ETags in the @protoutil/aip package.
import { checksum } from "@protoutil/core";
const message1 = create(MySchema, { foo: "bar" });const checksum1 = checksum(MySchema, message1);
const message2 = create(MySchema, { foo: "bar" });const checksum2 = checksum(MySchema, message2);
const message3 = create(MySchema, { baz: "quz" });const checksum3 = checksum(MySchema, message3);
checksum1 === checksum2; // truechecksum1 === checksum3; // falseFields
Section titled “Fields”The getField and setField functions get and set field values on a message, with support for oneof fields:
import { getField, setField } from "@protoutil/core";
getField(message, fieldDescriptor); // Gets the value (or returns undefined)setField(message, fieldDescriptor, value); // Sets the valueBoth functions check that the field descriptor belongs to the message’s type and throw an error on mismatch. setField does not validate the value’s type before setting.
Duration
Section titled “Duration”A Duration represents a signed, fixed-length span of time represented as a count of seconds and fractions of seconds at nanosecond resolution.
Import from @protoutil/core/wkt:
import { duration, assertValidDuration, isValidDuration, durationFromString, durationToString, durationFromNanos, durationNanos, clampDuration, durationFromTemporal, durationTemporal,} from "@protoutil/core/wkt";Creating Durations
Section titled “Creating Durations”duration(1n, 1_000_000); // 1.001 secondsduration(315_576_000_001n); // throws — max is +-10,000 yearsValidation
Section titled “Validation”assertValidDuration(d); // throws if invalidisValidDuration(d); // true/falseString Conversion
Section titled “String Conversion”durationFromString("2s"); // Duration message representing 2 secondsdurationToString(d); // "1.001s"Nanosecond Conversion
Section titled “Nanosecond Conversion”durationFromNanos(1_000_000n); // Duration representing 1 milliseconddurationNanos(d); // BigInt nanosecondsClamping
Section titled “Clamping”const min = duration(5n);const max = duration(10n);clampDuration(duration(15n), min, max); // returns maxclampDuration(duration(1n), min, max); // returns minclampDuration(duration(7n), min, max); // returns originalWithout arguments, clampDuration clamps to the protobuf spec range (-315,576,000,000s to +315,576,000,000s).
Temporal API
Section titled “Temporal API”Conversion to/from Temporal.Duration (using temporal-polyfill):
durationFromTemporal(temporalDuration); // Duration messagedurationTemporal(message); // Temporal.DurationTimestamp
Section titled “Timestamp”A Timestamp represents a point in time independent of any time zone or local calendar, encoded as a count of seconds and fractions of seconds at nanosecond resolution.
Range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
Import from @protoutil/core/wkt:
import { timestamp, assertValidTimestamp, isValidTimestamp, timestampFromString, timestampToString, timestampFromNanos, timestampNanos, roundTimestampNanos, clampTimestamp, temporalTimestampNow, timestampFromInstant, timestampInstant,} from "@protoutil/core/wkt";Creating Timestamps
Section titled “Creating Timestamps”timestamp(1n, 1_000_000); // 1.001 seconds after unix epochtimestamp(253402300800n); // throws — max is 9999-12-31T23:59:59.999999999ZValidation
Section titled “Validation”assertValidTimestamp(ts); // throws if invalidisValidTimestamp(ts); // true/falseString Conversion (RFC 3339)
Section titled “String Conversion (RFC 3339)”timestampFromString("1970-01-01T02:07:34.000000321+07:00"); // Timestamp messagetimestampToString(ts); // "1970-01-01T00:00:00.000000000Z"Nanosecond Conversion
Section titled “Nanosecond Conversion”timestampFromNanos(1_000_000n); // 1ms after epochtimestampNanos(ts); // BigInt nanosecondsMath Example
Section titled “Math Example”const epoch = timestampFromNanos(0n);const oneWeek = durationFromString(`${7 * 24 * 60 * 60}s`);const oneWeekLater = timestampFromNanos(timestampNanos(epoch) + durationNanos(oneWeek));timestampToString(oneWeekLater); // "1970-01-08T00:00:00.000Z"Rounding
Section titled “Rounding”Ensure nanos is an integer after calculations:
let ts = create(TimestampSchema, { nanos: 3 / 2 });ts = roundTimestampNanos(ts);assertValidTimestamp(ts); // does not throwClamping
Section titled “Clamping”clampTimestamp(timestamp(15n), min, max); // clamp to rangeWithout arguments, clamps to the protobuf spec range (0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z).
Temporal API
Section titled “Temporal API”temporalTimestampNow(); // Timestamp with nanosecond resolutiontimestampFromInstant(instant); // from Temporal.InstanttimestampInstant(ts); // to Temporal.InstantFieldMask
Section titled “FieldMask”FieldMask represents a set of symbolic field paths used to specify a subset of fields that should be returned by a get operation or modified by an update operation.
Import from @protoutil/core/wkt:
import { fieldMask, assertValidFieldMask, isValidFieldMask, fieldMaskHasPath, applyFieldMask, mergeFieldMasks, intersectFieldMasks,} from "@protoutil/core/wkt";Strict vs Non-Strict Mode
Section titled “Strict vs Non-Strict Mode”All FieldMask functions accept a strict parameter (default: true). In strict mode, only spec-compliant field masks are allowed. Set strict to false to allow wildcards (*) per the AIP Guidelines.
Creating FieldMasks
Section titled “Creating FieldMasks”fieldMask(MySchema, ["my_path", "my_other_path"]);// throws if fields don't exist on MySchemaValidation
Section titled “Validation”assertValidFieldMask(MySchema, fm); // throws if invalidisValidFieldMask(MySchema, fm); // true/falsePath Matching
Section titled “Path Matching”const fm = fieldMask(MySchema, ["a"]);fieldMaskHasPath(fm, "a"); // truefieldMaskHasPath(fm, "b"); // falsefieldMaskHasPath(fm, "a.b"); // true — "a" covers nested fieldsApplying
Section titled “Applying”const fm = fieldMask(MySchema, ["a"]);applyFieldMask(MySchema, message, fm); // only "a" field populatedapplyFieldMask(MySchema, message, fm, { inverse: true }); // everything EXCEPT "a"applyFieldMask does not mutate the original message. Options:
| Option | Default | Description |
|---|---|---|
inverse | false | When true, applies the inverse of the mask |
strict | true | When false, allows wildcards in the mask |
Merging
Section titled “Merging”Combines paths — parent fields subsume their children:
const one = fieldMask(MySchema, ["a"]);const two = fieldMask(MySchema, ["a.b", "c"]);mergeFieldMasks(one, two); // paths: ["a", "c"]Intersecting
Section titled “Intersecting”Returns only paths present in all masks — child paths preferred over parents:
intersectFieldMasks(one, two); // paths: ["a.b"]Integer Validators
Section titled “Integer Validators”Import from @protoutil/core:
| Function | Description |
|---|---|
assertValidInt32(num) | Throws if num is not a 32-bit signed integer |
isValidInt32(num) | Returns true if num is a 32-bit signed integer |
assertValidInt64(num) | Throws if num (BigInt) is not a 64-bit signed integer |
isValidInt64(num) | Returns true if num (BigInt) is a 64-bit signed integer |
assertValidUInt32(num) | Throws if num is not a 32-bit unsigned integer |
isValidUInt32(num) | Returns true if num is a 32-bit unsigned integer |
assertValidUInt64(num) | Throws if num (BigInt) is not a 64-bit unsigned integer |
isValidUInt64(num) | Returns true if num (BigInt) is a 64-bit unsigned integer |
Error Classes
Section titled “Error Classes”Import from @protoutil/core:
| Class | Description |
|---|---|
OutOfRangeError | Indicates a value is out of range. Properties: value, min, max. |
InvalidValueError | Indicates a value is invalid. Properties: value. |
Unit Testing Schemas
Section titled “Unit Testing Schemas”This library exports the Google protobuf unit testing schemas compiled from the protocolbuffers repository. These are useful when testing protobuf-dependent libraries.
// Main test types (proto2)import { TestAllTypesSchema } from "@protoutil/core/unittest";
// Proto3-specific typesimport { TestAllTypes_NestedEnumSchema } from "@protoutil/core/unittest/proto3";Many additional schemas are available under @protoutil/core/unittest/* sub-paths (arena, custom-options, features, lite, etc.). Please explore the repository or file an issue if you need a schema that isn’t exported.