-
Notifications
You must be signed in to change notification settings - Fork 52
docs(api): add creator query normalization docs with before/after examples #238
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,109 @@ | ||||||||||||||||||||||||||||||||||||
| # Creator Query Normalization | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| This document describes how raw query parameters for creator lookup endpoints are | ||||||||||||||||||||||||||||||||||||
| normalized before use. See [`src/utils/public-query-parse.utils.ts`](../../src/utils/public-query-parse.utils.ts) | ||||||||||||||||||||||||||||||||||||
| for the generic Zod-based validation layer that wraps these parameters. | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| ## Overview | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Creator lookup endpoints accept three optional identifier fields. Each field is | ||||||||||||||||||||||||||||||||||||
| read directly from `req.query` by | ||||||||||||||||||||||||||||||||||||
| [`parseCreatorPublicQuery`](../../src/utils/creator-public-query.util.ts) and | ||||||||||||||||||||||||||||||||||||
| forwarded to the service layer as-is. No coercion, trimming, or case-folding is | ||||||||||||||||||||||||||||||||||||
| applied at the utility level — normalization is the caller's responsibility. | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| | Query key | Constant | Typical format | | ||||||||||||||||||||||||||||||||||||
| | :--------------- | :------------------------------------------ | :---------------------- | | ||||||||||||||||||||||||||||||||||||
| | `creatorId` | `CREATOR_PUBLIC_QUERY_KEYS.CREATOR_ID` | UUID v4 string | | ||||||||||||||||||||||||||||||||||||
| | `creatorAddress` | `CREATOR_PUBLIC_QUERY_KEYS.CREATOR_ADDRESS` | Stellar public key (G…) | | ||||||||||||||||||||||||||||||||||||
| | `username` | `CREATOR_PUBLIC_QUERY_KEYS.USERNAME` | Lowercase handle | | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+15
to
+19
|
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| ## Field-by-field rules | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| ### `creatorId` | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Identifies a creator by their internal database UUID. | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| **Rules applied by callers before querying:** | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - Must be a valid UUID v4 (`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`). | ||||||||||||||||||||||||||||||||||||
| - Leading/trailing whitespace should be stripped. | ||||||||||||||||||||||||||||||||||||
| - Case is insignificant for UUID comparison but the stored value is lowercase — | ||||||||||||||||||||||||||||||||||||
| normalize to lowercase before querying. | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| **Before / after examples:** | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| | Raw query string | Normalized value used in query | | ||||||||||||||||||||||||||||||||||||
| | :------------------------ | :----------------------------------- | | ||||||||||||||||||||||||||||||||||||
| | `creatorId=ABC-123` | rejected — not a valid UUID | | ||||||||||||||||||||||||||||||||||||
| | `creatorId= 3f6a1b2c-… ` | `3f6a1b2c-…` (whitespace stripped) | | ||||||||||||||||||||||||||||||||||||
| | `creatorId=3F6A1B2C-…` | `3f6a1b2c-…` (lowercased) | | ||||||||||||||||||||||||||||||||||||
| | `creatorId=3f6a1b2c-…` | `3f6a1b2c-…` (unchanged, valid UUID) | | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+36
to
+41
|
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| ### `creatorAddress` | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Identifies a creator by their linked Stellar public key. | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| **Rules applied by callers before querying:** | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - Must start with `G` and be 56 characters (Stellar ed25519 public key format). | ||||||||||||||||||||||||||||||||||||
| - Leading/trailing whitespace should be stripped. | ||||||||||||||||||||||||||||||||||||
| - Stellar addresses are case-sensitive — do **not** normalize case. | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| **Before / after examples:** | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| | Raw query string | Normalized value used in query | | ||||||||||||||||||||||||||||||||||||
| | :-------------------------- | :---------------------------------------------- | | ||||||||||||||||||||||||||||||||||||
| | `creatorAddress= GABC…XYZ ` | `GABC…XYZ` (whitespace stripped) | | ||||||||||||||||||||||||||||||||||||
| | `creatorAddress=gabc…xyz` | rejected — lowercase Stellar address is invalid | | ||||||||||||||||||||||||||||||||||||
| | `creatorAddress=GABC…XYZ` | `GABC…XYZ` (unchanged, valid address) | | ||||||||||||||||||||||||||||||||||||
| | `creatorAddress=SHORTKEY` | rejected — not 56 characters | | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
Comment on lines
+57
to
+63
|
||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| ### `username` | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Identifies a creator by their public handle. | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| **Rules applied by callers before querying:** | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - Leading/trailing whitespace should be stripped. | ||||||||||||||||||||||||||||||||||||
| - Stored usernames are lowercase — normalize to lowercase before querying so | ||||||||||||||||||||||||||||||||||||
| that `Alice`, `alice`, and `ALICE` all resolve to the same creator. | ||||||||||||||||||||||||||||||||||||
| - Empty string after trimming is treated as absent (no filter applied). | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| **Before / after examples:** | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| | Raw query string | Normalized value used in query | | ||||||||||||||||||||||||||||||||||||
| | :--------------------- | :----------------------------- | | ||||||||||||||||||||||||||||||||||||
| | `username=Alice` | `alice` | | ||||||||||||||||||||||||||||||||||||
| | `username= Alice ` | `alice` (trimmed + lowercased) | | ||||||||||||||||||||||||||||||||||||
| | `username=MUSIC_MAKER` | `music_maker` | | ||||||||||||||||||||||||||||||||||||
| | `username=` | _(parameter ignored)_ | | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
Comment on lines
+79
to
+85
|
||||||||||||||||||||||||||||||||||||
| ## Validation integration | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| These normalization rules are enforced at the route/controller layer using the | ||||||||||||||||||||||||||||||||||||
| `parsePublicQuery` helper from | ||||||||||||||||||||||||||||||||||||
| [`src/utils/public-query-parse.utils.ts`](../../src/utils/public-query-parse.utils.ts). | ||||||||||||||||||||||||||||||||||||
| A Zod schema wraps each field, applies `.trim()` and `.toLowerCase()` transforms | ||||||||||||||||||||||||||||||||||||
| where appropriate, and returns a typed `{ ok: true, data }` result or a | ||||||||||||||||||||||||||||||||||||
| structured `{ ok: false, details }` error array suitable for a `400` response. | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||||||||||||||
| // Example schema used with parsePublicQuery | ||||||||||||||||||||||||||||||||||||
| const creatorLookupSchema = z.object({ | ||||||||||||||||||||||||||||||||||||
| creatorId: z.string().uuid().optional(), | ||||||||||||||||||||||||||||||||||||
| creatorAddress: z.string().length(56).startsWith('G').optional(), | ||||||||||||||||||||||||||||||||||||
| username: z.string().trim().toLowerCase().optional(), | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+98
to
+100
|
||||||||||||||||||||||||||||||||||||
| creatorId: z.string().uuid().optional(), | |
| creatorAddress: z.string().length(56).startsWith('G').optional(), | |
| username: z.string().trim().toLowerCase().optional(), | |
| creatorId: z.string() | |
| .trim() | |
| .toLowerCase() | |
| .pipe(z.string().uuid()) | |
| .optional(), | |
| creatorAddress: z.string() | |
| .trim() | |
| .pipe(z.string().length(56).startsWith('G')) | |
| .optional(), | |
| username: z.string() | |
| .trim() | |
| .toLowerCase() | |
| .transform((value) => (value === '' ? undefined : value)) | |
| .optional(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This states the creator lookup endpoints read
req.queryviaparseCreatorPublicQuery, butparseCreatorPublicQueryis not referenced anywhere insrc/(it’s currently only defined insrc/utils/creator-public-query.util.ts). Either update the docs to describe the actual current call path/schemas that normalize these params, or clarify that this utility (and these query keys) are not wired into any endpoint yet.