Skip to content

feat(casing): snake/wire surface parity across params, bodies, presentation and columns (#131); hyphenated wire names alias cleanly (#119) - #140

Open
jeffreyaven wants to merge 1 commit into
mainfrom
feat/casing-surface-131-119
Open

feat(casing): snake/wire surface parity across params, bodies, presentation and columns (#131); hyphenated wire names alias cleanly (#119)#140
jeffreyaven wants to merge 1 commit into
mainfrom
feat/casing-surface-131-119

Conversation

@jeffreyaven

Copy link
Copy Markdown
Member

Closes #131. Closes #119.

Every change is gated on provider doc config (request.nativeCasing on the
method, config.snake_case_aliases on the provider). Resolution is wire-first
on every surface: the key as written matches first, the snake alias second, and
no wire spelling is removed from any resolvable set. Absent both flags every
path is byte-identical.

#119 - hyphenated wire names

casing.ToSnake now treats - as a word boundary, transforming each segment
with the existing botocore rules: openai-organization -> openai_organization,
OpenAI-Organization -> open_ai_organization, X-Amz-Date -> x_amz_date.
Non-hyphenated names are unchanged (VPCId -> vpc_id, training_file ->
identity). FromSnake(_, kebab) was already the correct inverse.

#131

item change
1. column surface Schema.GetProperty and FindByPath accept the snake alias of a wire property when snake_case_aliases is on (wire-first), so snake projections resolve their property schema.
2. acronym round-trip GetParameter, parameterMatch, namespaceParameterMatch and GetOperationParameter resolve a snake key through the declared wire names (ToSnake-derived alias map) before the mechanical FromSnake fallback, so ip_protocol -> IPProtocol, binary_id -> BinaryId. GetParametersIncludingNativeCasing aliases data__ body keys with the prefix kept.
3. default data__ regime revertRequestBodyAttributeRename maps a snake body key to its wire property when the method declares nativeCasing, so data__storage_class and data__storageClass both send {"storageClass": ...}. Unknown keys pass through as today (an error here would break free-form bodies).
4. presentation RenameRequestBodyAttribute (SHOW INSERT) and ToPresentationMap (SHOW METHODS) present snake names only when the method declares nativeCasing and the provider enables snake_case_aliases; nested body contents and server variables keep wire casing. The unexported rename used for resolution is unchanged, so GetParameters() keeps the wire keys.
5. body-less EXEC GetRequestBodySchema returns nil, nil when no body schema is declared, so a metadata-only request block on a body-less method no longer fails before dispatch. The internal body-attribute accessors keep their error contract, which preserves routing exactly (they previously short-circuited before required server variables were added).

Verification

  • go build ./..., go test ./... (21 packages), gofmt on changed hunks, lint
    clean on changed lines. New tests: pkg/casing hyphen cases and
    internal/anysdk/casing_alias_resolution_test.go (one test per item, each
    asserting the wire spelling still resolves and the flag-off path is unchanged).
  • End-to-end: stackql built against this branch vs v0.5.4-alpha01, local file
    registry provider with snake_case_aliases: true and per-method
    nativeCasing, mock logging method/path/query/header/body:
statement v0.5.4-alpha01 this branch
WHERE openai_organization = 'org-x' (kebab header) could not locate symbol header openai-organization: org-x on the wire
INSERT ... (data__name, data__storage_class) body {"storage_class": ...} (silently ignored by an API) body {"storageClass": ...}
INSERT ... (data__name, data__storageClass) {"storageClass": ...} unchanged
EXEC ...stop @machineId (body-less, request: {nativeCasing}) no request body for operation dispatched POST /machines/m1/stop
SHOW METHODS (stop) machineId machine_id
SHOW INSERT data__storageClass data__storage_class
WHERE max_results = 2 / WHERE maxResults = 2 ?maxResults=2 unchanged
SELECT machine_type, creation_timestamp, ip_protocol rows unchanged

Remaining in stackql (wire-through)

Two acceptance points in #131 sit in stackql's own layers and are unchanged by
this PR; both now have the any-sdk primitives they need:

  • Wire-spelled column under the flag (SELECT machineType with
    snake_case_aliases): still no such column: machineType from the SQL
    backend. unary_selection.go builds the column descriptor from the SQL
    identifier; with FindByPath now alias-aware it can rename the descriptor to
    the resolved property's snake display name.
  • Required EXEC argument as snake (EXEC ... @machine_id): the analyzer
    matches required exec args by wire name; resolving them through
    GetParameter / GetParametersIncludingNativeCasing makes required and
    optional exec args uniform.
  • analyzeSchemaVsMap should nil-guard the schema now that a body-less method
    reports nil, nil: an EXEC that supplies a payload to such a method must
    error rather than dereference nil.

🤖 Generated with Claude Code

…tation and columns (#131); hyphenated wire names alias cleanly (#119)

- casing.ToSnake treats '-' as a word boundary, so header names such as
  openai-organization gain a usable snake alias.
- Parameter retry paths (GetParameter, parameterMatch, namespaceParameterMatch,
  GetOperationParameter) resolve a snake key through the declared wire names
  (ToSnake-derived), so acronym-headed names (IPProtocol, BinaryId) round-trip;
  FromSnake stays as a fallback.
- data__ body keys: the revert path maps a snake key to its wire property when
  the method declares nativeCasing, so the default body regime sends wire keys.
- Presentation (SHOW METHODS / SHOW INSERT via RenameRequestBodyAttribute and
  ToPresentationMap) is snake only when the method declares nativeCasing and
  the provider enables snake_case_aliases; resolution keeps every wire spelling.
- A request block without a body schema is no longer an error from
  GetRequestBodySchema, so metadata-only blocks on body-less EXEC methods
  dispatch; the body-attribute accessors keep their error contract.
- Schema.GetProperty / FindByPath accept the snake alias of a wire property
  under snake_case_aliases, wire-first.

All gated on provider config; absent both flags every path is unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant