Repository navigation
fix(localized): read a record in plain data as its values by locale - #112
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PlainData<T>says thatfromPlainDatacan read a localized field as one value per locale. The runtime did not do that:fromPlainData({ displayName: { en, fr } }).localize("en")stored{ en: { en, fr } }, so the record ended up nested under one locale.localize()call, the record stayed floating, andinsertstored no text.LocalizationModifiernow has afromPlainDataevent handler. When the plain data gives a plain object for a localized field, the handler unlocks that field under"*", so the object is locked as the field's texts by locale.attachModifierregisters the method as an event.insert,updateandtoDatabasecallfromPlainData, so they get the same behaviour.The handler acts only when Localization is the field's last modifier. With
@Localized() @Encrypted(), encryption runs inside the locales. Locking under"*"would then store the cipher triple as locales{0, 1, 2}, and that row could never be read back. Such a field keeps its old behaviour.Release
This is a patch. It makes the runtime match the published
PlainDatatype, and it changes no signature.These callers can see a difference:
fromPlainData,insert,updateortoDatabase. Before, the object was nested under a locale or dropped. Now every locale is stored. Onupdate, the given record replaces the stored texts.ImageValue, given as a single value. Before,fromPlainData({ image: { key, alt } }).localize("en")stored{ en: { key, alt } }. Nowkeyandaltare read as locales.PlainDataalready allows both readings, and this PR picks the one the type documents. The DMS data API builds its write instance itself and does not callfromPlainData, so it is not affected. The one DMSfromPlainDatacall on a localized table (attachments/table-view.ts) runsunlock(…, "*")straight after, so its result does not change.Rows that are already stored do not change. Only new writes that carry a plain object for a localized field store a different shape.
Scope
main: for@Localized() @Encrypted(),fromPlainData(…).localize("en")on a new row throws inModifiersDynamicMetadata.set, for a single text too. That is a separate bug.Related issue
ANT-1973, found by ANT-1912 (dms-saas).
Verification
The new MongoDB suite
src/tests/localized_plain_data.test.tswas run throughajs module test.Before, on
mainwith only the test commit:After:
mainand after the fix. They guard against a handler that also locks a string ornullunder"*", which would throw aTypeErroror clear the field.expected { …(3) } to equal undefined) and passes with it.row_forms,localized_no_key,localized_query_keys,modifiers/localizationandpartial_update. That includes theundefined-key behaviour.pnpm run checks:Checks: 11 passed, 0 failed.flowchart LR P["plain data { displayName: { en, fr } }"] --> A[assign fields] A --> E{fromPlainData event} E -->|"plain object, Localization last"| S["unlock field under '*'"] --> L["lock { en, fr }"] E -->|"text, null, or inner modifier"| F[value floats until localize]Checklist