feat: Update measurement API to align with lexicon beta.12+#120
Conversation
🦋 Changeset detectedLatest commit: 61fe2cf The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📝 WalkthroughWalkthroughUpdates SDK to lexicon v0.10.0-beta.13: renames evidence→attachment, evolves measurement APIs (Create/UpdateMeasurementParams, required Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client
participant Ops as HypercertOperationsImpl
participant Resolver as resolveToStrongRef
participant Lex as LexiconService
participant Store as ATProtoStore
Client->>Ops: addMeasurement(CreateMeasurementParams)
Ops->>Resolver: resolveToStrongRef(params.subject)
alt subject is string
Resolver->>Lex: fetchRecord(uri)
Lex-->>Resolver: StrongRef (uri + cid)
Resolver-->>Ops: StrongRef
else subject is StrongRef
Resolver-->>Ops: StrongRef
end
Ops->>Ops: processLocations(params.locations)
Ops->>Lex: validate ATTACHMENT & MEASUREMENT schemas
Lex-->>Ops: validation result
Ops->>Store: createRecord(ATTACHMENT / HypercertMeasurement)
Store-->>Ops: CreateResult (uri, cid)
Ops-->>Client: return CreateResult
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/sdk-core/src/repository/HypercertOperationsImpl.ts (1)
1102-1150: Use ATTACHMENT collection constant for createRecord.The code validates and sets
$typewithHYPERCERT_COLLECTIONS.ATTACHMENT, butcreateRecordstill uses the deprecatedHYPERCERT_COLLECTIONS.EVIDENCE. Both currently referenceATTACHMENT_NSID, so the code works, but this inconsistency should be resolved by using the current constant throughout.♻️ Proposed fix
const result = await this.agent.com.atproto.repo.createRecord({ repo: this.repoDid, - collection: HYPERCERT_COLLECTIONS.EVIDENCE, + collection: HYPERCERT_COLLECTIONS.ATTACHMENT, record: evidenceRecord, });
🤖 Fix all issues with AI agents
In `@packages/sdk-core/package.json`:
- Line 91: The package.json entry for dependency "@hypercerts-org/lexicon"
points to non-published version 0.10.0-beta.13; update the dependency to a
published version (e.g., 0.10.0-beta.12 or 0.10.0-beta.11) in package.json or
ensure the project uses the private registry that hosts 0.10.0-beta.13, and then
reconcile code to match the chosen lexicon schema: search for code using lexicon
types/names (imports and usages referencing evidence, subject, content,
relationType, contributors, locations) and either adapt to the older published
schema or apply the breaking-change mappings (evidence → attachment, subject →
subjects array, content → array, remove relationType/contributors/locations) in
functions/classes handling lexicon payloads so runtime and types align with the
selected package version.
In `@packages/sdk-core/src/repository/HypercertOperationsImpl.ts`:
- Around line 1520-1593: Update the addMeasurement JSDoc examples and parameter
descriptions to match the current CreateMeasurementParams and
HypercertMeasurement field names: replace subjectUri with subject (strong ref or
URI per CreateMeasurementParams), methodUri with methodURI, and evidenceUris
with evidenceURI (singular field name used in the measurementRecord), and ensure
other optional fields (locations, measurers, commentFacets) reflect the actual
names used in addMeasurement and HypercertMeasurement; locate these in the
addMeasurement JSDoc block surrounding the addMeasurement function and update
the example payloads and any inline param names to the new identifiers.
In `@packages/sdk-core/src/repository/interfaces.ts`:
- Around line 965-1006: The examples in the addMeasurement JSDoc use outdated
parameter names (subjectUri, methodUri, evidenceUris) that no longer match
CreateMeasurementParams; update both the "Basic measurement" and "Full
measurement" examples to use the current parameter names (subject instead of
subjectUri, methodURI instead of methodUri, and evidenceURI/evidenceURIs as
defined by CreateMeasurementParams) and ensure other fields (unit, value,
locations, measurers, comment, commentFacets) match the type names and casing
used by CreateMeasurementParams so the examples compile and reflect the real API
for the addMeasurement method.
- Around line 230-245: The workScope property currently allows an invalid shape
({ $type: string }) which bypasses compile-time validation; change its type to
the StrongRef type imported from the services types to enforce the proper { uri,
cid, $type } structure—update the import to bring in StrongRef from the services
types module and replace the union on the workScope declaration (the workScope?:
string | { uri: string; cid: string } | { $type: string }; line) with
workScope?: string | StrongRef so the compiler guarantees the correct reference
shape.
In `@packages/sdk-core/src/services/hypercerts/types.ts`:
- Around line 388-446: Update the basic example in the CreateMeasurementParams
docblock to use the correct property name `subject` (not `subjectUri`) to match
the type definition; edit the example object in the comment so it uses `subject:
"at://did:plc:abc/org.hypercerts.claim.activity/xyz"` and keep the rest of the
example fields unchanged to reflect the real `CreateMeasurementParams` shape.
In `@specs/lexicon-sync/v0.10.0-beta.11-v0.10.0-beta.13.md`:
- Around line 90-108: The checklist item referencing "Update
`UpdateMeasurementParams` accordingly ( There is no Update function)" is
ambiguous; either remove this item or reword it to clarify intent — e.g., change
to "Remove/skip UpdateMeasurementParams (no update endpoint exists)" or "Prepare
UpdateMeasurementParams for future update endpoint (no current update
function)"; update the spec text where "UpdateMeasurementParams" and the parent
checklist are listed so readers clearly understand whether an update API is
absent or this is a TODO for a future endpoint.
🧹 Nitpick comments (2)
packages/sdk-core/tests/repository/HypercertValidation.test.ts (1)
8-13: Consider centralizing the workScope test helper.
This helper is duplicated in other tests; a shared utility would reduce drift.packages/sdk-core/src/repository/HypercertOperationsImpl.ts (1)
1035-1100: Add a null guard inresolveToStrongRef.
typeof input === "object"will throw onnullwhen using"uri" in input; a guard keeps error handling consistent.♻️ Proposed fix
- if (typeof input === "object" && "uri" in input && "cid" in input) { + if (input && typeof input === "object" && "uri" in input && "cid" in input) {
2caf565 to
d6c0bf0
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/sdk-react/tests/hooks/useHypercerts.test.tsx (1)
219-236: Remove or replace the complexworkScopeobject structure; it doesn't match the type definition.The
workScopetype definition ininterfaces.tsaccepts onlystring | { uri: string; cid: string } | { $type: string }. The test at lines 223–232 uses an invalid structure withop,args, and nestedatomproperties that don't conform to this type. Use the correct string format (e.g.,"Climate Action"as shown at line 286) or a valid StrongRef object instead.
🤖 Fix all issues with AI agents
In @.changeset/update-measurement-api.md:
- Around line 1-20: Add a short explicit pre-1.0 breaking-change note to the
changeset clarifying that minor version bumps in these 0.x packages can be
breaking; update the changeset text that lists "@hypercerts-org/sdk-core" and
"@hypercerts-org/sdk-react" and the breaking changes (e.g., addMeasurement() →
CreateMeasurementParams, subject replacing hypercertUri, unit required,
measurers optional, methodUri→methodURI, evidenceUris→evidenceURI, removal of
OrgHypercertsDefs) with a single sentence such as “Note: These packages are
pre-1.0; minor version bumps may include breaking changes.” so consumers
immediately see the pre-1.0 expectation.
🧹 Nitpick comments (1)
packages/sdk-core/src/repository/HypercertOperationsImpl.ts (1)
1102-1104: Track the TODO for attachment schema alignment.Can you open a follow‑up issue and link it here?
If you want, I can draft the attachment‑schema migration plan.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/sdk-core/src/index.ts (1)
147-174: ExportHypercertAttachmentfrom the main entrypoint.
types.tsdefinesHypercertAttachment, butindex.tsonly re-exportsHypercertEvidence. Exposing the new alias from the main entrypoint avoids a leaky public surface.📝 Suggested export update
export type { StrongRef, HypercertClaim, HypercertRights, HypercertContributionDetails, HypercertContributorInformation, HypercertContributor, HypercertMeasurement, HypercertEvaluation, HypercertCollection, HypercertCollectionItem, HypercertWorkScopeTag, HypercertLocation, BadgeAward, BadgeDefinition, BadgeResponse, FundingReceipt, // SDK-specific types + HypercertAttachment, HypercertEvidence, HypercertImage, HypercertImageRecord, BlobRef, HypercertWithMetadata, HypercertProject, HypercertProjectWithMetadata, CreateProjectParams, UpdateProjectParams, } from "./services/hypercerts/types.js";As per coding guidelines, ensure all public APIs are exported via the correct entrypoints.
packages/sdk-core/src/repository/HypercertOperationsImpl.ts (1)
1102-1150: Use the non-deprecatedATTACHMENTcollection constant instead ofEVIDENCE.The record is validated as
HYPERCERT_COLLECTIONS.ATTACHMENTand$typeis set toATTACHMENT, butcreateRecordstill uses the deprecatedHYPERCERT_COLLECTIONS.EVIDENCEconstant. While both constants currently resolve to the same value (ATTACHMENT_NSID),EVIDENCEis marked as deprecated since beta.13 and should be replaced. Additionally, the TODO comment indicates the migration to the Attachment Lexicon is incomplete—this change would resolve it.🐛 Proposed fix
const result = await this.agent.com.atproto.repo.createRecord({ repo: this.repoDid, - collection: HYPERCERT_COLLECTIONS.EVIDENCE, + collection: HYPERCERT_COLLECTIONS.ATTACHMENT, record: evidenceRecord, });
🤖 Fix all issues with AI agents
In `@packages/sdk-core/src/services/hypercerts/types.ts`:
- Around line 382-438: Add two missing types for measurements to follow the SDK
convention: declare a MeasurementParams base type that maps to the lexicon Main
record (e.g., aliasing OrgHypercertsClaimMeasurement.Main or a strict SDK-facing
shape) and declare UpdateMeasurementParams as the update variant that mirrors
CreateMeasurementParams but with fields optional/partial for patch semantics
(ensure subject can still accept string | StrongRef and locations can accept
LocationParams[]). Place the new types alongside CreateMeasurementParams so code
that expects Main/SDK/Create/Update/Params for the measurement entity is
satisfied.
🧹 Nitpick comments (2)
packages/sdk-react/tests/testing/mocks.test.ts (1)
174-181: Consider simplifying the type assertion for workScope override.The double assertion
as unknown as typeof hc.workScopeworks but is verbose. SinceUpdateHypercertParams.workScopeacceptsstringdirectly, you could simplify this:it("should allow overriding hypercert properties", () => { const hc = createMockHypercert({ title: "Custom Hypercert", - workScope: "Climate Action" as unknown as typeof hc.workScope, + workScope: "Climate Action", }); expect(hc.title).toBe("Custom Hypercert"); expect(hc.workScope).toBe("Climate Action"); });If TypeScript still complains, the assertion may be needed due to
Hypercert["workScope"]being a stricter type than whatPartial<Hypercert>accepts. In that case, the current approach is acceptable..changeset/update-measurement-api.md (1)
14-14: Consider clarifying whetherevidenceURIstill accepts multiple values.The rename from
evidenceUris(plural) toevidenceURI(singular) could cause confusion about whether the field still accepts an array of URIs or has changed to accept only a single URI. A brief note would help users understand if this is purely a naming change or if the functionality has also changed.
d6c0bf0 to
8977a33
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/sdk-core/src/repository/HypercertOperationsImpl.ts (1)
1124-1144: Filter legacy evidence-only fields before attachment validation.Spreading
...restinto the new attachment record will propagate deprecated fields (e.g., relationType/contributors/locations) and can fail validation for existing callers. Whitelist only attachment-supported fields before validation to preserve backward compatibility.🛠️ Suggested fix (whitelist attachment fields)
- const { subjectUri, content, ...rest } = evidence; + const { subjectUri, content, ...rest } = evidence; + const { + title, + shortDescription, + description, + contentType, + location, + shortDescriptionFacets, + descriptionFacets, + } = rest as Partial<HypercertAttachment>; @@ - const evidenceRecord: HypercertAttachment = { - ...rest, + const evidenceRecord: HypercertAttachment = { + title, + shortDescription, + description, + contentType, + location, + shortDescriptionFacets, + descriptionFacets, $type: HYPERCERT_COLLECTIONS.ATTACHMENT, createdAt, content: [evidenceContent], // content is now an array subjects: [{ uri: subject.uri, cid: subject.cid }], // subject -> subjects array };
🤖 Fix all issues with AI agents
In `@packages/sdk-react/src/types.ts`:
- Around line 316-320: The UpdateHypercertParams.workScope union uses an ad-hoc
object type that allows invalid shapes (e.g., { $type: string })—replace the
inline type with the canonical StrongRef from `@hypercerts-org/sdk-core` to match
core validation. Import StrongRef from "@hypercerts-org/sdk-core" and change the
workScope type to string | StrongRef (update any related references or exports
in the same file), ensuring the type now enforces { uri: string; cid: string }
exactly.
8977a33 to
cd7bdef
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/sdk-core/src/repository/HypercertOperationsImpl.ts`:
- Around line 1664-1671: The updateMeasurement method currently accepts any
collection from the parsed URI and may write measurement-shaped data into
arbitrary collections; update the validation after uriMatch (in
updateMeasurement) to assert the parsed collection equals the measurements
collection name (e.g., "measurement" or the repo's measurement collection
constant) and throw a ValidationError if it does not target the measurement
collection so only URIs targeting measurements are allowed.
🧹 Nitpick comments (1)
packages/sdk-core/src/services/hypercerts/types.ts (1)
388-394: Consider consolidating duplicate type aliases.Both
Measurement(line 394) andHypercertMeasurement(line 151) aliasOrgHypercertsClaimMeasurement.Main. While the grouping in this section is logical, having two identical exports may confuse SDK consumers.Consider either removing
Measurementin favor of the existingHypercertMeasurement, or adding a@seereference to clarify they're equivalent:/** * SDK type for measurement records. * Alias for the lexicon Main type, used in SDK operations. * - * `@see` HypercertMeasurement - Equivalent alias + * `@see` {`@link` HypercertMeasurement} - Identical alias following `Hypercert*` naming convention */ export type Measurement = OrgHypercertsClaimMeasurement.Main;
cd7bdef to
7b6f1f5
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/sdk-core/src/repository/HypercertOperationsImpl.ts (1)
1130-1151: Use the attachment collection when creating attachment records.The record is validated as
HYPERCERT_COLLECTIONS.ATTACHMENT(the current collection), but the write operation usesHYPERCERT_COLLECTIONS.EVIDENCE, which is deprecated in favor ofATTACHMENT(as noted in lexicons.ts). Although both currently resolve to the same NSID, using the deprecated constant misaligns with the schema validation and contradicts the code comment stating "evidence is no longer available in the lexicons." Update the collection to useHYPERCERT_COLLECTIONS.ATTACHMENT.🔧 Suggested fix
const result = await this.agent.com.atproto.repo.createRecord({ repo: this.repoDid, - collection: HYPERCERT_COLLECTIONS.EVIDENCE, + collection: HYPERCERT_COLLECTIONS.ATTACHMENT, record: evidenceRecord, });
🤖 Fix all issues with AI agents
In @.changeset/update-measurement-api.md:
- Around line 18-20: Update the sdk-react workScope bullet to reflect the
current type for UpdateHypercertParams.workScope: replace the invalid `{ $type:
string }` shape with `StrongRef` (or the inline `{ uri: string; cid: string }`)
and document the union as `string | StrongRef` (or `string | { uri; cid }`) so
the bullet matches the actual type used by UpdateHypercertParams.workScope.
7b6f1f5 to
61fe2cf
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/sdk-core/src/repository/HypercertOperationsImpl.ts`:
- Around line 1103-1105: The addEvidence method currently accepts
CreateHypercertEvidenceParams but transforms it to the lexicon's
HypercertAttachment shape (subjects array, content array) as a temporary
compatibility shim; update the API to align with the Attachment lexicon by
changing the method signature and input type to accept HypercertAttachment
directly (or a clearly-named AttachmentInput that matches the lexicon), remove
the internal transformation logic inside addEvidence, and update any
callers/tests to construct subjects and content as arrays to match
HypercertAttachment; ensure function name addEvidence and types
CreateHypercertEvidenceParams and HypercertAttachment are the points of change
so consumers and implementations use the lexicon schema consistently.
🧹 Nitpick comments (1)
packages/sdk-core/src/services/hypercerts/types.ts (1)
12-12: Align UpdateMeasurementParams with the Create/Update pattern while keepingsubjectimmutable.
Guidelines call forUpdate*Params = Partial<Create*Params>; you can preserve immutability by addingsubject?: never. As per coding guidelines, this keeps the convention consistent.♻️ Suggested change
-import type { Except, OverrideProperties, SetOptional } from "type-fest"; +import type { OverrideProperties, SetOptional } from "type-fest"; -export type UpdateMeasurementParams = Partial<Except<CreateMeasurementParams, "subject">>; +export type UpdateMeasurementParams = Partial<CreateMeasurementParams> & { subject?: never };Also applies to: 471-471
Summary
Updates the
addMeasurementAPI to align with the lexicon beta.12+ schema changes, introducing breaking changes to improve measurement handling and add new capabilities.Breaking Changes
addMeasurement()now acceptsCreateMeasurementParamsinstead of individual parameterssubjectfield replaceshypercertUriand accepts both string AT-URIs and StrongRefsunitis now a required field (e.g., "tons CO2e", "hectares", "%")measurersis now optional instead of requiredmethodUri→methodURI,evidenceUris→evidenceURINew Features
locationsarray to specify where measurements were takenstartDateandendDatefor measurement timeframesmethodTypefor short methodology identifierscommentandcommentFacetsfieldsInternal Improvements
resolveToStrongRefutility for handling string/StrongRef conversionsHypercertAttachmentschema (beta.13 compatibility)Test Results
addMeasurementtests to use new API parametersresolveToStrongRefutilityRelated
.changeset/update-measurement-api.mdSummary by CodeRabbit
Breaking Changes
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.